Skip to:
Content

BuddyPress.org

Ticket #8734: 8734.03.patch

File 8734.03.patch, 20.2 KB (added by dcavins, 3 years ago)

Return to simple option for community visibility.

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

    diff --git src/bp-activity/bp-activity-functions.php src/bp-activity/bp-activity-functions.php
    index ef4b90614..b7c303ae0 100644
    function bp_activity_user_can_read( $activity, $user_id = 0 ) { 
    33043304                $user_id = bp_loggedin_user_id();
    33053305        }
    33063306
     3307        if ( ! bp_current_user_can( 'bp_view', array( 'bp_component' => 'activity' ) ) ) {
     3308                $retval = false;
     3309        }
     3310
    33073311        // If activity is from a group, do extra cap checks.
    3308         if ( bp_is_active( 'groups' ) && buddypress()->groups->id === $activity->component ) {
     3312        if ( bp_is_active( 'groups' ) && buddypress()->groups->id === $activity->component && bp_current_user_can( 'bp_view', array( 'bp_component' => 'groups' ) ) ) {
    33093313                // Check to see if the user has access to the activity's parent group.
    33103314                $group = groups_get_group( $activity->item_id );
    33113315                if ( $group ) {
    function bp_activity_personal_data_exporter( $email_address, $page ) { 
    44824486 * Checks whether an activity feed is enabled.
    44834487 *
    44844488 * @since 8.0.0
     4489 * @since 12.0.0 Added bp_current_user_can( 'bp_view' ) check.
    44854490 *
    44864491 * @param string $feed_id The feed identifier. Possible values are:
    44874492 *                        'sitewide', 'personal', 'friends', 'mygroups', 'mentions', 'favorites'.
    44884493 */
    44894494function bp_activity_is_feed_enable( $feed_id = '' ) {
     4495        if ( bp_current_user_can( 'bp_view', array( 'bp_component' => 'activity' ) ) ) {
     4496                // @TODO: Should we map the feeds to a component, like
     4497                // $component = 'activity';
     4498                // switch ( $feed_id ) {
     4499                //      case 'mygroups':
     4500                //              $component = 'groups';
     4501                //              break;
     4502                //      case 'personal':
     4503                //      case 'friends':
     4504                //      case 'mentions':
     4505                //      case 'favorites':
     4506                //      default:
     4507                //              $component = 'members';
     4508                //              break;
     4509                // }
     4510                // $retval = bp_current_user_can( 'bp_view', array( 'bp_component' => $component ) );
     4511                $retval = true;
     4512        } else {
     4513                $retval = false;
     4514        }
     4515
    44904516        /**
    44914517         * Filters if BuddyPress should consider feeds enabled. If disabled, it will return early.
    44924518         *
    44934519         * @since 1.8.0
    44944520         * @since 8.0.0 Adds the `$feed_id` parameter.
    44954521         *
    4496          * @param bool   $value   Defaults to true aka feeds are enabled.
     4522         * @param bool   $retval  Whether this feed is enabled or not.
    44974523         * @param string $feed_id The feed identifier.
    44984524         */
    4499         return (bool) apply_filters( 'bp_activity_enable_feeds', true, $feed_id );
     4525        return (bool) apply_filters( 'bp_activity_enable_feeds', $retval, $feed_id );
    45004526}
  • src/bp-core/admin/bp-core-admin-settings.php

    diff --git src/bp-core/admin/bp-core-admin-settings.php src/bp-core/admin/bp-core-admin-settings.php
    index a4ae985c8..dd3727ac9 100644
    function bp_admin_setting_callback_account_deletion() { 
    4747<?php
    4848}
    4949
     50/**
     51 * Enable private site functionality.
     52 *
     53 * @since 12.0.0
     54 *
     55 */
     56function bp_admin_setting_callback_community_visibility() {
     57        $visibility = bp_get_community_visibility( 'all' );
     58?>
     59        <select name="_bp_community_visibility[global]" id="_bp_community_visibility-global" aria-describedby="_bp_community_visibility_description" autocomplete="off">
     60                <option value="anyone" <?php echo selected( $visibility['global'], 'anyone' ); ?>><?php esc_html_e( 'Anyone', 'buddypress' ); ?></option>
     61                <option value="members" <?php echo selected( $visibility['global'], 'members' ); ?>><?php esc_html_e( 'Members Only', 'buddypress' ); ?></option>
     62        </select>
     63
     64        <p id="_bp_community_visibility_description" class="description"><?php esc_html_e( 'Choose "Anyone" to allow any visitor access to your community area. Choose "Members Only" to restrict access to your community area to logged-in members only.', 'buddypress' ); ?></p>
     65<?php
     66}
     67
     68/**
     69 * Sanitize the visibility setting when it is saved.
     70 *
     71 * @since 12.0.0
     72 *
     73 * @param mixed $saved_value The value passed to the save function.
     74 */
     75function bp_admin_sanitize_callback_community_visibility( $saved_value ) {
     76        $retval = array();
     77
     78        // Use the global setting, if it has been passed.
     79        $retval['global'] = isset( $saved_value['global'] ) ? $saved_value['global'] : 'anyone';
     80        // Ensure the global value is a valid option. Else, assume that the site is open.
     81        if ( ! in_array( $retval['global'], array( 'anyone', 'members' ), true ) ) {
     82                $retval['global'] = 'anyone';
     83        }
     84
     85        // Keys must be either 'global' or a component ID, but not register or activate.
     86        $directory_pages = bp_core_get_directory_pages();
     87        foreach ( $directory_pages as $component_id => $component_page ) {
     88                if ( in_array( $component_id, array( 'register', 'activate' ), true ) ) {
     89                        continue;
     90                }
     91
     92                // Use the global value if a specific value hasn't been set.
     93                $component_value = isset( $saved_value[ $component_id ] ) ? $saved_value[ $component_id ] : $retval['global'];
     94
     95                // Valid values are 'anyone' or 'memebers'.
     96                if ( ! in_array( $component_value, array( 'anyone', 'members' ), true ) ) {
     97                        $component_value = $retval['global'];
     98                }
     99                $retval[ $component_id ] = $component_value;
     100        }
     101
     102        return $saved_value;
     103}
     104
    50105/**
    51106 * Form element to change the active template pack.
    52107 */
  • src/bp-core/bp-core-caps.php

    diff --git src/bp-core/bp-core-caps.php src/bp-core/bp-core-caps.php
    index dd8288029..e2e569239 100644
    function bp_remove_caps() { 
    124124 * Map community caps to built in WordPress caps.
    125125 *
    126126 * @since 1.6.0
     127 * @since 12.0.0 Added mapping for `bp_view` capability.
    127128 *
    128129 * @see WP_User::has_cap() for description of the arguments passed to the
    129130 *      'map_meta_cap' filter.
    function bp_remove_caps() { 
    137138 */
    138139function bp_map_meta_caps( $caps, $cap, $user_id, $args ) {
    139140
     141        switch ( $cap ) {
     142                case 'bp_view' :
     143                        $caps = array( 'exist' );
     144                        if ( ! $user_id ) {
     145
     146                                // A BuddyPress component ID may be optionally passed with the `bp_view` check.
     147                                $component = isset( $args['bp_component'] ) ? $args['bp_component'] : '';
     148
     149                                if ( 'members' === bp_get_community_visibility( $component ) ) {
     150                                        $caps = array( 'do_not_allow' );
     151                                }
     152                        }
     153                        break;
     154        }
     155
    140156        /**
    141157         * Filters the community caps mapping to be built in WordPress caps.
    142158         *
  • src/bp-core/bp-core-functions.php

    diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php
    index b6ae3455d..2ca510bda 100644
    function bp_core_get_directory_page_id( $component = null ) { 
    668668        return $page_id;
    669669}
    670670
     671/**
     672 * Get the component ID corresponding to a directory page ID.
     673 *
     674 * @since 12.0.0
     675 *
     676 * @param int $page_id The ID of the directory page associated with the component.
     677 * @return int|false The slug representing the component. False if none is found.
     678 */
     679function bp_core_get_component_from_directory_page_id( $page_id = 0 ) {
     680        $bp_pages = bp_core_get_directory_page_ids( 'all' );
     681
     682        $component = false;
     683        foreach ( $bp_pages as $component_id => $p_id) {
     684                if ( $page_id === $p_id ) {
     685                        $component = $component_id;
     686                        break;
     687                }
     688        }
     689
     690        return $component;
     691}
     692
    671693/**
    672694 * Store the list of BP directory pages in the appropriate meta table.
    673695 *
    function bp_core_set_unique_directory_page_slug( $slug = '', $post_ID = 0, $post 
    969991                $pages = get_posts(
    970992                        array(
    971993                                'post__not_in' => array( $post_ID ),
    972                                 'post_status'  => array( 'publish', 'bp_restricted' ),
     994                                'post_status'  => bp_core_get_directory_pages_stati(),
    973995                                'post_type'    => array( 'buddypress', 'page' ),
    974996                        )
    975997                );
    function bp_get_component_navigations( $component = '' ) { 
    49494971
    49504972        return $navigations;
    49514973}
     4974
     4975/**
     4976 * Get the community visibility value calculated from the
     4977 * saved visibility setting.
     4978 *
     4979 * @since 12.0.0
     4980 *
     4981 * @param string $component Whether we want the visibility for a single component
     4982 *                          or for all components.
     4983 *
     4984 * @return arrary|string $retval The calculated visbility settings for the site.
     4985 */
     4986function bp_get_community_visibility( $component = 'global' ) {
     4987        $retval      = 'anyone';
     4988        $saved_value = (array) get_option( '_bp_community_visibility', array() );
     4989
     4990        // If the global value has not been set, we assume that the site is open.
     4991        if ( ! isset( $saved_value['global'] ) ) {
     4992                $saved_value['global'] = 'anyone';
     4993        }
     4994
     4995        if ( 'all' === $component ) {
     4996                // Build the component list.
     4997                $retval = array(
     4998                        'global' => $saved_value['global']
     4999                );
     5000                $directory_pages = bp_core_get_directory_pages();
     5001                foreach ( $directory_pages as $component_id => $component_page ) {
     5002                        if ( in_array( $component_id, array( 'register', 'activate' ), true ) ) {
     5003                                continue;
     5004                        }
     5005                        $retval[ $component_id ] = isset( $saved_value[ $component_id ] ) ? $saved_value[ $component_id ] : $saved_value['global'];
     5006                }
     5007        } else {
     5008                // We are checking a particular component.
     5009                // Fall back to the global value if not set.
     5010                $retval = isset( $saved_value[ $component ] ) ? $saved_value[ $component ] : $saved_value['global'];
     5011        }
     5012
     5013        /**
     5014         * Filter the community visibility value calculated from the
     5015         * saved visibility setting.
     5016         *
     5017         * @since 12.0.0
     5018         *
     5019         * @param arrary|string $retval    The calculated visbility settings for the site.
     5020         * @param string        $component The component value to get the visibility for.
     5021         */
     5022        return apply_filters( 'bp_get_community_visibility', $retval, $component );
     5023}
  • src/bp-core/classes/class-bp-admin.php

    diff --git src/bp-core/classes/class-bp-admin.php src/bp-core/classes/class-bp-admin.php
    index 173219099..ebb273415 100644
    class BP_Admin { 
    476476                add_settings_field( 'bp-disable-account-deletion', __( 'Account Deletion', 'buddypress' ), 'bp_admin_setting_callback_account_deletion', 'buddypress', 'bp_main' );
    477477                register_setting( 'buddypress', 'bp-disable-account-deletion', 'intval' );
    478478
     479                // Community Visibility
     480                add_settings_field( '_bp_community_visibility', __( 'Community Visibility', 'buddypress' ), 'bp_admin_setting_callback_community_visibility', 'buddypress', 'bp_main' );
     481                register_setting( 'buddypress', '_bp_community_visibility', 'bp_admin_sanitize_callback_community_visibility' );
     482
    479483                // Template pack picker.
    480484                add_settings_field( '_bp_theme_package_id', __( 'Template Pack', 'buddypress' ), 'bp_admin_setting_callback_theme_package_id', 'buddypress', 'bp_main', array( 'label_for' => '_bp_theme_package_id' ) );
    481485                register_setting( 'buddypress', '_bp_theme_package_id', 'sanitize_text_field' );
  • src/bp-core/classes/class-bp-component.php

    diff --git src/bp-core/classes/class-bp-component.php src/bp-core/classes/class-bp-component.php
    index 80adaf668..585e7b076 100644
    class BP_Component { 
    12571257         *
    12581258         * @since 12.0.0
    12591259         *
    1260          * @param  null     $retval A null value to use the regular WP Query.
    1261          * @param  WP_Query $query  The WP Query object.
     1260         * @param  null     $posts A null value to use the regular WP Query.
     1261         * @param  WP_Query $query The WP Query object.
    12621262         * @return null|array Null if not displaying a BuddyPress page.
    1263          *                    An array containing the BuddyPress directory post otherwise.
     1263         *                    An array containing the BuddyPress directory page otherwise.
    12641264         */
    1265         public function pre_query( $retval = null, $query = null ) {
     1265        public function pre_query( $posts = null, $query = null ) {
    12661266                remove_filter( 'posts_pre_query', array( $this, 'pre_query' ), 10 );
    12671267
    12681268                $queried_object = $query->get_queried_object();
    12691269
    12701270                if ( $queried_object instanceof WP_Post && 'buddypress' === get_post_type( $queried_object ) ) {
    1271                         // Only include the queried directory post into returned posts.
    1272                         $retval = array( $queried_object );
    1273 
    1274                         // Reset some query flags.
    1275                         $query->is_home       = false;
    1276                         $query->is_front_page = false;
    1277                         $query->is_page       = false;
    1278                         $query->is_archive    = false;
    1279                         $query->is_tax        = false;
    1280 
    1281                         if ( ! is_embed() ) {
    1282                                 $query->is_single = true;
     1271                        $component = bp_core_get_component_from_directory_page_id( $queried_object->ID );
     1272                        if ( bp_current_user_can( 'bp_view', array( 'bp_component' => $component ) ) ) {
     1273                                // Only include the queried directory post into returned posts.
     1274                                $posts = array( $queried_object );
     1275
     1276                                // Reset some query flags.
     1277                                $query->is_home       = false;
     1278                                $query->is_front_page = false;
     1279                                $query->is_page       = false;
     1280                                $query->is_archive    = false;
     1281                                $query->is_tax        = false;
     1282
     1283                                if ( ! is_embed() ) {
     1284                                        $query->is_single = true;
     1285                                }
     1286                        } else {
     1287                                // The current user may not access the directory page.
     1288                                $bp                    = buddypress();
     1289                                $bp->current_component = 'core';
     1290
     1291                                // Unset other BuddyPress URI globals.
     1292                                foreach ( array( 'current_item', 'current_action', 'action_variables', 'displayed_user' ) as $global ) {
     1293                                        if ( 'action_variables' === $global ) {
     1294                                                $bp->{$global} = array();
     1295                                        } elseif ( 'displayed_user' === $global ) {
     1296                                                $bp->{$global} = new \stdClass();
     1297                                        } else {
     1298                                                $bp->{$global} = '';
     1299                                        }
     1300                                }
     1301
     1302                                // Reset the post.
     1303                                $post = (object) array(
     1304                                        'ID'             => 0,
     1305                                        'post_type'      => 'buddypress',
     1306                                        'post_name'      => 'restricted',
     1307                                        'post_title'     => __( 'Members-only area', 'buddypress' ),
     1308                                        'post_content'   => bp_buffer_template_part( 'assets/utils/restricted-access-message', null, false ),
     1309                                        'comment_status' => 'closed',
     1310                                        'comment_count'  => 0,
     1311                                );
     1312
     1313                                // Reset the queried object.
     1314                                $query->queried_object    = get_post( $post );
     1315                                $query->queried_object_id = $query->queried_object->ID;
     1316
     1317                                // Reset the posts.
     1318                                $posts = array( $query->queried_object );
     1319
     1320                                // Reset some WP Query properties.
     1321                                $query->found_posts   = 1;
     1322                                $query->max_num_pages = 1;
     1323                                $query->posts         = $posts;
     1324                                $query->post          = $post;
     1325                                $query->post_count    = 1;
     1326                                $query->is_home       = false;
     1327                                $query->is_front_page = false;
     1328                                $query->is_page       = false;
     1329                                $query->is_single     = true;
     1330                                $query->is_archive    = false;
     1331                                $query->is_tax        = false;
     1332
     1333                                // Make sure no comments are displayed for this page.
     1334                                add_filter( 'comments_pre_query', 'bp_comments_pre_query', 10, 2 );
    12831335                        }
    1284                 }
    12851336
    1286                 return $retval;
     1337                        return $posts;
     1338                }
    12871339        }
    12881340
    12891341        /**
  • src/bp-core/classes/class-bp-core.php

    diff --git src/bp-core/classes/class-bp-core.php src/bp-core/classes/class-bp-core.php
    index 6c04ad080..396d39459 100644
    class BP_Core extends BP_Component { 
    397397                parent::register_post_types();
    398398        }
    399399
    400         /**
    401          * Set up the component post statuses.
    402          *
    403          * @since 12.0.0
    404          */
    405         public function register_post_statuses() {
    406                 register_post_status(
    407                         'bp_restricted',
    408                         array(
    409                                 'label'    => _x( 'Restricted to members', '`buddypress` post type post status', 'buddypress' ),
    410                                 'public'   => false,
    411                                 'internal' => true,
    412                         )
    413                 );
    414 
    415                 parent::register_post_statuses();
    416         }
    417 
    418400        /**
    419401         * Parse the WP_Query and eventually set the BP Search mechanism.
    420402         *
  • new file src/bp-templates/bp-legacy/buddypress/assets/utils/restricted-access-message.php

    diff --git src/bp-templates/bp-legacy/buddypress/assets/utils/restricted-access-message.php src/bp-templates/bp-legacy/buddypress/assets/utils/restricted-access-message.php
    new file mode 100644
    index 000000000..554f71e36
    - +  
     1<?php
     2/**
     3 * Message to inform the community is restricted to members.
     4 *
     5 * @package BuddyPress
     6 * @subpackage bp-legacy
     7 *
     8 * @since 12.0.0
     9 */
     10
     11// Exit if accessed directly.
     12if ( ! defined( 'ABSPATH' ) ) {
     13        exit;
     14}
     15?>
     16<!-- wp:paragraph {"align":"center"} -->
     17<p class="has-text-align-center"><?php esc_html_e( 'This community area is accessible to logged-in members only.', 'buddypress' ); ?></p>
     18<!-- /wp:paragraph -->
     19
     20<!-- wp:columns -->
     21<div class="wp-block-columns"><!-- wp:column {"width":"25%"} -->
     22<div class="wp-block-column" style="flex-basis:25%"></div>
     23<!-- /wp:column -->
     24
     25<!-- wp:column {"width":"50%"} -->
     26<div class="wp-block-column" style="flex-basis:50%"><!-- wp:bp/login-form {"forgotPwdLink":true} /--></div>
     27<!-- /wp:column -->
     28
     29<!-- wp:column {"width":"25%"} -->
     30<div class="wp-block-column" style="flex-basis:25%"></div>
     31<!-- /wp:column --></div>
     32<!-- /wp:columns -->
  • new file src/bp-templates/bp-nouveau/buddypress/assets/utils/restricted-access-message.php

    diff --git src/bp-templates/bp-nouveau/buddypress/assets/utils/restricted-access-message.php src/bp-templates/bp-nouveau/buddypress/assets/utils/restricted-access-message.php
    new file mode 100644
    index 000000000..a995fe119
    - +  
     1<?php
     2/**
     3 * Message to inform the community is restricted to members.
     4 *
     5 * @package BuddyPress
     6 * @subpackage bp-nouveau
     7 *
     8 * @since 12.0.0
     9 */
     10
     11// Exit if accessed directly.
     12if ( ! defined( 'ABSPATH' ) ) {
     13        exit;
     14}
     15?>
     16<!-- wp:paragraph {"align":"center"} -->
     17<p class="has-text-align-center"><?php esc_html_e( 'This community area is accessible to logged-in members only.', 'buddypress' ); ?></p>
     18<!-- /wp:paragraph -->
     19
     20<!-- wp:columns -->
     21<div class="wp-block-columns"><!-- wp:column {"width":"25%"} -->
     22<div class="wp-block-column" style="flex-basis:25%"></div>
     23<!-- /wp:column -->
     24
     25<!-- wp:column {"width":"50%"} -->
     26<div class="wp-block-column" style="flex-basis:50%"><!-- wp:bp/login-form {"forgotPwdLink":true} /--></div>
     27<!-- /wp:column -->
     28
     29<!-- wp:column {"width":"25%"} -->
     30<div class="wp-block-column" style="flex-basis:25%"></div>
     31<!-- /wp:column --></div>
     32<!-- /wp:columns -->
  • new file tests/phpunit/testcases/core/community-visibility.php

    diff --git tests/phpunit/testcases/core/community-visibility.php tests/phpunit/testcases/core/community-visibility.php
    new file mode 100644
    index 000000000..5ce8ec324
    - +  
     1<?php
     2/**
     3 * @group bp_community_visibility
     4 */
     5class BP_Tests_BP_Community_Visibility_TestCases extends BP_UnitTestCase {
     6        protected $old_user;
     7        protected $logged_in_user;
     8
     9        public function set_up() {
     10                parent::set_up();
     11                $this->old_user = get_current_user_id();
     12                $this->logged_in_user = self::factory()->user->create();
     13                $this->set_current_user( $this->logged_in_user );
     14
     15                // Save a typical setting.
     16                $setting = array(
     17                        'global' => 'members',
     18                );
     19                update_option( '_bp_community_visibility', $setting );
     20        }
     21
     22        public function tear_down() {
     23                parent::tear_down();
     24                $this->set_current_user( $this->old_user );
     25                // Reset site to totally open.
     26                delete_option( '_bp_community_visibility' );
     27        }
     28
     29        // Test that logged-in user has access to component marked anyone and component marked members
     30        public function test_bp_community_visibility_allow_visibility_for_logged_in_user() {
     31                $this->assertTrue( bp_user_can( $this->logged_in_user, 'bp_view' ) );
     32        }
     33
     34        // Test that anonymous user does not have access
     35        public function test_bp_community_visibility_enforce_visibility_for_anon_user() {
     36                $this->assertFalse( bp_user_can( 0, 'bp_view' ) );
     37        }
     38
     39        // Bad component ID should use global setting.
     40        public function test_bp_community_visibility_bad_component_id() {
     41                $this->assertFalse( bp_user_can( 0, 'bp_view', array( 'bp_component' => 'blerg' ) ) );
     42                $this->assertTrue( bp_user_can( $this->logged_in_user, 'bp_view', array( 'bp_component' => 'blerg' ) ) );
     43        }
     44
     45        // No saved setting should be open access for anonymous users and logged in users.
     46        public function test_bp_community_visibility_no_saved_setting() {
     47                delete_option( '_bp_community_visibility' );
     48                // No saved setting should result in the site being open to anyone.
     49                $this->assertTrue( bp_user_can( 0, 'bp_view' ) );
     50                $this->assertTrue( bp_user_can( $this->logged_in_user, 'bp_view' ) );
     51        }
     52
     53        // Ensure that "anyone" setting allows access to everyone.
     54        public function test_bp_community_visibility_access_allowed() {
     55                $setting = array(
     56                        'global'      => 'anyone',
     57                );
     58                update_option( '_bp_community_visibility', $setting );
     59                $this->assertTrue( bp_user_can( 0, 'bp_view' ) );
     60                $this->assertTrue( bp_user_can( $this->logged_in_user, 'bp_view' ) );
     61        }
     62
     63        // Make sure fallback logic works for mixed-up setting values.
     64        public function test_bp_community_visibility_fallback_setting() {
     65                // Save a partial setting.
     66                $setting = array(
     67                        'global'      => 'members',
     68                        'members'     => 'anyone',
     69                );
     70                update_option( '_bp_community_visibility', $setting );
     71                $this->assertTrue( 'members' === bp_get_community_visibility( 'groups' ) );
     72        }
     73}