Skip to:
Content

BuddyPress.org

Ticket #6677: 6677.1.patch

File 6677.1.patch, 107.4 KB (added by dcavins, 3 years ago)

First draft of adding group capability checks.

  • src/bp-activity/bp-activity-screens.php

    diff --git src/bp-activity/bp-activity-screens.php src/bp-activity/bp-activity-screens.php
    index a131548..668b1c1 100644
    function bp_activity_screen_single_activity_permalink() { 
    234234                        return;
    235235                }
    236236
    237                 // Check to see if the group is not public, if so, check the
    238                 // user has access to see this activity.
    239                 if ( $group = groups_get_group( array( 'group_id' => $activity->item_id ) ) ) {
    240 
    241                         // Group is not public.
    242                         if ( 'public' != $group->status ) {
    243 
    244                                 // User is not a member of group.
    245                                 if ( !groups_is_user_member( bp_loggedin_user_id(), $group->id ) ) {
    246                                         $has_access = false;
    247                                 }
     237                // Check to see if the user has access to see this activity.
     238                if ( $group = groups_get_group( array( 'group_id' => $activity->item_id, 'populate_extras' => true ) ) ) {
     239                        if ( ! $group->user_has_access ) {
     240                                $has_access = false;
    248241                        }
    249242                }
    250243        }
  • src/bp-core/bp-core-functions.php

    diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php
    index 6acfb73..056a1ff 100644
    function bp_core_get_table_prefix() { 
    109109 *
    110110 * @since 2.2.0
    111111 *
    112  * @param array      $items The items to be sorted. Its constituent items can be either associative arrays or objects.
    113  * @param string|int $key   The array index or property name to sort by.
    114  * @param string     $type  Sort type. 'alpha' for alphabetical, 'num' for numeric. Default: 'alpha'.
     112 * @param array      $items         The items to be sorted. Its constituent items
     113 *                                  can be either associative arrays or objects.
     114 * @param string|int $key           The array index or property name to sort by.
     115 * @param string     $type          Sort type. 'alpha' for alphabetical, 'num'
     116 *                                  for numeric. Default: 'alpha'.
     117 * @param bool       $preserve_keys Whether to keep the keys or not.
     118 *
    115119 * @return array $items The sorted array.
    116120 */
    117 function bp_sort_by_key( $items, $key, $type = 'alpha' ) {
    118         usort( $items, array( new BP_Core_Sort_By_Key_Callback( $key, $type ), 'sort_callback' ) );
     121function bp_sort_by_key( $items, $key, $type = 'alpha', $preserve_keys = false ) {
     122        if ( true === $preserve_keys ) {
     123                uasort( $items, array( new BP_Core_Sort_By_Key_Callback( $key, $type ), 'sort_callback' ) );
     124        } else {
     125                usort( $items, array( new BP_Core_Sort_By_Key_Callback( $key, $type ), 'sort_callback' ) );
     126        }
    119127
    120128        return $items;
    121129}
  • src/bp-forums/bp-forums-screens.php

    diff --git src/bp-forums/bp-forums-screens.php src/bp-forums/bp-forums-screens.php
    index 7b8a435..76c452c 100644
    function bp_forums_directory_forums_setup() { 
    4545                        $bp->groups->current_group = groups_get_group( array( 'group_id' => $_POST['topic_group_id'] ) );
    4646                        if ( !empty( $bp->groups->current_group->id ) ) {
    4747                                // Auto join this user if they are not yet a member of this group.
    48                                 if ( !bp_current_user_can( 'bp_moderate' ) && 'public' == $bp->groups->current_group->status && !groups_is_user_member( bp_loggedin_user_id(), $bp->groups->current_group->id ) )
     48                                if ( ! bp_current_user_can( 'bp_moderate' ) && 'anyone_can_join' == bp_groups_group_has_cap( $bp->groups->current_group, 'join_method' ) && ! groups_is_user_member( bp_loggedin_user_id(), $bp->groups->current_group->id ) )
    4949                                        groups_join_group( $bp->groups->current_group->id );
    5050
    5151                                $error_message = '';
  • src/bp-groups/bp-groups-actions.php

    diff --git src/bp-groups/bp-groups-actions.php src/bp-groups/bp-groups-actions.php
    index 4a3c510..7d71738 100644
    function bp_groups_group_access_protection() { 
    4141
    4242        $current_group   = groups_get_current_group();
    4343        $user_has_access = $current_group->user_has_access;
     44        $is_visible      = $current_group->is_visible;
    4445        $no_access_args  = array();
    4546
    46         if ( ! $user_has_access && 'hidden' !== $current_group->status ) {
     47        if ( ! $user_has_access && $is_visible ) {
    4748                // Always allow access to home and request-membership.
    4849                if ( bp_is_current_action( 'home' ) || bp_is_current_action( 'request-membership' ) ) {
    4950                        $user_has_access = true;
    function bp_groups_group_access_protection() { 
    9394        // Hidden groups should return a 404 for non-members.
    9495        // Unset the current group so that you're not redirected
    9596        // to the default group tab.
    96         if ( 'hidden' == $current_group->status ) {
     97        if ( ! $is_visible ) {
    9798                buddypress()->groups->current_group = 0;
    9899                buddypress()->is_single_item        = false;
    99100                bp_do_404();
    function groups_action_create_group() { 
    200201                                }
    201202                        }
    202203
    203                         if ( 'private' == $_POST['group-status'] )
    204                                 $group_status = 'private';
    205                         elseif ( 'hidden' == $_POST['group-status'] )
    206                                 $group_status = 'hidden';
     204                        if ( in_array( $_POST['group-status'], bp_groups_get_group_statuses( array(), 'names' ) ) ) {
     205                                $group_status = sanitize_key( $_POST['group-status'] );
     206                        }
    207207
    208208                        if ( !$bp->groups->new_group_id = groups_create_group( array( 'group_id' => $bp->groups->new_group_id, 'status' => $group_status, 'enable_forum' => $group_enable_forum ) ) ) {
    209209                                bp_core_add_message( __( 'There was an error saving group details. Please try again.', 'buddypress' ), 'error' );
    function groups_action_join_group() { 
    395395        if ( !groups_is_user_member( bp_loggedin_user_id(), $bp->groups->current_group->id ) && !groups_is_user_banned( bp_loggedin_user_id(), $bp->groups->current_group->id ) ) {
    396396
    397397                // User wants to join a group that is not public.
    398                 if ( $bp->groups->current_group->status != 'public' ) {
     398                if ( 'anyone_can_join' != bp_groups_group_has_cap( $bp->groups->current_group, 'join_method' ) ) {
    399399                        if ( !groups_check_user_has_invite( bp_loggedin_user_id(), $bp->groups->current_group->id ) ) {
    400400                                bp_core_add_message( __( 'There was an error joining the group.', 'buddypress' ), 'error' );
    401401                                bp_core_redirect( bp_get_group_permalink( $bp->groups->current_group ) );
    function groups_action_leave_group() { 
    462462
    463463                $redirect = bp_get_group_permalink( groups_get_current_group() );
    464464
    465                 if( 'hidden' == $bp->groups->current_group->status ) {
     465                if ( ! bp_groups_group_has_cap( $bp->groups->current_group, 'show_group' ) ) {
    466466                        $redirect = trailingslashit( bp_loggedin_user_domain() . bp_get_groups_slug() );
    467467                }
    468468
    function groups_action_group_feed() { 
    566566        ) );
    567567}
    568568add_action( 'bp_actions', 'groups_action_group_feed' );
     569
     570/**
     571 * Fire the 'bp_groups_register_group_statuses' action.
     572 *
     573 * @since 2.7.0
     574 */
     575function bp_groups_register_group_statuses() {
     576        /**
     577         * Fires when it's appropriate to register group statuses.
     578         *
     579         * @since 2.7.0
     580         */
     581        do_action( 'bp_groups_register_group_statuses' );
     582}
     583add_action( 'bp_loaded', 'bp_groups_register_group_statuses' );
  • src/bp-groups/bp-groups-activity.php

    diff --git src/bp-groups/bp-groups-activity.php src/bp-groups/bp-groups-activity.php
    index 0bf4f29..e99f75a 100644
    function groups_record_activity( $args = '' ) { 
    363363                        $group = groups_get_group( array( 'group_id' => $args['item_id'] ) );
    364364                }
    365365
    366                 if ( isset( $group->status ) && 'public' != $group->status ) {
     366                if ( 'anyone' != bp_groups_group_has_cap( $group, 'access_group' ) ) {
    367367                        $hide_sitewide = true;
    368368                }
    369369        }
  • src/bp-groups/bp-groups-admin.php

    diff --git src/bp-groups/bp-groups-admin.php src/bp-groups/bp-groups-admin.php
    index 5a2a0bf..eae2119 100644
    function bp_groups_admin_load() { 
    265265                 *
    266266                 * @param array $value Array of allowed group statuses.
    267267                 */
    268                 $allowed_status = apply_filters( 'groups_allowed_status', array( 'public', 'private', 'hidden' ) );
     268                $allowed_status = apply_filters( 'groups_allowed_status', bp_groups_get_group_statuses( array(), 'names' ) );
    269269                $status         = ( in_array( $_POST['group-status'], (array) $allowed_status ) ) ? $_POST['group-status'] : 'public';
    270270
    271271                /**
    function bp_groups_admin_index() { 
    794794 */
    795795function bp_groups_admin_edit_metabox_settings( $item ) {
    796796
    797         $invite_status = groups_get_groupmeta( $item->id, 'invite_status' ); ?>
     797        $invite_status    = groups_get_groupmeta( $item->id, 'invite_status' );
     798        $privacy_statuses = bp_groups_get_group_statuses( array(), 'objects' );
     799        ?>
    798800
    799801        <?php if ( bp_is_active( 'forums' ) ) : ?>
    800802                <div class="bp-groups-settings-section" id="bp-groups-settings-section-forum">
    function bp_groups_admin_edit_metabox_settings( $item ) { 
    807809                        <legend><?php _e( 'Privacy', 'buddypress' ); ?></legend>
    808810
    809811                        <ul>
    810                                 <li><input type="radio" name="group-status" id="bp-group-status-public" value="public" <?php checked( $item->status, 'public' ) ?> /><label for="bp-group-status-public"><?php _e( 'Public', 'buddypress' ) ?></label></li>
    811                                 <li><input type="radio" name="group-status" id="bp-group-status-private" value="private" <?php checked( $item->status, 'private' ) ?> /><label for="bp-group-status-private"><?php _e( 'Private', 'buddypress' ) ?></label></li>
    812                                 <li><input type="radio" name="group-status" id="bp-group-status-hidden" value="hidden" <?php checked( $item->status, 'hidden' ) ?> /><label for="bp-group-status-hidden"><?php _e( 'Hidden', 'buddypress' ) ?></label></li>
     812                        <?php foreach ( $privacy_statuses as $status) : ?>
     813                                <li><input type="radio" name="group-status" id="bp-group-status-<?php echo $status->name; ?>" value="<?php echo $status->name; ?>" <?php checked( $item->status, $status->name ); ?> /><label for="bp-group-status-<?php echo $status->name; ?>"><?php echo $status->display_name; ?></label></li>
     814                        <?php endforeach; ?>
    813815                        </ul>
    814816                </fieldset>
    815817        </div>
  • new file src/bp-groups/bp-groups-capabilities.php

    diff --git src/bp-groups/bp-groups-capabilities.php src/bp-groups/bp-groups-capabilities.php
    new file mode 100644
    index 0000000..869a996
    - +  
     1<?php
     2/**
     3 * BuddyPress Groups Capabilities.
     4 *
     5 * @package BuddyPress
     6 * @subpackage GroupsCapabilities
     7 * @since 2.7.0
     8 */
     9
     10/** Group Statuses and Capabilities *******************************************/
     11
     12/**
     13 * Set up base group statuses.
     14 *
     15 * @since 2.7.0
     16 */
     17function bp_groups_register_base_group_statuses() {
     18
     19        $public_group_caps = array(
     20                'join_method'    => 'anyone_can_join',
     21                'show_group'     => 'anyone',
     22                'access_group'   => 'anyone',
     23                'post_in_forum'  => 'anyone',
     24        );
     25        /**
     26         * Filters the basic capabilities of the "public" group status.
     27         *
     28         * @since 2.7.0
     29         *
     30         * @param array $public_group_caps Array of capabilities.
     31         */
     32        $public_group_caps = apply_filters( 'bp_groups_public_group_status_caps', $public_group_caps );
     33
     34        bp_groups_register_group_status( 'public', array(
     35                'display_name'    => _x( 'Public', 'Group status name', 'buddypress' ),
     36                'capabilities'    => $public_group_caps,
     37                'fallback_status' => 'none',
     38                'priority'        => 10,
     39        ) );
     40
     41        $private_group_caps = array(
     42                'join_method'   => 'accepts_membership_requests',
     43                'show_group'    => 'anyone',
     44                'access_group'  => 'member',
     45                'post_in_forum' => 'member',
     46        );
     47        /**
     48         * Filters the basic capabilities of the "public" group status.
     49         *
     50         * @since 2.7.0
     51         *
     52         * @param array $private_group_caps Array of capabilities.
     53         */
     54        $private_group_caps = apply_filters( 'bp_groups_private_group_status_caps', $private_group_caps );
     55
     56        bp_groups_register_group_status( 'private', array(
     57                'display_name'    => _x( 'Private', 'Group status name', 'buddypress' ),
     58                'capabilities'    => $private_group_caps,
     59                'fallback_status' => 'none',
     60                'priority'        => 50,
     61        ) );
     62
     63        $hidden_group_caps = array(
     64                'join_method'   => 'invitation_only',
     65                'show_group'    => array( 'member', 'invited' ), // Invitees must be able to know about hidden groups.
     66                'access_group'  => 'member',
     67                'post_in_forum' => 'member',
     68        );
     69        /**
     70         * Filters the basic capabilities of the "public" group status.
     71         *
     72         * @since 2.7.0
     73         *
     74         * @param array $private_group_caps Array of capabilities.
     75         */
     76        $hidden_group_caps = apply_filters( 'bp_groups_hidden_group_status_caps', $hidden_group_caps );
     77
     78        bp_groups_register_group_status( 'hidden', array(
     79                'display_name'    => _x( 'Hidden', 'Group status name', 'buddypress' ),
     80                'capabilities'    => $hidden_group_caps,
     81                'fallback_status' => 'none',
     82                'priority'        => 90,
     83        ) );
     84}
     85add_action( 'bp_groups_register_group_statuses', 'bp_groups_register_base_group_statuses', 8 );
     86
     87/**
     88 * Register a group status.
     89 *
     90 * @since 2.7.0
     91 *
     92 * @param string $group_status Unique string identifier for the group status.
     93 * @param array  $args {
     94 *     Array of arguments describing the group type.
     95 *
     96 *         @type string $name            Displayed name.
     97 *         @type array  $capabilities    Array of capabilities. See
     98 *                                       `bp_groups_register_base_group_statuses()`
     99 *                                       for commons capability sets.
     100 *         @type string $fallback_status If a capability isn't set, which typical
     101 *                                       status is most similar to the new status?
     102 *                                       Specify 'public', 'private', or 'hidden'.
     103 *         @type int    $priority        Order the capability among the default
     104 *                                       statuses: 'public' has a priority of 10,
     105 *                                       'private' has a priority of 50, and
     106 *                                       'hidden' has a priority of 90.
     107 *
     108 * }
     109 * @return object|WP_Error Group type object on success, WP_Error object on failure.
     110 */
     111function bp_groups_register_group_status( $group_status, $args = array() ) {
     112        $bp = buddypress();
     113
     114        if ( isset( $bp->groups->statuses[ $group_status ] ) ) {
     115                return new WP_Error( 'bp_group_status_exists', __( 'Group status already exists.', 'buddypress' ), $group_status );
     116        }
     117
     118        $r = bp_parse_args( $args, array(
     119                'name'            => $group_status,
     120                'display_name'    => ucfirst( $group_status ),
     121                'capabilities'    => array(),
     122                'fallback_status' => 'public',
     123        ), 'register_group_status' );
     124
     125        $group_status = sanitize_key( $group_status );
     126
     127        /**
     128         * Filters the list of illegal group status names.
     129         *
     130         * - 'any' is a special pseudo-type.
     131         *
     132         * @since 2.7.0
     133         *
     134         * @param array $illegal_names Array of illegal names.
     135         */
     136        $illegal_names = apply_filters( 'bp_group_status_illegal_names', array( 'any' ) );
     137        if ( in_array( $group_status, $illegal_names, true ) ) {
     138                return new WP_Error( 'bp_group_status_illegal_name', __( 'You may not register a group status with this name.', 'buddypress' ), $group_status );
     139        }
     140
     141        // Use the fallback status to fill out the status.
     142        if ( 'none' != $r['fallback_status'] ) {
     143                $fallback_caps = bp_groups_get_group_status_capabilities( $r['fallback_status'] );
     144
     145                if ( $fallback_caps ) {
     146                        $r['capabilities'] = bp_parse_args( $r['capabilities'], $fallback_caps, 'register_group_status_parse_caps' );
     147                }
     148        }
     149
     150        $bp->groups->statuses[ $group_status ] = $status = (object) $r;
     151
     152        /**
     153         * Fires after a group status is registered.
     154         *
     155         * @since 2.7.0
     156         *
     157         * @param string $group_status Group status identifier.
     158         * @param object $status       Group status object.
     159         */
     160        do_action( 'bp_groups_register_group_status', $group_status, $status );
     161
     162        return $status;
     163}
     164
     165/**
     166 * Deregister a group status.
     167 *
     168 * @since 2.7.0
     169 *
     170 * @param string $group_status Unique string identifier for the group status.
     171 *
     172 * @return bool|WP_Error if the group status isn't registered.
     173 */
     174function bp_groups_deregister_group_status( $group_status ) {
     175        $bp = buddypress();
     176        $retval = false;
     177
     178        if ( ! isset( $bp->groups->statuses[ $group_status ] ) ) {
     179                return new WP_Error( 'bp_group_status_does_not_exist', __( 'Group status does not exist.', 'buddypress' ), $group_status );
     180        } else {
     181                $old_status_object = $bp->groups->statuses[ $group_status ];
     182                unset( $bp->groups->statuses[ $group_status ] );
     183                $retval = true;
     184        }
     185
     186        /**
     187         * Fires after a group status is deregistered.
     188         *
     189         * @since 2.7.0
     190         *
     191         * @param string $group_status Group status identifier.
     192         * @param object $status       Removed group status object.
     193         */
     194        do_action( 'bp_groups_deregister_group_status', $group_status, $old_status_object );
     195
     196        return $retval;
     197}
     198
     199/**
     200 * Add a group capability to an existing status.
     201 *
     202 * @since 2.7.0
     203 *
     204 * @param string $status The name of the status to edit.
     205 * @param string $cap    Capability to add.
     206 * @param string $value  New value of the capability.
     207 *
     208 * @return bool True if set, false otherwise.
     209 */
     210function bp_groups_add_group_status_capability( $status, $cap, $value = true ) {
     211        $bp = buddypress();
     212        if ( empty( $status ) || empty( $cap ) || ! isset( $bp->groups->statuses[$status] ) ) {
     213                return false;
     214        }
     215        $cap_name = sanitize_key( $cap );
     216        $bp->groups->statuses[$status]->capabilities[$cap_name] = $value;
     217        return true;
     218}
     219
     220/**
     221 * Edit a group capability for a specific status.
     222 *
     223 * Edit an existing group capability by changing the value.
     224 *
     225 * @since 2.7.0
     226 *
     227 * @param string $status The name of the status to edit.
     228 * @param string $cap    Capability to edit.
     229 * @param string $value  New value of the capability.
     230 *
     231 * @return bool True if set, false otherwise.
     232 */
     233function bp_groups_edit_group_status_capability( $status, $cap, $value = true ) {
     234        $bp = buddypress();
     235        if ( empty( $status )
     236                || empty( $cap )
     237                || ! isset( $bp->groups->statuses[$status] )
     238                || ! isset( $bp->groups->statuses[$status]->capabilities[$cap] ) ) {
     239                return false;
     240        }
     241        $bp->groups->statuses[$status]->capabilities[$cap] = $value;
     242        return true;
     243}
     244
     245/**
     246 * Get a list of all registered group status objects.
     247 *
     248 * @since 2.7.0
     249 *
     250 * @see bp_groups_register_group_status() for accepted arguments.
     251 *
     252 * @param array|string $args     Optional. An array of key => value arguments to match against
     253 *                               the group type objects. Default empty array.
     254 * @param string       $output   Optional. The type of output to return. Accepts 'names'
     255 *                               or 'objects'. Default 'names'.
     256 * @param string       $operator Optional. The logical operation to perform. 'or' means only one
     257 *                               element from the array needs to match; 'and' means all elements
     258 *                               must match. Accepts 'or' or 'and'. Default 'and'.
     259 *
     260 * @return array       $types    A list of groups status names or objects.
     261 */
     262function bp_groups_get_group_statuses( $args = array(), $output = 'names', $operator = 'and' ) {
     263        $statuses = buddypress()->groups->statuses;
     264
     265        $statuses = wp_filter_object_list( $statuses, $args, $operator );
     266
     267        // Sort by status "priority".
     268        $statuses = bp_sort_by_key( $statuses, 'priority', 'num', true );
     269
     270        /**
     271         * Filters the array of group status objects.
     272         *
     273         * This filter is run before the $output filter has been applied, so that
     274         * filtering functions have access to the entire group status objects.
     275         *
     276         * @since 2.6.0
     277         *
     278         * @param array  $statuses  Group status objects, keyed by name.
     279         * @param array  $args      Array of key=>value arguments for filtering.
     280         * @param string $operator  'or' to match any of $args, 'and' to require all.
     281         */
     282        $statuses = apply_filters( 'bp_groups_get_group_statuses', $statuses, $args, $operator );
     283
     284        if ( 'names' === $output ) {
     285                $statuses = wp_list_pluck( $statuses, 'name' );
     286        }
     287
     288        return $statuses;
     289}
     290
     291/**
     292 * Retrieve a group status object by name.
     293 *
     294 * @since 2.7.0
     295 *
     296 * @param string $group_status The name of the group status.
     297 *
     298 * @return object A group status object.
     299 */
     300function bp_groups_get_group_status_object( $group_status ) {
     301        $statuses = bp_groups_get_group_statuses( array(), 'objects' );
     302
     303        if ( empty( $statuses[ $group_status ] ) ) {
     304                return null;
     305        }
     306
     307        return $statuses[ $group_status ];
     308}
     309
     310/**
     311 * Retrieve a group status object's capabilities by the status name.
     312 *
     313 * @since 2.7.0
     314 *
     315 * @param string $group_status The name of the group status.
     316 *
     317 * @return array The capabilities array of the group status object.
     318 */
     319function bp_groups_get_group_status_capabilities( $group_status ) {
     320
     321        $status = bp_groups_get_group_status_object( $group_status );
     322
     323        if ( empty( $status->capabilities ) ) {
     324                return null;
     325        }
     326
     327        return $status->capabilities;
     328}
     329
     330/**
     331 * Add a group capability to an existing status.
     332 *
     333 * Edit an existing group capability by changing the value.
     334 *
     335 * @since 2.7.0
     336 *
     337 * @param string $status The name of the status to edit.
     338 * @param string $cap    Capability to edit.
     339 * @param string $value  New value of the capability.
     340 *
     341 * @return array $capabilities Capabilities array for specified group.
     342 */
     343function bp_groups_get_group_capabilities( $group ) {
     344        // Have the group's capabilities been populated?
     345        if ( is_object( $group ) && ! isset( $group->capabilities ) ) {
     346                $group = groups_get_group( array( 'group_id' => $group->id, 'populate_extras' => true ) );
     347        } elseif ( is_int( $group ) ) {
     348                $group = groups_get_group( array( 'group_id' => (int) $group, 'populate_extras' => true ) );
     349        }
     350
     351        if ( ! isset( $group->capabilities ) ) {
     352                return false;
     353        }
     354
     355        if ( ! empty( $group->capabilities ) ) {
     356                return $group->capabilities;
     357        } else {
     358                return false;
     359        }
     360}
     361
     362/**
     363 * Check whether a group status has a value for a capability.
     364 *
     365 * If the capability has a non-falsey value, it is returned, so this funciton
     366 * can be used to check and fetch capability values. To check the capabilities
     367 * of a specific group, use `bp_groups_group_has_cap()` below.
     368 *
     369 * @since 2.7.0
     370 *
     371 * @param string $status The name of the status to check.
     372 * @param string $cap    Capability to check.
     373 *
     374 * @return mixed|bool Returns the value stored for the capability if set, false otherwise.
     375 */
     376function bp_groups_group_status_has_cap( $status, $cap ) {
     377        $bp = buddypress();
     378
     379        if ( ! isset( $bp->groups->statuses[$status] ) || ! isset( $bp->groups->statuses[$status]->capabilities ) ) {
     380                return false;
     381        }
     382
     383        /**
     384         * Filter which capabilities are associated with a group status.
     385         *
     386         * @since 2.7.0
     387         *
     388         * @param array  $capabilities Array of capabilities for this status.
     389         * @param string $status       Status name.
     390         * @param string $cap          Capability name.
     391         */
     392        $capabilities = apply_filters( 'bp_groups_group_status_has_cap', $bp->groups->statuses[$status]->capabilities, $status, $cap );
     393
     394        if ( ! empty( $capabilities[$cap] ) ) {
     395                return $capabilities[$cap];
     396        } else {
     397                return false;
     398        }
     399}
     400
     401/**
     402 * Check whether a group has a value for a capability.
     403 *
     404 * If the capability has a non-falsey value, it is returned, so this funciton
     405 * can be used to check and fetch capability values. To check the capabilities
     406 * of a status generally, use `bp_groups_group_status_has_cap()` above.
     407 * To filter a particular group's capabilities, use the
     408 * `bp_groups_group_object_set_caps` filter hook.
     409 *
     410 * @since 2.7.0
     411 *
     412 * @param object|int $group Group object or id of the group to check.
     413 * @param string     $cap   Capability to check.
     414 *
     415 * @return mixed|bool Returns the value stored for the capability if set, false otherwise.
     416 */
     417function bp_groups_group_has_cap( $group, $cap ) {
     418        // Have the group's capabilities been populated?
     419        if ( is_object( $group ) && ! isset( $group->capabilities ) ) {
     420                $group = groups_get_group( array( 'group_id' => $group->id, 'populate_extras' => true ) );
     421        } elseif ( is_int( $group ) ) {
     422                $group = groups_get_group( array( 'group_id' => (int) $group, 'populate_extras' => true ) );
     423        }
     424
     425        if ( ! isset( $group->capabilities ) ) {
     426                return false;
     427        }
     428
     429        if ( ! empty( $group->capabilities[$cap] ) ) {
     430                return $group->capabilities[$cap];
     431        } else {
     432                return false;
     433        }
     434}
     435
     436/**
     437 * User-friendly descriptions for each group capability.
     438 *
     439 * Used on the group settings and create screens to describe the capabilities
     440 * of each group status.
     441 *
     442 * @since 2.7.0
     443 *
     444 * @param string $cap   Capability to check.
     445 * @param mixed  $value The value of the capability we'd like to describe.
     446 *
     447 * @return mixed|bool Returns the value stored for the capability if set, false otherwise.
     448 */
     449function bp_groups_group_capabilities_description( $cap, $value ) {
     450        $retval = '';
     451
     452        switch ( $cap ) {
     453                case 'join_method':
     454                        if ( 'anyone_can_join' == $value ) {
     455                                $retval = __( 'Any site member can join this group.', 'buddypress' );
     456                        } elseif ( 'accepts_membership_requests' == $value ) {
     457                                $retval = __( 'Only users who request membership and are accepted can join the group.', 'buddypress' );
     458                        } elseif ( 'invitation_only' == $value ) {
     459                                $retval = __( 'Only users who are invited can join the group.', 'buddypress' );
     460                        }
     461                        break;
     462                case 'show_group' :
     463                        // @TODO: This could be an array of options.
     464                        if ( 'anyone' == $value ) {
     465                                $retval = __( 'This group will be listed in the groups directory and in search results.', 'buddypress' );
     466                        } else {
     467                                $retval = __( 'This group will not be listed in the groups directory or search results.', 'buddypress' );
     468                        }
     469                        break;
     470                case 'access_group' :
     471                        // @TODO: This could be an array of options.
     472                        if ( 'anyone' == $value ) {
     473                                $retval = __( 'Group content and activity will be visible to any visitor to the site.', 'buddypress' );
     474                        } elseif ( 'loggedin' == $value ) {
     475                                $retval = __( 'Group content and activity will be visible to any site member.', 'buddypress' );
     476                        } else {
     477                                $retval = __( 'Group content and activity will only be visible to members of the group.', 'buddypress' );
     478                        }
     479                        break;
     480                default:
     481                        /**
     482                         * Provide the group capability description for custom capabilities.
     483                         *
     484                         * @since 2.7.0
     485                         *
     486                         * @param string $retval The description of the capability and value combination.
     487                         * @param string $cap    Capability name.
     488                         * @param string $name   Value for the capability.
     489                         */
     490                        $retval = apply_filters( 'bp_groups_group_custom_capabilities_description', $retval, $cap, $value );
     491                        break;
     492        }
     493
     494        return $retval;
     495}
     496
     497/**
     498 * Check whether a user meets an access condition for a group.
     499 *
     500 * Used to calculate whether the group is visible and accessible to the user.
     501 *
     502 * @since 2.7.0
     503 *
     504 * @param string $access_condition 'anyone', 'loggedin', 'member',
     505 *                                 'mod', 'admin', or 'noone'.
     506 *                                 Defaults to the current group.
     507 * @param int    $group_id         Optional. ID of the group to check.
     508 * @param int    $user_id          Optional. ID of the user to check.
     509 *                                 Defaults to the current user.
     510 *
     511 * @return bool
     512 */
     513function bp_groups_user_meets_access_condition( $access_condition, $group_id = 0, $user_id = 0 ) {
     514        if ( ! $group_id ) {
     515                $group_id = bp_get_current_group_id();
     516        }
     517        if ( ! $group_id ) {
     518                return false;
     519        }
     520        if ( ! $user_id ) {
     521                $user_id = bp_loggedin_user_id();
     522        }
     523
     524        switch ( $access_condition ) {
     525                case 'admin' :
     526                        $meets_condition = groups_is_user_admin( $user_id, $group_id );
     527                        break;
     528
     529                case 'mod' :
     530                        $meets_condition = groups_is_user_mod( $user_id, $group_id );
     531                        break;
     532
     533                case 'member' :
     534                        $meets_condition = groups_is_user_member( $user_id, $group_id );
     535                        break;
     536
     537                case 'invited' :
     538                        $meets_condition = groups_check_user_has_invite( $user_id, $group_id );
     539                        break;
     540
     541                case 'loggedin' :
     542                        $meets_condition = is_user_logged_in();
     543                        break;
     544
     545                case 'noone' :
     546                        $meets_condition = false;
     547                        break;
     548
     549                case 'anyone' :
     550                default :
     551                        $meets_condition = true;
     552                        break;
     553        }
     554
     555        return (bool) $meets_condition;
     556}
     557
     558/**
     559 * Reset the 'last_changed' cache incrementor when groups are updated.
     560 *
     561 * @since 2.7.0
     562 */
     563function bp_groups_cache_invalidate_last_changed_incrementor() {
     564        wp_cache_delete( 'last_changed', 'bp_groups' );
     565}
     566// @TODO: This is updated on every group creation, deletion, setting update, and membership change.
     567// Is this a bad caching strategy?
     568add_action( 'groups_created_group', 'bp_groups_cache_invalidate_last_changed_incrementor' );
     569add_action( 'groups_settings_updated', 'bp_groups_cache_invalidate_last_changed_incrementor' );
     570add_action( 'groups_delete_group', 'bp_groups_cache_invalidate_last_changed_incrementor' );
     571add_action( 'groups_join_group', 'bp_groups_cache_invalidate_last_changed_incrementor' );
     572add_action( 'groups_leave_group', 'bp_groups_cache_invalidate_last_changed_incrementor' );
     573add_action( 'groups_invite_user', 'bp_groups_cache_invalidate_last_changed_incrementor' );
     574add_action( 'groups_uninvite_user', 'bp_groups_cache_invalidate_last_changed_incrementor' );
     575add_action( 'groups_accept_invite', 'bp_groups_cache_invalidate_last_changed_incrementor' );
     576add_action( 'groups_reject_invite', 'bp_groups_cache_invalidate_last_changed_incrementor' );
     577// More, too. Promotions, etc.
     578
  • src/bp-groups/bp-groups-filters.php

    diff --git src/bp-groups/bp-groups-filters.php src/bp-groups/bp-groups-filters.php
    index 4aefa10..ac28c83 100644
    function bp_groups_disable_at_mention_notification_for_non_public_groups( $send, 
    316316
    317317        if ( 'groups' === $activity->component ) {
    318318                $group = groups_get_group( array( 'group_id' => $activity->item_id ) );
    319                 if ( 'public' !== $group->status && ! groups_is_user_member( $user_id, $group->id ) ) {
     319                if ( 'anyone' != bp_groups_group_has_cap( $group, 'access_group' ) && ! groups_is_user_member( $user_id, $group->id ) ) {
    320320                        $send = false;
    321321                }
    322322        }
  • src/bp-groups/bp-groups-functions.php

    diff --git src/bp-groups/bp-groups-functions.php src/bp-groups/bp-groups-functions.php
    index cb0753e..c793b6a 100644
    function groups_get_group( $args = '' ) { 
    8686 *     @type string   $description  Optional. The group's description.
    8787 *     @type string   $slug         The group slug.
    8888 *     @type string   $status       The group's status. Accepts 'public', 'private' or
    89  *                                  'hidden'. Defaults to 'public'.
     89 *                                  'hidden' or registered statuses. Defaults to 'public'.
    9090 *     @type int      $enable_forum Optional. Whether the group has a forum enabled.
    9191 *                                  If the legacy forums are enabled for this group
    9292 *                                  or if a bbPress forum is enabled for the group,
    function groups_edit_base_group_details( $group_id, $group_name, $group_desc, $n 
    272272 */
    273273function groups_edit_group_settings( $group_id, $enable_forum, $status, $invite_status = false ) {
    274274
    275         $group = groups_get_group( array( 'group_id' => $group_id ) );
     275        $group = groups_get_group( array( 'group_id' => $group_id, 'populate_extras' => true ) );
    276276        $group->enable_forum = $enable_forum;
    277277
    278278        /**
    279          * Before we potentially switch the group status, if it has been changed to public
    280          * from private and there are outstanding membership requests, auto-accept those requests.
     279         * Before we potentially switch the group status, if the old status required membership requests,
     280         * but the new status allows anyone to join, auto-accept those requests.
    281281         */
    282         if ( 'private' == $group->status && 'public' == $status )
     282        if (
     283                // Group membership is currently "by request"...
     284                'accepts_membership_requests' == bp_groups_group_has_cap( $group, 'join_method' )
     285                // and the group is changing to a status that allows open membership.
     286                && 'anyone_can_join' == bp_groups_group_status_has_cap( $status, $cap )
     287                )
     288        {
    283289                groups_accept_all_pending_membership_requests( $group->id );
     290        }
    284291
    285292        // Now update the status.
    286293        $group->status = $status;
    287294
    288         if ( !$group->save() )
     295        if ( ! $group->save() )
    289296                return false;
    290297
    291298        // If forums have been enabled, and a forum does not yet exist, we need to create one.
    function groups_edit_group_settings( $group_id, $enable_forum, $status, $invite_ 
    296303        }
    297304
    298305        // Set the invite status.
    299         if ( $invite_status )
     306        if ( $invite_status ) {
    300307                groups_update_groupmeta( $group->id, 'invite_status', $invite_status );
     308        }
    301309
    302310        groups_update_groupmeta( $group->id, 'last_activity', bp_core_current_time() );
    303311
  • src/bp-groups/bp-groups-screens.php

    diff --git src/bp-groups/bp-groups-screens.php src/bp-groups/bp-groups-screens.php
    index cbbc758..d248805 100644
    function groups_screen_group_forum() { 
    214214                        check_admin_referer( 'bp_forums_new_reply' );
    215215
    216216                        // Auto join this user if they are not yet a member of this group.
    217                         if ( bp_groups_auto_join() && !bp_current_user_can( 'bp_moderate' ) && 'public' == $bp->groups->current_group->status && !groups_is_user_member( bp_loggedin_user_id(), $bp->groups->current_group->id ) ) {
     217                        if ( bp_groups_auto_join() && !bp_current_user_can( 'bp_moderate' ) && 'anyone_can_join' == bp_groups_group_has_cap( $bp->groups->current_group, 'join_method' ) && !groups_is_user_member( bp_loggedin_user_id(), $bp->groups->current_group->id ) ) {
    218218                                groups_join_group( $bp->groups->current_group->id, bp_loggedin_user_id() );
    219219                        }
    220220
    function groups_screen_group_forum() { 
    521521                        if ( $user_is_banned ) {
    522522                                $error_message = __( "You have been banned from this group.", 'buddypress' );
    523523
    524                         } elseif ( bp_groups_auto_join() && !bp_current_user_can( 'bp_moderate' ) && 'public' == $bp->groups->current_group->status && !groups_is_user_member( bp_loggedin_user_id(), $bp->groups->current_group->id ) ) {
     524                        } elseif ( bp_groups_auto_join() && !bp_current_user_can( 'bp_moderate' ) && 'anyone_can_join' == bp_groups_group_has_cap( $bp->groups->current_group, 'join_method' ) && !groups_is_user_member( bp_loggedin_user_id(), $bp->groups->current_group->id ) ) {
    525525                                // Auto join this user if they are not yet a member of this group.
    526526                                groups_join_group( $bp->groups->current_group->id, bp_loggedin_user_id() );
    527527                        }
    function groups_screen_group_request_membership() { 
    715715
    716716        $bp = buddypress();
    717717
    718         if ( 'private' != $bp->groups->current_group->status )
     718        if ( 'accepts_membership_requests' != bp_groups_group_has_cap( $bp->groups->current_group, 'join_method' ) )
    719719                return false;
    720720
    721721        // If the user is already invited, accept invitation.
    function groups_screen_group_admin_settings() { 
    903903
    904904                // Checked against a whitelist for security.
    905905                /** This filter is documented in bp-groups/bp-groups-admin.php */
    906                 $allowed_status = apply_filters( 'groups_allowed_status', array( 'public', 'private', 'hidden' ) );
     906                $allowed_status = apply_filters( 'groups_allowed_status', bp_groups_get_group_statuses( array(), 'names' ) );
    907907                $status         = ( in_array( $_POST['group-status'], (array) $allowed_status ) ) ? $_POST['group-status'] : 'public';
    908908
    909909                // Checked against a whitelist for security.
    function groups_screen_group_admin_requests() { 
    12691269                return false;
    12701270        }
    12711271
    1272         if ( ! bp_is_item_admin() || ( 'public' == $bp->groups->current_group->status ) ) {
     1272        if ( ! bp_is_item_admin() || 'accepts_membership_requests' != bp_groups_group_has_cap( groups_get_current_group(), 'join_method' ) ) {
    12731273                return false;
    12741274        }
    12751275
  • src/bp-groups/bp-groups-template.php

    diff --git src/bp-groups/bp-groups-template.php src/bp-groups/bp-groups-template.php
    index f08fea5..0a59e85 100644
    function bp_group_is_visible( $group = false ) { 
    280280                $group =& $groups_template->group;
    281281        }
    282282
    283         if ( 'public' == $group->status ) {
     283        if ( $group->is_visible ) {
    284284                return true;
    285         } else {
    286                 if ( groups_is_user_member( bp_loggedin_user_id(), $group->id ) ) {
    287                         return true;
    288                 }
    289285        }
    290286
    291287        return false;
    function bp_get_group_type( $group = false ) { 
    470466                $group =& $groups_template->group;
    471467        }
    472468
    473         if ( 'public' == $group->status ) {
    474                 $type = __( "Public Group", 'buddypress' );
    475         } elseif ( 'hidden' == $group->status ) {
    476                 $type = __( "Hidden Group", 'buddypress' );
    477         } elseif ( 'private' == $group->status ) {
    478                 $type = __( "Private Group", 'buddypress' );
     469        $status_obj = bp_groups_get_group_status_object( $group->status );
     470        if ( ! empty( $status_obj->display_name ) ) {
     471                $type = $status_obj->display_name . ' ' . __( 'Group', 'buddypress' );
    479472        } else {
    480473                $type = ucwords( $group->status ) . ' ' . __( 'Group', 'buddypress' );
    481474        }
    function bp_group_status( $group = false ) { 
    529522                 */
    530523                return apply_filters( 'bp_get_group_status', $group->status, $group );
    531524        }
    532 
    533525/**
    534526 * Output the group avatar while in the groups loop.
    535527 *
    function bp_group_admin_tabs( $group = false ) { 
    26052597        }
    26062598
    26072599        $css_id = 'manage-members';
    2608 
    2609         if ( 'private' == $group->status ) {
     2600        if ( 'accepts_membership_requests' == bp_groups_group_has_cap( $group, 'join_method' ) ) {
    26102601                $css_id = 'membership-requests';
    26112602        }
    26122603
    function bp_group_join_button( $group = false ) { 
    32023193                        $group =& $groups_template->group;
    32033194                }
    32043195
     3196                var_dump( $group );
     3197
    32053198                // Don't show button if not logged in or previously banned.
    32063199                if ( ! is_user_logged_in() || bp_group_is_user_banned( $group ) ) {
    32073200                        return false;
    function bp_group_join_button( $group = false ) { 
    32363229
    32373230                // Not a member.
    32383231                } else {
     3232                        // Show different buttons based on group capabilities.
     3233                                                        // Member has outstanding invitation -
     3234                                // show an "Accept Invitation" button.
     3235                        if ( $group->is_invited ) {
     3236                                $button = array(
     3237                                        'id'                => 'accept_invite',
     3238                                        'component'         => 'groups',
     3239                                        'must_be_logged_in' => true,
     3240                                        'block_self'        => false,
     3241                                        'wrapper_class'     => 'group-button ' . $group->status,
     3242                                        'wrapper_id'        => 'groupbutton-' . $group->id,
     3243                                        'link_href'         => add_query_arg( 'redirect_to', bp_get_group_permalink( $group ), bp_get_group_accept_invite_link( $group ) ),
     3244                                        'link_text'         => __( 'Accept Invitation', 'buddypress' ),
     3245                                        'link_class'        => 'group-button accept-invite',
     3246                                );
     3247                        } elseif ( 'anyone_can_join' == bp_groups_group_has_cap( $group, 'join_method' ) ) {
     3248                                $button = array(
     3249                                        'id'                => 'join_group',
     3250                                        'component'         => 'groups',
     3251                                        'must_be_logged_in' => true,
     3252                                        'block_self'        => false,
     3253                                        'wrapper_class'     => 'group-button ' . $group->status,
     3254                                        'wrapper_id'        => 'groupbutton-' . $group->id,
     3255                                        'link_href'         => wp_nonce_url( bp_get_group_permalink( $group ) . 'join', 'groups_join_group' ),
     3256                                        'link_text'         => __( 'Join Group', 'buddypress' ),
     3257                                        'link_class'        => 'group-button join-group',
     3258                                );
     3259                        } elseif ( 'accepts_membership_requests' == bp_groups_group_has_cap( $group, 'join_method' ) ) {
     3260
     3261                                // Member has requested membership but request is pending -
     3262                                // show a "Request Sent" button.
     3263                                if ( $group->is_pending ) {
     3264                                        $button = array(
     3265                                                'id'                => 'membership_requested',
     3266                                                'component'         => 'groups',
     3267                                                'must_be_logged_in' => true,
     3268                                                'block_self'        => false,
     3269                                                'wrapper_class'     => 'group-button pending ' . $group->status,
     3270                                                'wrapper_id'        => 'groupbutton-' . $group->id,
     3271                                                'link_href'         => bp_get_group_permalink( $group ),
     3272                                                'link_text'         => __( 'Request Sent', 'buddypress' ),
     3273                                                'link_class'        => 'group-button pending membership-requested',
     3274                                        );
    32393275
    3240                         // Show different buttons based on group status.
    3241                         switch ( $group->status ) {
    3242                                 case 'hidden' :
    3243                                         return false;
    3244 
    3245                                 case 'public':
     3276                                // Member has not requested membership yet -
     3277                                // show a "Request Membership" button.
     3278                                } else {
    32463279                                        $button = array(
    3247                                                 'id'                => 'join_group',
     3280                                                'id'                => 'request_membership',
    32483281                                                'component'         => 'groups',
    32493282                                                'must_be_logged_in' => true,
    32503283                                                'block_self'        => false,
    32513284                                                'wrapper_class'     => 'group-button ' . $group->status,
    32523285                                                'wrapper_id'        => 'groupbutton-' . $group->id,
    3253                                                 'link_href'         => wp_nonce_url( bp_get_group_permalink( $group ) . 'join', 'groups_join_group' ),
    3254                                                 'link_text'         => __( 'Join Group', 'buddypress' ),
    3255                                                 'link_class'        => 'group-button join-group',
     3286                                                'link_href'         => wp_nonce_url( bp_get_group_permalink( $group ) . 'request-membership', 'groups_request_membership' ),
     3287                                                'link_text'         => __( 'Request Membership', 'buddypress' ),
     3288                                                'link_class'        => 'group-button request-membership',
    32563289                                        );
    3257                                         break;
    3258 
    3259                                 case 'private' :
    3260 
    3261                                         // Member has outstanding invitation -
    3262                                         // show an "Accept Invitation" button.
    3263                                         if ( $group->is_invited ) {
    3264                                                 $button = array(
    3265                                                         'id'                => 'accept_invite',
    3266                                                         'component'         => 'groups',
    3267                                                         'must_be_logged_in' => true,
    3268                                                         'block_self'        => false,
    3269                                                         'wrapper_class'     => 'group-button ' . $group->status,
    3270                                                         'wrapper_id'        => 'groupbutton-' . $group->id,
    3271                                                         'link_href'         => add_query_arg( 'redirect_to', bp_get_group_permalink( $group ), bp_get_group_accept_invite_link( $group ) ),
    3272                                                         'link_text'         => __( 'Accept Invitation', 'buddypress' ),
    3273                                                         'link_class'        => 'group-button accept-invite',
    3274                                                 );
    3275 
    3276                                         // Member has requested membership but request is pending -
    3277                                         // show a "Request Sent" button.
    3278                                         } elseif ( $group->is_pending ) {
    3279                                                 $button = array(
    3280                                                         'id'                => 'membership_requested',
    3281                                                         'component'         => 'groups',
    3282                                                         'must_be_logged_in' => true,
    3283                                                         'block_self'        => false,
    3284                                                         'wrapper_class'     => 'group-button pending ' . $group->status,
    3285                                                         'wrapper_id'        => 'groupbutton-' . $group->id,
    3286                                                         'link_href'         => bp_get_group_permalink( $group ),
    3287                                                         'link_text'         => __( 'Request Sent', 'buddypress' ),
    3288                                                         'link_class'        => 'group-button pending membership-requested',
    3289                                                 );
    3290 
    3291                                         // Member has not requested membership yet -
    3292                                         // show a "Request Membership" button.
    3293                                         } else {
    3294                                                 $button = array(
    3295                                                         'id'                => 'request_membership',
    3296                                                         'component'         => 'groups',
    3297                                                         'must_be_logged_in' => true,
    3298                                                         'block_self'        => false,
    3299                                                         'wrapper_class'     => 'group-button ' . $group->status,
    3300                                                         'wrapper_id'        => 'groupbutton-' . $group->id,
    3301                                                         'link_href'         => wp_nonce_url( bp_get_group_permalink( $group ) . 'request-membership', 'groups_request_membership' ),
    3302                                                         'link_text'         => __( 'Request Membership', 'buddypress' ),
    3303                                                         'link_class'        => 'group-button request-membership',
    3304                                                 );
    3305                                         }
    3306 
    3307                                         break;
     3290                                }
    33083291                        }
    33093292                }
    33103293
    function bp_group_status_message( $group = null ) { 
    34483431
    34493432        // Group has a status.
    34503433        } else {
    3451                 switch( $group->status ) {
    3452 
    3453                         // Private group.
    3454                         case 'private' :
    3455                                 if ( ! bp_group_has_requested_membership( $group ) ) {
    3456                                         if ( is_user_logged_in() ) {
    3457                                                 if ( bp_group_is_invited( $group ) ) {
    3458                                                         $message = __( 'You must accept your pending invitation before you can access this private group.', 'buddypress' );
    3459                                                 } else {
    3460                                                         $message = __( 'This is a private group and you must request group membership in order to join.', 'buddypress' );
    3461                                                 }
     3434                if ( 'accepts_membership_requests' == bp_groups_group_has_cap( $group, 'join_method' ) ) {
     3435                        if ( ! bp_group_has_requested_membership( $group ) ) {
     3436                                if ( is_user_logged_in() ) {
     3437                                        if ( bp_group_is_invited( $group ) ) {
     3438                                                $message = __( 'You must accept your pending invitation before you can access this private group.', 'buddypress' );
    34623439                                        } else {
    3463                                                 $message = __( 'This is a private group. To join you must be a registered site member and request group membership.', 'buddypress' );
     3440                                                $message = __( 'This is a private group and you must request group membership in order to join.', 'buddypress' );
    34643441                                        }
    34653442                                } else {
    3466                                         $message = __( 'This is a private group. Your membership request is awaiting approval from the group administrator.', 'buddypress' );
     3443                                        $message = __( 'This is a private group. To join you must be a registered site member and request group membership.', 'buddypress' );
    34673444                                }
     3445                        } else {
     3446                                $message = __( 'This is a private group. Your membership request is awaiting approval from the group administrator.', 'buddypress' );
     3447                        }
    34683448
    3469                                 break;
    3470 
    3471                         // Hidden group.
    3472                         case 'hidden' :
    3473                         default :
    3474                                 $message = __( 'This is a hidden group and only invited members can join.', 'buddypress' );
    3475                                 break;
     3449                } elseif ( 'invitation_only' == bp_groups_group_has_cap( $group, 'join_method' ) ) {
     3450                        // This group neither accepts requests nor allows open membership.
     3451                        $message = __( 'This is a hidden group and only invited members can join.', 'buddypress' );
    34763452                }
    34773453        }
    34783454
  • src/bp-groups/classes/class-bp-group-extension.php

    diff --git src/bp-groups/classes/class-bp-group-extension.php src/bp-groups/classes/class-bp-group-extension.php
    index d6cf777..5bbdbe4 100644
    class BP_Group_Extension { 
    586586                                $group = groups_get_group( array(
    587587                                        'group_id' => $this->group_id,
    588588                                ) );
    589 
    590                                 if ( ! empty( $group->status ) && 'public' === $group->status ) {
     589                                if ( 'anyone' != bp_groups_group_has_cap( $group, 'access_group' ) ) {
    591590                                        // Tabs in public groups are accessible to anyone by default.
    592591                                        $this->params['access'] = 'anyone';
    593592                                } else {
  • src/bp-groups/classes/class-bp-groups-component.php

    diff --git src/bp-groups/classes/class-bp-groups-component.php src/bp-groups/classes/class-bp-groups-component.php
    index 93bb9b7..23bfbbc 100644
    class BP_Groups_Component extends BP_Component { 
    8585        public $types = array();
    8686
    8787        /**
     88         * Group statuses.
     89         *
     90         * @see bp_groups_register_group_status()
     91         *
     92         * @since 2.7.0
     93         * @var array
     94         */
     95        public $statuses = array();
     96
     97        /**
    8898         * Start the groups component creation process.
    8999         *
    90100         * @since 1.5.0
    class BP_Groups_Component extends BP_Component { 
    122132                        'template',
    123133                        'adminbar',
    124134                        'functions',
    125                         'notifications'
     135                        'notifications',
     136                        'capabilities'
    126137                );
    127138
    128139                if ( ! buddypress()->do_autoload ) {
    class BP_Groups_Component extends BP_Component { 
    232243
    233244                        // If the user is not an admin, check if they are a moderator.
    234245                        if ( ! bp_is_item_admin() ) {
    235                                 bp_update_is_item_mod  ( groups_is_user_mod  ( bp_loggedin_user_id(), $this->current_group->id ), 'groups' );
     246                                bp_update_is_item_mod  ( groups_is_user_mod( bp_loggedin_user_id(), $this->current_group->id ), 'groups' );
    236247                        }
    237248
    238249                        // Is the logged in user a member of the group?
    class BP_Groups_Component extends BP_Component { 
    242253                                $this->current_group->is_user_member = false;
    243254                        }
    244255
    245                         // Should this group be visible to the logged in user?
    246                         if ( 'public' == $this->current_group->status || $this->current_group->is_user_member ) {
     256                        // Set group visibility and access.
     257                        if ( bp_current_user_can( 'bp_moderate' ) ) {
    247258                                $this->current_group->is_visible = true;
     259                                $this->current_group->user_has_access = true;
    248260                        } else {
     261                                // Should this group be visible to the current user?
    249262                                $this->current_group->is_visible = false;
    250                         }
    251263
    252                         // If this is a private or hidden group, does the user have access?
    253                         if ( 'private' == $this->current_group->status || 'hidden' == $this->current_group->status ) {
    254                                 if ( $this->current_group->is_user_member && is_user_logged_in() || bp_current_user_can( 'bp_moderate' ) ) {
    255                                         $this->current_group->user_has_access = true;
    256                                 } else {
    257                                         $this->current_group->user_has_access = false;
     264                                // Parse multiple visibility conditions into an array.
     265                                $access_conditions = $this->current_group->capabilities['show_group'];
     266                                if ( ! is_array( $access_conditions ) ) {
     267                                        $access_conditions = explode( ',', $access_conditions );
     268                                }
     269
     270                                // If the current user meets at least one condition,
     271                                // allow visibility.
     272                                foreach ( $access_conditions as $access_condition ) {
     273                                        if ( bp_groups_user_meets_access_condition( $access_condition, $this->current_group->id ) ) {
     274                                                $this->current_group->is_visible = true;
     275                                                break;
     276                                        }
     277                                }
     278
     279                                // Should the user have access to this group?
     280                                $this->current_group->user_has_access = false;
     281
     282                                // Parse multiple visibility conditions into an array.
     283                                $access_conditions = $this->current_group->capabilities['access_group'];
     284                                if ( ! is_array( $access_conditions ) ) {
     285                                        $access_conditions = explode( ',', $access_conditions );
     286                                }
     287
     288                                // If the current user meets at least one condition,
     289                                // allow access.
     290                                foreach ( $access_conditions as $access_condition ) {
     291                                        if ( bp_groups_user_meets_access_condition( $access_condition, $this->current_group->id ) ) {
     292                                                $this->current_group->user_has_access = true;
     293                                                break;
     294                                        }
    258295                                }
    259                         } else {
    260                                 $this->current_group->user_has_access = true;
    261296                        }
    262297
     298
    263299                        // Check once if the current group has a custom front template.
    264300                        $this->current_group->front_template = bp_groups_get_front_template( $this->current_group );
    265301
    class BP_Groups_Component extends BP_Component { 
    350386                 *
    351387                 * @param array $value Array of valid group statuses.
    352388                 */
    353                 $this->valid_status = apply_filters( 'groups_valid_status', array(
    354                         'public',
    355                         'private',
    356                         'hidden'
    357                 ) );
     389                $this->valid_status = apply_filters( 'groups_valid_status', bp_groups_get_group_statuses() );
    358390
    359391                // Auto join group when non group member performs group activity.
    360392                $this->auto_join = defined( 'BP_DISABLE_AUTO_GROUP_JOIN' ) && BP_DISABLE_AUTO_GROUP_JOIN ? false : true;
    class BP_Groups_Component extends BP_Component { 
    541573                        if ( is_user_logged_in() &&
    542574                                 ! $this->current_group->is_user_member &&
    543575                                 ! groups_check_for_membership_request( bp_loggedin_user_id(), $this->current_group->id ) &&
    544                                  $this->current_group->status == 'private' &&
     576                                 'accepts_membership_requests' == bp_groups_group_has_cap( $this->current_group, 'join_method' ) &&
    545577                                 ! groups_check_user_has_invite( bp_loggedin_user_id(), $this->current_group->id )
    546578                                ) {
    547579
    class BP_Groups_Component extends BP_Component { 
    676708                                        'position' => 30,
    677709                                ), $default_params );
    678710
    679                                 if ( 'private' == $this->current_group->status ) {
     711                                if ( 'accepts_membership_requests' == bp_groups_group_has_cap( $this->current_group, 'join_method' ) ) {
    680712                                        $sub_nav[] = array_merge( array(
    681713                                                'name'     => __( 'Requests', 'buddypress' ),
    682714                                                'slug'     => 'membership-requests',
  • src/bp-groups/classes/class-bp-groups-group.php

    diff --git src/bp-groups/classes/class-bp-groups-group.php src/bp-groups/classes/class-bp-groups-group.php
    index bde4f1e..fda6852 100644
    class BP_Groups_Group { 
    6868        public $status;
    6969
    7070        /**
     71         * Group capabilities.
     72         *
     73         * @since 2.7.0
     74         * @var array
     75         */
     76        public $capabilities;
     77
     78        /**
    7179         * Should (legacy) bbPress forums be enabled for this group?
    7280         *
    7381         * @since 1.6.0
    class BP_Groups_Group { 
    140148        public $last_activity;
    141149
    142150        /**
    143          * If this is a private or hidden group, does the current user have access?
     151         * Should the current user have access?
    144152         *
    145153         * @since 1.6.0
    146154         * @var bool
    class BP_Groups_Group { 
    148156        public $user_has_access;
    149157
    150158        /**
     159         * Should the current user be able to see the group?
     160         *
     161         * @since 1.6.0
     162         * @var bool
     163         */
     164        public $is_visible;
     165
     166        /**
    151167         * Raw arguments passed to the constructor.
    152168         *
    153169         * @since 2.0.0
    class BP_Groups_Group { 
    217233                $this->enable_forum = $group->enable_forum;
    218234                $this->date_created = $group->date_created;
    219235
     236                // Populate the group's capabilities.
     237                $base_caps = bp_groups_get_group_status_capabilities( $group->status );
     238                /**
     239                 * Filters the capabilities for a specific group.
     240                 *
     241                 * @since 2.7.0
     242                 *
     243                 * @param array  $base_caps  The capabilities for this group.
     244                 * @param array  $group      Group object as it exists so far.
     245                 */
     246                $this->capabilities = apply_filters( 'bp_groups_group_object_set_caps', $base_caps, $this );
     247
    220248                // Are we getting extra group data?
    221249                if ( ! empty( $this->args['populate_extras'] ) ) {
    222250
    class BP_Groups_Group { 
    249277                        $this->is_invited = groups_check_user_has_invite( $user_id, $this->id );
    250278                        $this->is_pending = groups_check_for_membership_request( $user_id, $this->id );
    251279
    252                         // If this is a private or hidden group, does the current user have access?
    253                         if ( ( 'private' === $this->status ) || ( 'hidden' === $this->status ) ) {
     280                        // Set group visibility and access.
     281                        if ( bp_current_user_can( 'bp_moderate' ) ) {
     282                                $this->is_visible = true;
     283                                $this->user_has_access = true;
     284                        } else {
     285                                // Should this group be visible to the current user?
     286                                $this->is_visible = false;
     287
     288                                // Parse multiple visibility conditions into an array.
     289                                $access_conditions = $this->capabilities['show_group'];
     290                                if ( ! is_array( $access_conditions ) ) {
     291                                        $access_conditions = explode( ',', $access_conditions );
     292                                }
     293
     294                                // If the current user meets at least one condition,
     295                                // allow visibility.
     296                                foreach ( $access_conditions as $access_condition ) {
     297                                        if ( bp_groups_user_meets_access_condition( $access_condition, $this->id, $user_id ) ) {
     298                                                $this->is_visible = true;
     299                                                break;
     300                                        }
     301                                }
    254302
    255                                 // Assume user does not have access to hidden/private groups.
     303                                // Should the user have access to this group?
    256304                                $this->user_has_access = false;
    257305
    258                                 // Group members or community moderators have access.
    259                                 if ( ( $this->is_member && is_user_logged_in() ) || bp_current_user_can( 'bp_moderate' ) ) {
    260                                         $this->user_has_access = true;
     306                                // Parse multiple visibility conditions into an array.
     307                                $access_conditions = $this->capabilities['access_group'];
     308                                if ( ! is_array( $access_conditions ) ) {
     309                                        $access_conditions = explode( ',', $access_conditions );
     310                                }
     311
     312                                // If the current user meets at least one condition,
     313                                // allow access.
     314                                foreach ( $access_conditions as $access_condition ) {
     315                                        if ( bp_groups_user_meets_access_condition( $access_condition, $this->id, $user_id ) ) {
     316                                                $this->user_has_access = true;
     317                                                break;
     318                                        }
    261319                                }
    262                         } else {
    263                                 $this->user_has_access = true;
    264320                        }
    265321                }
    266322        }
    class BP_Groups_Group { 
    478534
    479535                $bp = buddypress();
    480536
    481                 return $wpdb->get_col( $wpdb->prepare( "SELECT user_id FROM {$bp->groups->table_name_members} WHERE group_id = %d and is_confirmed = 0 AND inviter_id = %d", $group_id, $user_id ) );
     537                // Hide invitations to unknowable groups.
     538                $hidden_sql = '';
     539                if ( $hidden_group_ids = self::get_hidden_group_ids() ) {
     540                        $hidden_group_ids = implode( ',', $hidden_group_ids );
     541                        $hidden_sql = " WHERE group_id NOT IN ({$hidden_group_ids})";
     542                }
     543
     544                return $wpdb->get_col( $wpdb->prepare( "SELECT user_id FROM {$bp->groups->table_name_members} WHERE group_id = %d and is_confirmed = 0 AND inviter_id = %d{$hidden_sql}", $group_id, $user_id ) );
    482545        }
    483546
    484547        /**
    class BP_Groups_Group { 
    522585                $bp = buddypress();
    523586
    524587                $gids = esc_sql( implode( ',', wp_parse_id_list( $gids['groups'] ) ) );
    525 
    526                 $paged_groups = $wpdb->get_results( $wpdb->prepare( "SELECT id as group_id FROM {$bp->groups->table_name} WHERE ( name LIKE %s OR description LIKE %s ) AND id IN ({$gids}) {$pag_sql}", $search_terms_like, $search_terms_like ) );
     588$sql = $wpdb->prepare( "SELECT id as group_id FROM {$bp->groups->table_name} WHERE ( name LIKE %s OR description LIKE %s ) AND id IN ({$gids}) {$pag_sql}", $search_terms_like, $search_terms_like );
     589                $paged_groups = $wpdb->get_results( $sql );
    527590                $total_groups = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM {$bp->groups->table_name} WHERE ( name LIKE %s OR description LIKE %s ) AND id IN ({$gids})", $search_terms_like, $search_terms_like ) );
    528591
    529592                return array( 'groups' => $paged_groups, 'total' => $total_groups );
    class BP_Groups_Group { 
    564627                        $order_sql = "ORDER BY {$sort_by} {$order}";
    565628                }
    566629
    567                 if ( !bp_current_user_can( 'bp_moderate' ) )
    568                         $hidden_sql = "AND status != 'hidden'";
     630                $hidden_sql = '';
     631                if ( ! bp_current_user_can( 'bp_moderate' ) && $hidden_group_ids = self::get_hidden_group_ids() ) {
     632                        $hidden_group_ids = implode( ',', $hidden_group_ids );
     633                        $hidden_sql = " AND id NOT IN ({$hidden_group_ids})";
     634                }
    569635
    570636                $bp = buddypress();
    571637
    class BP_Groups_Group { 
    789855
    790856                $sql['where'] = " g.id = gm1.group_id AND g.id = gm2.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count'";
    791857
    792                 if ( empty( $r['show_hidden'] ) ) {
    793                         $sql['hidden'] = " AND g.status != 'hidden'";
    794                 }
    795858
    796859                if ( ! empty( $r['search_terms'] ) ) {
    797860                        $search_terms_like = '%' . bp_esc_like( $r['search_terms'] ) . '%';
    class BP_Groups_Group { 
    835898                        $sql['include'] = " AND g.id IN ({$include})";
    836899                }
    837900
    838                 if ( ! empty( $r['exclude'] ) ) {
    839                         $exclude        = implode( ',', wp_parse_id_list( $r['exclude'] ) );
    840                         $sql['exclude'] = " AND g.id NOT IN ({$exclude})";
     901                $exclude_group_ids = array();
     902                if ( ! $r['show_hidden'] || ! empty( $r['exclude'] ) ) {
     903                        $hidden_group_ids = array();
     904                        if ( ! $r['show_hidden'] ) {
     905                                // Get the groups not visible to this user. Note: this could be empty.
     906                                $hidden_group_ids = self::get_hidden_group_ids();
     907                        }
     908
     909                        if ( ! empty( $r['exclude'] ) ) {
     910                                $exclude_group_ids = wp_parse_id_list( $r['exclude'] );
     911                        }
     912
     913                        $exclude_group_ids = array_merge( $exclude_group_ids, $hidden_group_ids );
     914                        if ( $exclude_group_ids ) {
     915                                $exclude_group_ids = implode( ',', $exclude_group_ids );
     916                                $sql['exclude'] = " AND g.id NOT IN ({$exclude_group_ids})";
     917                        }
    841918                }
    842919
    843920                /* Order/orderby ********************************************/
    class BP_Groups_Group { 
    914991                        $total_sql['select'] .= ", {$bp->groups->table_name_members} m";
    915992                }
    916993
    917                 if ( ! empty( $sql['hidden'] ) ) {
    918                         $total_sql['where'][] = "g.status != 'hidden'";
    919                 }
    920 
    921994                if ( ! empty( $sql['search'] ) ) {
    922995                        $total_sql['where'][] = $wpdb->prepare( "( g.name LIKE %s OR g.description LIKE %s )", $search_terms_like, $search_terms_like );
    923996                }
    class BP_Groups_Group { 
    9481021                }
    9491022
    9501023                // Already escaped in the paginated results block.
    951                 if ( ! empty( $exclude ) ) {
    952                         $total_sql['where'][] = "g.id NOT IN ({$exclude})";
     1024                if ( ! empty( $exclude_group_ids ) ) {
     1025                        $total_sql['where'][] = "g.id NOT IN ({$exclude_group_ids})";
    9531026                }
    9541027
    9551028                $total_sql['where'][] = "g.id = gm.group_id";
    class BP_Groups_Group { 
    11271200                        $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) );
    11281201                }
    11291202
    1130                 if ( !is_user_logged_in() || ( !bp_current_user_can( 'bp_moderate' ) && ( $user_id != bp_loggedin_user_id() ) ) )
    1131                         $hidden_sql = " AND g.status != 'hidden'";
    1132 
    11331203                if ( !empty( $search_terms ) ) {
    11341204                        $search_terms_like = '%' . bp_esc_like( $search_terms ) . '%';
    11351205                        $search_sql        = $wpdb->prepare( ' AND ( g.name LIKE %s OR g.description LIKE %s ) ', $search_terms_like, $search_terms_like );
    11361206                }
    11371207
    1138                 if ( !empty( $exclude ) ) {
    1139                         $exclude     = implode( ',', wp_parse_id_list( $exclude ) );
    1140                         $exclude_sql = " AND g.id NOT IN ({$exclude})";
     1208                $hidden_group_ids = self::get_hidden_group_ids();
     1209                $exclude_group_ids = array();
     1210                if ( ! empty( $exclude ) ) {
     1211                        $exclude_group_ids = wp_parse_id_list( $exclude );
     1212                }
     1213
     1214                if ( $hidden_group_ids || $exclude_group_ids ) {
     1215                        $exclude_group_ids = array_merge( $exclude_group_ids, $hidden_group_ids );
     1216                        $exclude_group_ids = implode( ',', $exclude_group_ids );
     1217                        $exclude_sql       = " AND g.id NOT IN ({$exclude_group_ids})";
    11411218                }
    11421219
    11431220                $bp = buddypress();
    11441221
    11451222                if ( !empty( $user_id ) ) {
    11461223                        $user_id      = absint( esc_sql( $user_id ) );
    1147                         $paged_groups = $wpdb->get_results( "SELECT DISTINCT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bp->groups->table_name_members} m, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = m.group_id AND g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) AND f.topics > 0 {$hidden_sql} {$search_sql} AND m.user_id = {$user_id} AND m.is_confirmed = 1 AND m.is_banned = 0 {$exclude_sql} ORDER BY f.topics DESC {$pag_sql}" );
    1148                         $total_groups = $wpdb->get_var( "SELECT COUNT(DISTINCT g.id) FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) AND f.topics > 0 {$hidden_sql} {$search_sql} AND m.user_id = {$user_id} AND m.is_confirmed = 1 AND m.is_banned = 0 {$exclude_sql}" );
     1224                        $paged_groups = $wpdb->get_results( "SELECT DISTINCT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bp->groups->table_name_members} m, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = m.group_id AND g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) AND f.topics > 0{$search_sql} AND m.user_id = {$user_id} AND m.is_confirmed = 1 AND m.is_banned = 0{$exclude_sql} ORDER BY f.topics DESC {$pag_sql}" );
     1225                        $total_groups = $wpdb->get_var( "SELECT COUNT(DISTINCT g.id) FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) AND f.topics > 0{$search_sql} AND m.user_id = {$user_id} AND m.is_confirmed = 1 AND m.is_banned = 0{$exclude_sql}" );
    11491226                } else {
    1150                         $paged_groups = $wpdb->get_results( "SELECT DISTINCT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) AND f.topics > 0 {$hidden_sql} {$search_sql} {$exclude_sql} ORDER BY f.topics DESC {$pag_sql}" );
    1151                         $total_groups = $wpdb->get_var( "SELECT COUNT(DISTINCT g.id) FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) AND f.topics > 0 {$hidden_sql} {$search_sql} {$exclude_sql}" );
     1227                        $paged_groups = $wpdb->get_results( "SELECT DISTINCT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) AND f.topics > 0{$search_sql}{$exclude_sql} ORDER BY f.topics DESC {$pag_sql}" );
     1228                        $total_groups = $wpdb->get_var( "SELECT COUNT(DISTINCT g.id) FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) AND f.topics > 0{$search_sql}{$exclude_sql}" );
    11521229                }
    11531230
    11541231                if ( !empty( $populate_extras ) ) {
    class BP_Groups_Group { 
    12331310                        $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) );
    12341311                }
    12351312
    1236                 if ( !is_user_logged_in() || ( !bp_current_user_can( 'bp_moderate' ) && ( $user_id != bp_loggedin_user_id() ) ) )
    1237                         $hidden_sql = " AND g.status != 'hidden'";
    1238 
    12391313                if ( !empty( $search_terms ) ) {
    12401314                        $search_terms_like = '%' . bp_esc_like( $search_terms ) . '%';
    12411315                        $search_sql        = $wpdb->prepare( ' AND ( g.name LIKE %s OR g.description LIKE %s ) ', $search_terms_like, $search_terms_like );
    12421316                }
    12431317
    1244                 if ( !empty( $exclude ) ) {
    1245                         $exclude     = implode( ',', wp_parse_id_list( $exclude ) );
    1246                         $exclude_sql = " AND g.id NOT IN ({$exclude})";
     1318                $hidden_group_ids =  self::get_hidden_group_ids();
     1319                $exclude_group_ids = array();
     1320                if ( ! empty( $exclude ) ) {
     1321                        $exclude_group_ids = wp_parse_id_list( $exclude );
     1322                }
     1323
     1324                if ( $hidden_group_ids || $exclude_group_ids ) {
     1325                        $exclude_group_ids = array_merge( $exclude_group_ids, $hidden_group_ids );
     1326                        $exclude_group_ids = implode( ',', $exclude_group_ids );
     1327                        $sql['exclude'] = " AND g.id NOT IN ({$exclude_group_ids})";
    12471328                }
    12481329
    12491330                $bp = buddypress();
    12501331
    12511332                if ( !empty( $user_id ) ) {
    12521333                        $user_id = esc_sql( $user_id );
    1253                         $paged_groups = $wpdb->get_results( "SELECT DISTINCT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bp->groups->table_name_members} m, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = m.group_id AND g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) {$hidden_sql} {$search_sql} AND m.user_id = {$user_id} AND m.is_confirmed = 1 AND m.is_banned = 0 {$exclude_sql} ORDER BY f.posts ASC {$pag_sql}" );
    1254                         $total_groups = $wpdb->get_results( "SELECT COUNT(DISTINCT g.id) FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bp->groups->table_name_members} m, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = m.group_id AND g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) AND f.posts > 0 {$hidden_sql} {$search_sql} AND m.user_id = {$user_id} AND m.is_confirmed = 1 AND m.is_banned = 0 {$exclude_sql} " );
     1334                        $paged_groups = $wpdb->get_results( "SELECT DISTINCT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bp->groups->table_name_members} m, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = m.group_id AND g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) {$search_sql} AND m.user_id = {$user_id} AND m.is_confirmed = 1 AND m.is_banned = 0 {$exclude_sql} ORDER BY f.posts ASC {$pag_sql}" );
     1335                        $total_groups = $wpdb->get_results( "SELECT COUNT(DISTINCT g.id) FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bp->groups->table_name_members} m, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = m.group_id AND g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) AND f.posts > 0 {$search_sql} AND m.user_id = {$user_id} AND m.is_confirmed = 1 AND m.is_banned = 0 {$exclude_sql} " );
    12551336                } else {
    1256                         $paged_groups = $wpdb->get_results( "SELECT DISTINCT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) AND f.posts > 0 {$hidden_sql} {$search_sql} {$exclude_sql} ORDER BY f.posts ASC {$pag_sql}" );
    1257                         $total_groups = $wpdb->get_var( "SELECT COUNT(DISTINCT g.id) FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) {$hidden_sql} {$search_sql} {$exclude_sql}" );
     1337                        $paged_groups = $wpdb->get_results( "SELECT DISTINCT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) AND f.posts > 0 {$search_sql} {$exclude_sql} ORDER BY f.posts ASC {$pag_sql}" );
     1338                        $total_groups = $wpdb->get_var( "SELECT COUNT(DISTINCT g.id) FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_groupmeta} gm3, {$bbdb->forums} f, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND g.id = gm3.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND (gm3.meta_key = 'forum_id' AND gm3.meta_value = f.forum_id) {$search_sql} {$exclude_sql}" );
    12581339                }
    12591340
    12601341                if ( !empty( $populate_extras ) ) {
    class BP_Groups_Group { 
    13061387
    13071388                $bp = buddypress();
    13081389
    1309                 if ( !empty( $exclude ) ) {
    1310                         $exclude     = implode( ',', wp_parse_id_list( $exclude ) );
    1311                         $exclude_sql = " AND g.id NOT IN ({$exclude})";
     1390                $hidden_group_ids = self::get_hidden_group_ids();
     1391                $exclude_group_ids = array();
     1392                if ( ! empty( $exclude ) ) {
     1393                        $exclude_group_ids = wp_parse_id_list( $exclude );
    13121394                }
    13131395
    1314                 if ( !bp_current_user_can( 'bp_moderate' ) )
    1315                         $hidden_sql = " AND status != 'hidden'";
     1396                if ( $hidden_group_ids || $exclude_group_ids ) {
     1397                        $exclude_group_ids = array_merge( $exclude_group_ids, $hidden_group_ids );
     1398                        $exclude_group_ids = implode( ',', $exclude_group_ids );
     1399                        $exclude_sql       = " AND g.id NOT IN ({$exclude_group_ids})";
     1400                }
    13161401
    13171402                $letter_like = bp_esc_like( $letter ) . '%';
    13181403
    class BP_Groups_Group { 
    13201405                        $pag_sql      = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) );
    13211406                }
    13221407
    1323                 $total_groups = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT g.id) FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND g.name LIKE %s {$hidden_sql} {$exclude_sql}", $letter_like ) );
     1408                $total_groups = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT g.id) FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND g.name LIKE %s{$exclude_sql}", $letter_like ) );
    13241409
    1325                 $paged_groups = $wpdb->get_results( $wpdb->prepare( "SELECT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND g.name LIKE %s {$hidden_sql} {$exclude_sql} ORDER BY g.name ASC {$pag_sql}", $letter_like ) );
     1410                $paged_groups = $wpdb->get_results( $wpdb->prepare( "SELECT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND g.name LIKE %s{$exclude_sql} ORDER BY g.name ASC {$pag_sql}", $letter_like ) );
    13261411
    13271412                if ( !empty( $populate_extras ) ) {
    13281413                        foreach ( (array) $paged_groups as $group ) {
    class BP_Groups_Group { 
    13681453                if ( !empty( $limit ) && !empty( $page ) )
    13691454                        $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) );
    13701455
    1371                 if ( !is_user_logged_in() || ( !bp_current_user_can( 'bp_moderate' ) && ( $user_id != bp_loggedin_user_id() ) ) )
    1372                         $hidden_sql = "AND g.status != 'hidden'";
    1373 
    13741456                if ( !empty( $search_terms ) ) {
    13751457                        $search_terms_like = '%' . bp_esc_like( $search_terms ) . '%';
    13761458                        $search_sql = $wpdb->prepare( " AND ( g.name LIKE %s OR g.description LIKE %s )", $search_terms_like, $search_terms_like );
    13771459                }
    13781460
    1379                 if ( !empty( $exclude ) ) {
    1380                         $exclude     = wp_parse_id_list( $exclude );
    1381                         $exclude     = esc_sql( implode( ',', $exclude ) );
    1382                         $exclude_sql = " AND g.id NOT IN ({$exclude})";
     1461                $hidden_group_ids = self::get_hidden_group_ids();
     1462                $exclude_group_ids = array();
     1463                if ( ! empty( $exclude ) ) {
     1464                        $exclude_group_ids = wp_parse_id_list( $exclude );
     1465                }
     1466
     1467                if ( $hidden_group_ids || $exclude_group_ids ) {
     1468                        $exclude_group_ids = array_merge( $exclude_group_ids, $hidden_group_ids );
     1469                        $exclude_group_ids = implode( ',', $exclude_group_ids );
     1470                        $exclude_sql       = " AND g.id NOT IN ({$exclude_group_ids})";
    13831471                }
    13841472
    13851473                $bp = buddypress();
    13861474
    13871475                if ( !empty( $user_id ) ) {
    13881476                        $user_id = esc_sql( $user_id );
    1389                         $paged_groups = $wpdb->get_results( "SELECT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE g.id = m.group_id AND g.id = gm1.group_id AND g.id = gm2.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' {$hidden_sql} {$search_sql} AND m.user_id = {$user_id} AND m.is_confirmed = 1 AND m.is_banned = 0 {$exclude_sql} ORDER BY rand() {$pag_sql}" );
    1390                         $total_groups = $wpdb->get_var( "SELECT COUNT(DISTINCT m.group_id) FROM {$bp->groups->table_name_members} m LEFT JOIN {$bp->groups->table_name_groupmeta} gm ON m.group_id = gm.group_id INNER JOIN {$bp->groups->table_name} g ON m.group_id = g.id WHERE gm.meta_key = 'last_activity'{$hidden_sql} {$search_sql} AND m.user_id = {$user_id} AND m.is_confirmed = 1 AND m.is_banned = 0 {$exclude_sql}" );
     1477                        $paged_groups = $wpdb->get_results( "SELECT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE g.id = m.group_id AND g.id = gm1.group_id AND g.id = gm2.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' {$search_sql} AND m.user_id = {$user_id} AND m.is_confirmed = 1 AND m.is_banned = 0{$exclude_sql} ORDER BY rand() {$pag_sql}" );
     1478                        $total_groups = $wpdb->get_var( "SELECT COUNT(DISTINCT m.group_id) FROM {$bp->groups->table_name_members} m LEFT JOIN {$bp->groups->table_name_groupmeta} gm ON m.group_id = gm.group_id INNER JOIN {$bp->groups->table_name} g ON m.group_id = g.id WHERE gm.meta_key = 'last_activity' {$search_sql} AND m.user_id = {$user_id} AND m.is_confirmed = 1 AND m.is_banned = 0{$exclude_sql}" );
    13911479                } else {
    1392                         $paged_groups = $wpdb->get_results( "SELECT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' {$hidden_sql} {$search_sql} {$exclude_sql} ORDER BY rand() {$pag_sql}" );
    1393                         $total_groups = $wpdb->get_var( "SELECT COUNT(DISTINCT g.id) FROM {$bp->groups->table_name_groupmeta} gm INNER JOIN {$bp->groups->table_name} g ON gm.group_id = g.id WHERE gm.meta_key = 'last_activity'{$hidden_sql} {$search_sql} {$exclude_sql}" );
     1480                        $paged_groups = $wpdb->get_results( "SELECT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name} g WHERE g.id = gm1.group_id AND g.id = gm2.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count'{$search_sql}{$exclude_sql} ORDER BY rand() {$pag_sql}" );
     1481                        $total_groups = $wpdb->get_var( "SELECT COUNT(DISTINCT g.id) FROM {$bp->groups->table_name_groupmeta} gm INNER JOIN {$bp->groups->table_name} g ON gm.group_id = g.id WHERE gm.meta_key = 'last_activity'{$search_sql}{$exclude_sql}" );
    13941482                }
    13951483
    13961484                if ( !empty( $populate_extras ) ) {
    class BP_Groups_Group { 
    14291517                        $group->is_invited = groups_is_user_invited( $user_id, $group->id ) ? '1' : '0';
    14301518                        $group->is_pending = groups_is_user_pending( $user_id, $group->id ) ? '1' : '0';
    14311519                        $group->is_banned  = (bool) groups_is_user_banned( $user_id, $group->id );
     1520
     1521                        // Populate the group's capabilities.
     1522                        if ( empty( $group->status ) ) {
     1523                                // @TODO: This seems like a hack. Need to figure out when $paged_groups are not complete.
     1524                                $temp_group    = groups_get_group( array( 'group_id' => $group->id ) );
     1525                                $group->status = $temp_group->status;
     1526                        }
     1527                        $base_caps = bp_groups_get_group_status_capabilities( $group->status );
     1528                        /**
     1529                         * Filters the capabilities for a specific group.
     1530                         *
     1531                         * @since 2.7.0
     1532                         *
     1533                         * @param array  $base_caps  The capabilities for this group.
     1534                         * @param array  $group      Group object as it exists so far.
     1535                         */
     1536                        $group->capabilities = apply_filters( 'bp_groups_group_object_set_caps', $base_caps, $group );
     1537
     1538                        // Set group visibility and access.
     1539                        if ( bp_current_user_can( 'bp_moderate' ) ) {
     1540                                $group->is_visible = true;
     1541                                $group->user_has_access = true;
     1542                        } else {
     1543                                // Should this group be visible to the current user?
     1544                                $group->is_visible = false;
     1545
     1546                                // Parse multiple visibility conditions into an array.
     1547                                $access_conditions = $group->capabilities['show_group'];
     1548                                if ( ! is_array( $access_conditions ) ) {
     1549                                        $access_conditions = explode( ',', $access_conditions );
     1550                                }
     1551
     1552                                // If the current user meets at least one condition,
     1553                                // allow visibility.
     1554                                foreach ( $access_conditions as $access_condition ) {
     1555                                        if ( bp_groups_user_meets_access_condition( $access_condition, $group->id, $user_id ) ) {
     1556                                                $group->is_visible = true;
     1557                                                break;
     1558                                        }
     1559                                }
     1560
     1561                                // Should the user have access to this group?
     1562                                $group->user_has_access = false;
     1563
     1564                                // Parse multiple visibility conditions into an array.
     1565                                $access_conditions = $group->capabilities['access_group'];
     1566                                if ( ! is_array( $access_conditions ) ) {
     1567                                        $access_conditions = explode( ',', $access_conditions );
     1568                                }
     1569
     1570                                // If the current user meets at least one condition,
     1571                                // allow access.
     1572                                foreach ( $access_conditions as $access_condition ) {
     1573                                        if ( bp_groups_user_meets_access_condition( $access_condition, $group->id, $user_id ) ) {
     1574                                                $group->user_has_access = true;
     1575                                                break;
     1576                                        }
     1577                                }
     1578                        }
     1579
    14321580                }
    14331581
    14341582                return $paged_groups;
    class BP_Groups_Group { 
    14651613                global $wpdb;
    14661614
    14671615                $hidden_sql = '';
    1468                 if ( !bp_current_user_can( 'bp_moderate' ) )
    1469                         $hidden_sql = "WHERE status != 'hidden'";
    1470 
     1616                if ( ! bp_current_user_can( 'bp_moderate' ) && $hidden_group_ids = self::get_hidden_group_ids() ) {
     1617                        $hidden_group_ids = implode( ',', $hidden_group_ids );
     1618                        $hidden_sql = " WHERE id NOT IN ({$hidden_group_ids})";
     1619                }
    14711620                $bp = buddypress();
    14721621
    14731622                return $wpdb->get_var( "SELECT COUNT(id) FROM {$bp->groups->table_name} {$hidden_sql}" );
    class BP_Groups_Group { 
    15371686         */
    15381687        public static function get_global_topic_count( $status = 'public', $search_terms = false ) {
    15391688                global $bbdb, $wpdb;
    1540 
     1689                // @TODO: Update this to account for custom statuses?
    15411690                switch ( $status ) {
    15421691                        case 'all' :
    15431692                                $status_sql = '';
    15441693                                break;
    1545 
    15461694                        case 'hidden' :
    15471695                                $status_sql = "AND g.status = 'hidden'";
    15481696                                break;
    class BP_Groups_Group { 
    15901738                $ids = array();
    15911739
    15921740                $ids['all']     = $wpdb->get_col( "SELECT id FROM {$bp->groups->table_name}" );
    1593                 $ids['public']  = $wpdb->get_col( "SELECT id FROM {$bp->groups->table_name} WHERE status = 'public'" );
    1594                 $ids['private'] = $wpdb->get_col( "SELECT id FROM {$bp->groups->table_name} WHERE status = 'private'" );
    1595                 $ids['hidden']  = $wpdb->get_col( "SELECT id FROM {$bp->groups->table_name} WHERE status = 'hidden'" );
     1741
     1742                $statuses = bp_groups_get_group_statuses( array(), 'names' );
     1743                foreach ( $statuses as $status ) {
     1744                        $ids[$status]  = $wpdb->get_col( $wpdb->prepare( "SELECT id FROM {$bp->groups->table_name} WHERE status = %s", $status ) );
     1745                }
    15961746
    15971747                return $ids;
    15981748        }
    class BP_Groups_Group { 
    16651815
    16661816                return $clause;
    16671817        }
     1818
     1819        /**
     1820         * Generate a list of groups that should be invisible to the current user.
     1821         *
     1822         * @since 2.7.0
     1823         *
     1824         * @return array $hidden_group_ids
     1825         */
     1826        protected static function get_hidden_group_ids() {
     1827                // @TODO: Should this short-circuit for site admins?
     1828
     1829                // Check cache for group data.
     1830                $last_changed = wp_cache_get( 'last_changed', 'bp_groups' );
     1831                if ( false === $last_changed ) {
     1832                        $last_changed = microtime();
     1833                        wp_cache_set( 'last_changed', $last_changed, 'bp_groups' );
     1834                }
     1835
     1836                $cache_key = 'hidden_groups_for_user_' . bp_loggedin_user_id() . '_' . $last_changed;
     1837
     1838                // Cache missed, so query the DB.
     1839                if ( false === $hidden_group_ids ) {
     1840                        // Fetch groups, check if the current user should be able to see each one.
     1841                        $all_group_args = array(
     1842                                'show_hidden'       => true, // Show hidden groups to non-admins.
     1843                                'per_page'          => false, // Return all.
     1844                                'page'              => false, // Return all.
     1845                                'update_meta_cache' => false // Don't prime the meta cache.
     1846                                );
     1847                        $groups = groups_get_groups( $all_group_args );
     1848
     1849                        $hidden_group_ids = array();
     1850                        if ( ! empty( $groups['groups'] ) ) {
     1851                                foreach ( $groups['groups'] as $group ) {
     1852                                        if ( ! $group->is_visible ) {
     1853                                                $hidden_group_ids[] = (int) $group->id;
     1854                                        }
     1855                                }
     1856                        }
     1857
     1858                        wp_cache_set( $cache_key, $hidden_group_ids, 'bp_groups' );
     1859                }
     1860                return $hidden_group_ids;
     1861        }
     1862
    16681863}
  • src/bp-groups/classes/class-bp-groups-list-table.php

    diff --git src/bp-groups/classes/class-bp-groups-list-table.php src/bp-groups/classes/class-bp-groups-list-table.php
    index 7cca49d..afb693c 100644
    class BP_Groups_List_Table extends WP_List_Table { 
    118118                        $include_id = (int) $_REQUEST['gid'];
    119119
    120120                // Set the current view.
    121                 if ( isset( $_GET['group_status'] ) && in_array( $_GET['group_status'], array( 'public', 'private', 'hidden' ) ) ) {
     121                if ( isset( $_GET['group_status'] ) && in_array( $_GET['group_status'], bp_groups_get_group_statuses( array(), 'names' ) ) ) {
    122122                        $this->view = $_GET['group_status'];
    123123                }
    124124
    class BP_Groups_List_Table extends WP_List_Table { 
    294294
    295295                <ul class="subsubsub">
    296296                        <li class="all"><a href="<?php echo esc_url( $url_base ); ?>" class="<?php if ( 'all' == $this->view ) echo 'current'; ?>"><?php _e( 'All', 'buddypress' ); ?></a> |</li>
    297                         <li class="public"><a href="<?php echo esc_url( add_query_arg( 'group_status', 'public', $url_base ) ); ?>" class="<?php if ( 'public' == $this->view ) echo 'current'; ?>"><?php printf( _n( 'Public <span class="count">(%s)</span>', 'Public <span class="count">(%s)</span>', $this->group_counts['public'], 'buddypress' ), number_format_i18n( $this->group_counts['public'] ) ); ?></a> |</li>
    298                         <li class="private"><a href="<?php echo esc_url( add_query_arg( 'group_status', 'private', $url_base ) ); ?>" class="<?php if ( 'private' == $this->view ) echo 'current'; ?>"><?php printf( _n( 'Private <span class="count">(%s)</span>', 'Private <span class="count">(%s)</span>', $this->group_counts['private'], 'buddypress' ), number_format_i18n( $this->group_counts['private'] ) ); ?></a> |</li>
    299                         <li class="hidden"><a href="<?php echo esc_url( add_query_arg( 'group_status', 'hidden', $url_base ) ); ?>" class="<?php if ( 'hidden' == $this->view ) echo 'current'; ?>"><?php printf( _n( 'Hidden <span class="count">(%s)</span>', 'Hidden <span class="count">(%s)</span>', $this->group_counts['hidden'], 'buddypress' ), number_format_i18n( $this->group_counts['hidden'] ) ); ?></a></li>
    300 
    301297                        <?php
     298                        $group_statuses = bp_groups_get_group_statuses( array(), 'objects' );
     299                        $num_statuses   = count( $group_statuses );
     300                        $i              = 1;
     301                        foreach ( $group_statuses as $status ) : ?>
     302                        <li class="<?php echo $status->name; ?>"><a href="<?php echo esc_url( add_query_arg( 'group_status', $status->name, $url_base ) ); ?>" class="<?php if ( $status->name == $this->view ) echo 'current'; ?>"><?php printf( _n( '%s <span class="count">(%s)</span>', '%s <span class="count">(%s)</span>',
     303                                        $status->display_name,
     304                                        $this->group_counts[$status->name], 'buddypress' ),
     305                                        $status->display_name,
     306                                        number_format_i18n( $this->group_counts[$status->name] ) ); ?></a><?php
     307                                if ( $i < $num_statuses ) {
     308                                        echo ' |';
     309                                }
     310                                $i++;
     311                        ?></li>
     312                        <?php
     313                        endforeach;
    302314
    303315                        /**
    304316                         * Fires inside listing of views so plugins can add their own.
    class BP_Groups_List_Table extends WP_List_Table { 
    553565         * @param array $item Information about the current row.
    554566         */
    555567        public function column_status( $item = array() ) {
    556                 $status      = $item['status'];
    557                 $status_desc = '';
    558 
    559                 // @todo This should be abstracted out somewhere for the whole
    560                 // Groups component.
    561                 switch ( $status ) {
    562                         case 'public' :
    563                                 $status_desc = __( 'Public', 'buddypress' );
    564                                 break;
    565                         case 'private' :
    566                                 $status_desc = __( 'Private', 'buddypress' );
    567                                 break;
    568                         case 'hidden' :
    569                                 $status_desc = __( 'Hidden', 'buddypress' );
    570                                 break;
    571                 }
     568                $status_object = bp_groups_get_group_status_object( $item['status'] );
     569                $status_desc   = $status_object->display_name;
    572570
    573571                /**
    574572                 * Filters the markup for the Status column.
  • src/bp-groups/classes/class-bp-groups-member.php

    diff --git src/bp-groups/classes/class-bp-groups-member.php src/bp-groups/classes/class-bp-groups-member.php
    index bfb1a76..fbfea91 100644
    class BP_Groups_Member { 
    508508
    509509                $bp = buddypress();
    510510
    511                 // If the user is logged in and viewing their own groups, we can show hidden and private groups.
    512                 if ( $user_id != bp_loggedin_user_id() ) {
    513                         $group_sql = $wpdb->prepare( "SELECT DISTINCT m.group_id FROM {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE g.status != 'hidden' AND m.user_id = %d AND m.is_confirmed = 1 AND m.is_banned = 0{$pag_sql}", $user_id );
    514                         $total_groups = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT m.group_id) FROM {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE g.status != 'hidden' AND m.user_id = %d AND m.is_confirmed = 1 AND m.is_banned = 0", $user_id ) );
    515                 } else {
    516                         $group_sql = $wpdb->prepare( "SELECT DISTINCT group_id FROM {$bp->groups->table_name_members} WHERE user_id = %d AND is_confirmed = 1 AND is_banned = 0{$pag_sql}", $user_id );
    517                         $total_groups = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT group_id) FROM {$bp->groups->table_name_members} WHERE user_id = %d AND is_confirmed = 1 AND is_banned = 0", $user_id ) );
     511                $hidden_sql = '';
     512                if ( $hidden_group_ids = self::get_hidden_group_ids() ) {
     513                        $hidden_group_ids = implode( ',', $hidden_group_ids );
     514                        $hidden_sql = " AND group_id NOT IN ({$hidden_group_ids})";
    518515                }
    519516
     517                $group_sql = $wpdb->prepare( "SELECT DISTINCT group_id FROM {$bp->groups->table_name_members} WHERE user_id = %d AND is_confirmed = 1 AND is_banned = 0{$hidden_sql}{$pag_sql}", $user_id );
     518                $total_groups = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT group_id) FROM {$bp->groups->table_name_members} m WHERE user_id = %d AND is_confirmed = 1 AND is_banned = 0{$hidden_sql}", $user_id ) );
     519
    520520                $groups = $wpdb->get_col( $group_sql );
    521521
    522522                return array( 'groups' => $groups, 'total' => (int) $total_groups );
    class BP_Groups_Member { 
    554554                        $filter_sql = $wpdb->prepare( " AND ( g.name LIKE %s OR g.description LIKE %s )", $search_terms_like, $search_terms_like );
    555555                }
    556556
    557                 if ( $user_id != bp_loggedin_user_id() )
    558                         $hidden_sql = " AND g.status != 'hidden'";
     557                if ( $hidden_group_ids = self::get_hidden_group_ids() ) {
     558                        $hidden_group_ids = implode( ',', $hidden_group_ids );
     559                        $hidden_sql = " AND g.id NOT IN ({$hidden_group_ids})";
     560                }
    559561
    560562                $bp = buddypress();
    561563
    class BP_Groups_Member { 
    597599                        $filter_sql = $wpdb->prepare( " AND ( g.name LIKE %s OR g.description LIKE %s )", $search_terms_like, $search_terms_like );
    598600                }
    599601
    600                 if ( $user_id != bp_loggedin_user_id() )
    601                         $hidden_sql = " AND g.status != 'hidden'";
     602                if ( $hidden_group_ids = self::get_hidden_group_ids() ) {
     603                        $hidden_group_ids = implode( ',', $hidden_group_ids );
     604                        $hidden_sql = " AND g.id NOT IN ({$hidden_group_ids})";
     605                }
    602606
    603607                $bp = buddypress();
    604608
    class BP_Groups_Member { 
    640644                        $filter_sql = $wpdb->prepare( " AND ( g.name LIKE %s OR g.description LIKE %s )", $search_terms_like, $search_terms_like );
    641645                }
    642646
    643                 if ( $user_id != bp_loggedin_user_id() )
    644                         $hidden_sql = " AND g.status != 'hidden'";
     647                if ( $hidden_group_ids = self::get_hidden_group_ids() ) {
     648                        $hidden_group_ids = implode( ',', $hidden_group_ids );
     649                        $hidden_sql = " AND g.id NOT IN ({$hidden_group_ids})";
     650                }
    645651
    646652                $bp = buddypress();
    647653
    class BP_Groups_Member { 
    685691                        $filter_sql        = $wpdb->prepare( " AND ( g.name LIKE %s OR g.description LIKE %s )", $search_terms_like, $search_terms_like );
    686692                }
    687693
    688                 if ( $user_id !== bp_loggedin_user_id() && ! bp_current_user_can( 'bp_moderate' ) ) {
    689                         $hidden_sql = " AND g.status != 'hidden'";
     694                if ( $hidden_group_ids = self::get_hidden_group_ids() ) {
     695                        $hidden_group_ids = implode( ',', $hidden_group_ids );
     696                        $hidden_sql = " AND g.id NOT IN ({$hidden_group_ids})";
    690697                }
    691698
    692699                $paged_groups = $wpdb->get_results( "SELECT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE g.id = m.group_id AND g.id = gm1.group_id AND g.id = gm2.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count'{$hidden_sql}{$filter_sql} AND {$user_id_sql} AND m.is_banned = 1  ORDER BY m.date_modified ASC {$pag_sql}" );
    class BP_Groups_Member { 
    711718
    712719                $bp = buddypress();
    713720
    714                 if ( $user_id != bp_loggedin_user_id() && !bp_current_user_can( 'bp_moderate' ) ) {
    715                         return (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT m.group_id) FROM {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE m.group_id = g.id AND g.status != 'hidden' AND m.user_id = %d AND m.is_confirmed = 1 AND m.is_banned = 0", $user_id ) );
    716                 } else {
    717                         return (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT m.group_id) FROM {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE m.group_id = g.id AND m.user_id = %d AND m.is_confirmed = 1 AND m.is_banned = 0", $user_id ) );
     721                $hidden_sql = '';
     722                if ( $hidden_group_ids = self::get_hidden_group_ids() ) {
     723                        $hidden_group_ids = implode( ',', $hidden_group_ids );
     724                        $hidden_sql = " AND m.group_id NOT IN ({$hidden_group_ids})";
    718725                }
     726
     727                return (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT m.group_id) FROM {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE m.group_id = g.id{$hidden_sql} AND m.user_id = %d AND m.is_confirmed = 1 AND m.is_banned = 0", $user_id ) );
    719728        }
    720729
    721730        /**
    class BP_Groups_Member { 
    740749
    741750                $pag_sql = ( !empty( $limit ) && !empty( $page ) ) ? $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) ) : '';
    742751
    743                 if ( !empty( $exclude ) ) {
    744                         $exclude     = implode( ',', wp_parse_id_list( $exclude ) );
    745                         $exclude_sql = " AND g.id NOT IN ({$exclude})";
    746                 } else {
    747                         $exclude_sql = '';
     752                $exclude_ids = array();
     753                if ( ! empty( $exclude ) ) {
     754                        $exclude_ids = wp_parse_id_list( $exclude );
     755                }
     756
     757                $hidden_group_ids = self::get_hidden_group_ids();
     758
     759                $exclude_sql = '';
     760                if ( $exclude_ids || $hidden_group_ids ) {
     761                        $hidden_group_ids = array_merge( $exclude_ids, $hidden_group_ids );
     762                        $hidden_group_ids = implode( ',', $hidden_group_ids );
     763                        $exclude_sql = " AND g.id NOT IN ({$hidden_group_ids})";
    748764                }
    749765
    750766                $bp = buddypress();
    class BP_Groups_Member { 
    770786                $count = wp_cache_get( $user_id, 'bp_group_invite_count' );
    771787
    772788                if ( false === $count ) {
    773                         $count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT m.group_id) FROM {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE m.group_id = g.id AND m.is_confirmed = 0 AND m.inviter_id != 0 AND m.invite_sent = 1 AND m.user_id = %d", $user_id ) );
     789
     790                        $exclude_sql = '';
     791                        if ( $hidden_group_ids = self::get_hidden_group_ids() ) {
     792                                $hidden_group_ids = implode( ',', $hidden_group_ids );
     793                                $exclude_sql = " AND m.group_id NOT IN ({$hidden_group_ids})";
     794                        }
     795
     796                        $count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT m.group_id) FROM {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE m.group_id = g.id AND m.is_confirmed = 0 AND m.inviter_id != 0 AND m.invite_sent = 1 AND m.user_id = %d{$exclude_sql}", $user_id ) );
    774797                        wp_cache_set( $user_id, $count, 'bp_group_invite_count' );
    775798                }
    776799
    class BP_Groups_Member { 
    9991022
    10001023                $bp = buddypress();
    10011024
    1002                 // If the user is logged in and viewing their random groups, we can show hidden and private groups.
    1003                 if ( bp_is_my_profile() ) {
    1004                         return $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT group_id FROM {$bp->groups->table_name_members} WHERE user_id = %d AND is_confirmed = 1 AND is_banned = 0 ORDER BY rand() LIMIT %d", $user_id, $total_groups ) );
    1005                 } else {
    1006                         return $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT m.group_id FROM {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE m.group_id = g.id AND g.status != 'hidden' AND m.user_id = %d AND m.is_confirmed = 1 AND m.is_banned = 0 ORDER BY rand() LIMIT %d", $user_id, $total_groups ) );
     1025                $hidden_sql = '';
     1026                if ( $hidden_group_ids = self::get_hidden_group_ids() ) {
     1027                        $hidden_group_ids = implode( ',', $hidden_group_ids );
     1028                        $hidden_sql = " AND group_id NOT IN ({$hidden_group_ids})";
    10071029                }
     1030                return $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT m.group_id FROM {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE m.group_id = g.id{$hidden_sql} AND m.user_id = %d AND m.is_confirmed = 1 AND m.is_banned = 0 ORDER BY rand() LIMIT %d", $user_id, $total_groups ) );
    10081031        }
    10091032
    10101033        /**
    class BP_Groups_Member { 
    12461269
    12471270                return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->groups->table_name_members} WHERE user_id = %d", $user_id ) );
    12481271        }
     1272
     1273        /**
     1274         * Generate a list of groups that should be invisible to the current user.
     1275         *
     1276         * @since 2.7.0
     1277         *
     1278         * @return array $hidden_group_ids
     1279         */
     1280        protected static function get_hidden_group_ids() {
     1281                // Check cache for group data.
     1282                $last_changed = wp_cache_get( 'last_changed', 'bp_groups' );
     1283                if ( false === $last_changed ) {
     1284                        $last_changed = microtime();
     1285                        wp_cache_set( 'last_changed', $last_changed, 'bp_groups' );
     1286                }
     1287
     1288                $cache_key = 'hidden_groups_for_user_' . bp_loggedin_user_id() . '_' . $last_changed;
     1289                $hidden_group_ids = wp_cache_get( $cache_key, 'bp_groups' );
     1290
     1291                // Cache missed, so query the DB.
     1292                if ( false === $hidden_group_ids ) {
     1293                        // Fetch groups, check if the current user should be able to see each one.
     1294                        $all_group_args = array(
     1295                                'show_hidden'       => true, // Show hidden groups to non-admins.
     1296                                'per_page'          => false, // Return all.
     1297                                'page'              => false, // Return all.
     1298                                'update_meta_cache' => false // Don't prime the meta cache.
     1299                                );
     1300                        $groups = groups_get_groups( $all_group_args );
     1301
     1302                        $hidden_group_ids = array();
     1303                        if ( ! empty( $groups['groups'] ) ) {
     1304                                foreach ( $groups['groups'] as $group ) {
     1305                                        if ( ! $group->is_visible ) {
     1306                                                $hidden_group_ids[] = (int) $group->id;
     1307                                        }
     1308                                }
     1309                        }
     1310
     1311                        wp_cache_set( $cache_key, $hidden_group_ids, 'bp_groups' );
     1312                }
     1313                return $hidden_group_ids;
     1314        }
    12491315}
  • src/bp-groups/classes/class-bp-groups-template.php

    diff --git src/bp-groups/classes/class-bp-groups-template.php src/bp-groups/classes/class-bp-groups-template.php
    index 043d8f4..b614d29 100644
    class BP_Groups_Template { 
    181181                $this->pag_page = bp_sanitize_pagination_arg( $this->pag_arg, $r['page']     );
    182182                $this->pag_num  = bp_sanitize_pagination_arg( 'num',          $r['per_page'] );
    183183
    184                 if ( bp_current_user_can( 'bp_moderate' ) || ( is_user_logged_in() && $user_id == bp_loggedin_user_id() ) ) {
     184                if ( bp_current_user_can( 'bp_moderate' ) ) {
    185185                        $show_hidden = true;
    186186                }
    187187
  • src/bp-templates/bp-legacy/buddypress-functions.php

    diff --git src/bp-templates/bp-legacy/buddypress-functions.php src/bp-templates/bp-legacy/buddypress-functions.php
    index 436fcac..1e72cd3 100644
    function bp_legacy_theme_ajax_joinleave_group() { 
    14371437                return;
    14381438
    14391439        if ( ! groups_is_user_member( bp_loggedin_user_id(), $group->id ) ) {
    1440                 if ( 'public' == $group->status ) {
     1440                if ( 'anyone_can_join' == bp_groups_group_has_cap( $group, 'join_method' ) ) {
    14411441                        check_ajax_referer( 'groups_join_group' );
    14421442
    14431443                        if ( ! groups_join_group( $group->id ) ) {
    function bp_legacy_theme_ajax_joinleave_group() { 
    14461446                                echo '<a id="group-' . esc_attr( $group->id ) . '" class="leave-group" rel="leave" title="' . __( 'Leave Group', 'buddypress' ) . '" href="' . wp_nonce_url( bp_get_group_permalink( $group ) . 'leave-group', 'groups_leave_group' ) . '">' . __( 'Leave Group', 'buddypress' ) . '</a>';
    14471447                        }
    14481448
    1449                 } elseif ( 'private' == $group->status ) {
     1449                } elseif ( 'accepts_membership_requests' == bp_groups_group_has_cap( $group, 'join_method' ) ) {
    14501450
    14511451                        // If the user has already been invited, then this is
    14521452                        // an Accept Invitation button.
    function bp_legacy_theme_ajax_joinleave_group() { 
    14761476
    14771477                if ( ! groups_leave_group( $group->id ) ) {
    14781478                        _e( 'Error leaving group', 'buddypress' );
    1479                 } elseif ( 'public' == $group->status ) {
     1479                } elseif ( bp_groups_group_has_cap( $group, 'anyone_can_join' ) ) {
    14801480                        echo '<a id="group-' . esc_attr( $group->id ) . '" class="join-group" rel="join" title="' . __( 'Join Group', 'buddypress' ) . '" href="' . wp_nonce_url( bp_get_group_permalink( $group ) . 'join', 'groups_join_group' ) . '">' . __( 'Join Group', 'buddypress' ) . '</a>';
    1481                 } elseif ( 'private' == $group->status ) {
     1481                } elseif ( bp_groups_group_has_cap( $group, 'accepts_membership_requests' ) ) {
    14821482                        echo '<a id="group-' . esc_attr( $group->id ) . '" class="request-membership" rel="join" title="' . __( 'Request Membership', 'buddypress' ) . '" href="' . wp_nonce_url( bp_get_group_permalink( $group ) . 'request-membership', 'groups_request_membership' ) . '">' . __( 'Request Membership', 'buddypress' ) . '</a>';
    14831483                }
    14841484        }
  • src/bp-templates/bp-legacy/buddypress/forums/index.php

    diff --git src/bp-templates/bp-legacy/buddypress/forums/index.php src/bp-templates/bp-legacy/buddypress/forums/index.php
    index 3508f30..1d32169 100644
     
    181181
    182182                                                <?php while ( bp_groups() ) : bp_the_group(); ?>
    183183
    184                                                         <?php if ( bp_group_is_forum_enabled() && ( bp_current_user_can( 'bp_moderate' ) || 'public' == bp_get_group_status() || bp_group_is_member() ) ) : ?>
     184                                                        <?php if ( bp_group_is_forum_enabled() && ( bp_current_user_can( 'bp_moderate' ) || 'anyone' != bp_groups_group_has_cap( $group, 'post_in_forum' ) || bp_group_is_member() ) ) : ?>
    185185
    186186                                                                <option value="<?php bp_group_id(); ?>"><?php bp_group_name(); ?></option>
    187187
  • src/bp-templates/bp-legacy/buddypress/groups/create.php

    diff --git src/bp-templates/bp-legacy/buddypress/groups/create.php src/bp-templates/bp-legacy/buddypress/groups/create.php
    index 244b0fc..b4c2a3c 100644
    do_action( 'bp_before_create_group_page' ); ?> 
    101101                                <h4><?php _e( 'Privacy Options', 'buddypress' ); ?></h4>
    102102
    103103                                <div class="radio">
    104 
    105                                         <label for="group-status-public"><input type="radio" name="group-status" id="group-status-public" value="public"<?php if ( 'public' == bp_get_new_group_status() || !bp_get_new_group_status() ) { ?> checked="checked"<?php } ?> aria-describedby="public-group-description" /> <?php _e( 'This is a public group', 'buddypress' ); ?></label>
    106 
    107                                         <ul id="public-group-description">
    108                                                 <li><?php _e( 'Any site member can join this group.', 'buddypress' ); ?></li>
    109                                                 <li><?php _e( 'This group will be listed in the groups directory and in search results.', 'buddypress' ); ?></li>
    110                                                 <li><?php _e( 'Group content and activity will be visible to any site member.', 'buddypress' ); ?></li>
    111                                         </ul>
    112 
    113 
    114                                         <label for="group-status-private"><input type="radio" name="group-status" id="group-status-private" value="private"<?php if ( 'private' == bp_get_new_group_status() ) { ?> checked="checked"<?php } ?> aria-describedby="private-group-description" /> <?php _e( 'This is a private group', 'buddypress' ); ?></label>
    115 
    116                                         <ul id="private-group-description">
    117                                                 <li><?php _e( 'Only users who request membership and are accepted can join the group.', 'buddypress' ); ?></li>
    118                                                 <li><?php _e( 'This group will be listed in the groups directory and in search results.', 'buddypress' ); ?></li>
    119                                                 <li><?php _e( 'Group content and activity will only be visible to members of the group.', 'buddypress' ); ?></li>
    120                                         </ul>
    121 
    122 
    123                                         <label for="group-status-hidden"><input type="radio" name="group-status" id="group-status-hidden" value="hidden"<?php if ( 'hidden' == bp_get_new_group_status() ) { ?> checked="checked"<?php } ?> aria-describedby="hidden-group-description" /> <?php _e('This is a hidden group', 'buddypress' ); ?></label>
    124 
    125                                         <ul id="hidden-group-description">
    126                                                 <li><?php _e( 'Only users who are invited can join the group.', 'buddypress' ); ?></li>
    127                                                 <li><?php _e( 'This group will not be listed in the groups directory or search results.', 'buddypress' ); ?></li>
    128                                                 <li><?php _e( 'Group content and activity will only be visible to members of the group.', 'buddypress' ); ?></li>
    129                                         </ul>
    130 
     104                                        <?php
     105                                        $allowed_statuses = bp_groups_get_group_statuses( array(), 'objects' );
     106                                        $new_group_status = bp_get_new_group_status();
     107                                        if ( ! $new_group_status ) {
     108                                                $new_group_status = current( $allowed_statuses )->name;
     109                                        }
     110                                        foreach( $allowed_statuses as $status ) :
     111                                        ?>
     112                                                <label for="group-status-<?php echo $status->name ?>"><input type="radio" name="group-status" id="group-status-<?php echo $status->name ?>" value="<?php echo $status->name ?>"<?php checked( $status->name, $new_group_status ); ?> aria-describedby="<?php echo $status->name ?>-group-description" /> <?php echo $status->display_name; ?></label>
     113
     114                                                <ul id="<?php echo $status->name ?>-group-description">
     115                                                        <?php
     116                                                        foreach ( $status->capabilities as $cap => $value ) :
     117                                                                $cap_desc = bp_groups_group_capabilities_description( $cap, $value );
     118                                                                if ( $cap_desc ) : ?>
     119                                                                <li><?php echo $cap_desc; ?></li>
     120                                                                <?php endif;
     121                                                        endforeach; ?>
     122                                                </ul>
     123                                        <?php endforeach; ?>
    131124                                </div>
    132125
    133126                                <h4><?php _e( 'Group Invitations', 'buddypress' ); ?></h4>
  • src/bp-templates/bp-legacy/buddypress/groups/single/admin.php

    diff --git src/bp-templates/bp-legacy/buddypress/groups/single/admin.php src/bp-templates/bp-legacy/buddypress/groups/single/admin.php
    index abeab17..783fd20 100644
    do_action( 'bp_before_group_admin_content' ); ?> 
    100100        <h4><?php _e( 'Privacy Options', 'buddypress' ); ?></h4>
    101101
    102102        <div class="radio">
    103 
    104                 <label for="group-status-public"><input type="radio" name="group-status" id="group-status-public" value="public"<?php if ( 'public' == bp_get_new_group_status() || !bp_get_new_group_status() ) { ?> checked="checked"<?php } ?> aria-describedby="public-group-description" /> <?php _e( 'This is a public group', 'buddypress' ); ?></label>
    105 
    106                 <ul id="public-group-description">
    107                         <li><?php _e( 'Any site member can join this group.', 'buddypress' ); ?></li>
    108                         <li><?php _e( 'This group will be listed in the groups directory and in search results.', 'buddypress' ); ?></li>
    109                         <li><?php _e( 'Group content and activity will be visible to any site member.', 'buddypress' ); ?></li>
    110                 </ul>
    111 
    112                 <label for="group-status-private"><input type="radio" name="group-status" id="group-status-private" value="private"<?php if ( 'private' == bp_get_new_group_status() ) { ?> checked="checked"<?php } ?> aria-describedby="private-group-description" /> <?php _e( 'This is a private group', 'buddypress' ); ?></label>
    113 
    114                 <ul id="private-group-description">
    115                         <li><?php _e( 'Only users who request membership and are accepted can join the group.', 'buddypress' ); ?></li>
    116                         <li><?php _e( 'This group will be listed in the groups directory and in search results.', 'buddypress' ); ?></li>
    117                         <li><?php _e( 'Group content and activity will only be visible to members of the group.', 'buddypress' ); ?></li>
    118                 </ul>
    119 
    120                 <label for="group-status-hidden"><input type="radio" name="group-status" id="group-status-hidden" value="hidden"<?php if ( 'hidden' == bp_get_new_group_status() ) { ?> checked="checked"<?php } ?> aria-describedby="hidden-group-description" /> <?php _e('This is a hidden group', 'buddypress' ); ?></label>
    121 
    122                 <ul id="hidden-group-description">
    123                         <li><?php _e( 'Only users who are invited can join the group.', 'buddypress' ); ?></li>
    124                         <li><?php _e( 'This group will not be listed in the groups directory or search results.', 'buddypress' ); ?></li>
    125                         <li><?php _e( 'Group content and activity will only be visible to members of the group.', 'buddypress' ); ?></li>
    126                 </ul>
    127 
     103                <?php
     104                $allowed_statuses = bp_groups_get_group_statuses( array(), 'objects' );
     105                $new_group_status = bp_get_new_group_status();
     106                if ( ! $new_group_status ) {
     107                        $new_group_status = current( $allowed_statuses )->name;
     108                }
     109                foreach( $allowed_statuses as $status ) :
     110                ?>
     111                        <label for="group-status-<?php echo $status->name ?>"><input type="radio" name="group-status" id="group-status-<?php echo $status->name ?>" value="<?php echo $status->name ?>"<?php checked( $status->name, $new_group_status ); ?> aria-describedby="<?php echo $status->name ?>-group-description" /> <?php echo $status->display_name; ?></label>
     112
     113                        <ul id="<?php echo $status->name ?>-group-description">
     114                                <?php
     115                                foreach ( $status->capabilities as $cap => $value ) :
     116                                        $cap_desc = bp_groups_group_capabilities_description( $cap, $value );
     117                                        if ( $cap_desc ) : ?>
     118                                                <li><?php echo $cap_desc; ?></li>
     119                                        <?php endif;
     120                                endforeach; ?>
     121                        </ul>
     122                <?php endforeach; ?>
    128123        </div>
    129124
    130125        <hr />