Ticket #8734: 8734.03.patch
| File 8734.03.patch, 20.2 KB (added by , 3 years ago) |
|---|
-
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 ) { 3304 3304 $user_id = bp_loggedin_user_id(); 3305 3305 } 3306 3306 3307 if ( ! bp_current_user_can( 'bp_view', array( 'bp_component' => 'activity' ) ) ) { 3308 $retval = false; 3309 } 3310 3307 3311 // 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' ) ) ) { 3309 3313 // Check to see if the user has access to the activity's parent group. 3310 3314 $group = groups_get_group( $activity->item_id ); 3311 3315 if ( $group ) { … … function bp_activity_personal_data_exporter( $email_address, $page ) { 4482 4486 * Checks whether an activity feed is enabled. 4483 4487 * 4484 4488 * @since 8.0.0 4489 * @since 12.0.0 Added bp_current_user_can( 'bp_view' ) check. 4485 4490 * 4486 4491 * @param string $feed_id The feed identifier. Possible values are: 4487 4492 * 'sitewide', 'personal', 'friends', 'mygroups', 'mentions', 'favorites'. 4488 4493 */ 4489 4494 function 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 4490 4516 /** 4491 4517 * Filters if BuddyPress should consider feeds enabled. If disabled, it will return early. 4492 4518 * 4493 4519 * @since 1.8.0 4494 4520 * @since 8.0.0 Adds the `$feed_id` parameter. 4495 4521 * 4496 * @param bool $ value Defaults to true aka feeds are enabled.4522 * @param bool $retval Whether this feed is enabled or not. 4497 4523 * @param string $feed_id The feed identifier. 4498 4524 */ 4499 return (bool) apply_filters( 'bp_activity_enable_feeds', true, $feed_id );4525 return (bool) apply_filters( 'bp_activity_enable_feeds', $retval, $feed_id ); 4500 4526 } -
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() { 47 47 <?php 48 48 } 49 49 50 /** 51 * Enable private site functionality. 52 * 53 * @since 12.0.0 54 * 55 */ 56 function 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 */ 75 function 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 50 105 /** 51 106 * Form element to change the active template pack. 52 107 */ -
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() { 124 124 * Map community caps to built in WordPress caps. 125 125 * 126 126 * @since 1.6.0 127 * @since 12.0.0 Added mapping for `bp_view` capability. 127 128 * 128 129 * @see WP_User::has_cap() for description of the arguments passed to the 129 130 * 'map_meta_cap' filter. … … function bp_remove_caps() { 137 138 */ 138 139 function bp_map_meta_caps( $caps, $cap, $user_id, $args ) { 139 140 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 140 156 /** 141 157 * Filters the community caps mapping to be built in WordPress caps. 142 158 * -
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 ) { 668 668 return $page_id; 669 669 } 670 670 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 */ 679 function 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 671 693 /** 672 694 * Store the list of BP directory pages in the appropriate meta table. 673 695 * … … function bp_core_set_unique_directory_page_slug( $slug = '', $post_ID = 0, $post 969 991 $pages = get_posts( 970 992 array( 971 993 'post__not_in' => array( $post_ID ), 972 'post_status' => array( 'publish', 'bp_restricted'),994 'post_status' => bp_core_get_directory_pages_stati(), 973 995 'post_type' => array( 'buddypress', 'page' ), 974 996 ) 975 997 ); … … function bp_get_component_navigations( $component = '' ) { 4949 4971 4950 4972 return $navigations; 4951 4973 } 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 */ 4986 function 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 { 476 476 add_settings_field( 'bp-disable-account-deletion', __( 'Account Deletion', 'buddypress' ), 'bp_admin_setting_callback_account_deletion', 'buddypress', 'bp_main' ); 477 477 register_setting( 'buddypress', 'bp-disable-account-deletion', 'intval' ); 478 478 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 479 483 // Template pack picker. 480 484 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' ) ); 481 485 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 { 1257 1257 * 1258 1258 * @since 12.0.0 1259 1259 * 1260 * @param null $ retvalA 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. 1262 1262 * @return null|array Null if not displaying a BuddyPress page. 1263 * An array containing the BuddyPress directory p ostotherwise.1263 * An array containing the BuddyPress directory page otherwise. 1264 1264 */ 1265 public function pre_query( $ retval= null, $query = null ) {1265 public function pre_query( $posts = null, $query = null ) { 1266 1266 remove_filter( 'posts_pre_query', array( $this, 'pre_query' ), 10 ); 1267 1267 1268 1268 $queried_object = $query->get_queried_object(); 1269 1269 1270 1270 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 ); 1283 1335 } 1284 }1285 1336 1286 return $retval; 1337 return $posts; 1338 } 1287 1339 } 1288 1340 1289 1341 /** -
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 { 397 397 parent::register_post_types(); 398 398 } 399 399 400 /**401 * Set up the component post statuses.402 *403 * @since 12.0.0404 */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 418 400 /** 419 401 * Parse the WP_Query and eventually set the BP Search mechanism. 420 402 * -
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. 12 if ( ! 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. 12 if ( ! 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 */ 5 class 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 }