Ticket #8139: 8139.05.patch
File 8139.05.patch, 163.1 KB (added by , 3 years ago) |
---|
-
src/bp-core/admin/bp-core-admin-functions.php
diff --git src/bp-core/admin/bp-core-admin-functions.php src/bp-core/admin/bp-core-admin-functions.php index 7749dd449..3096ba338 100644
function bp_core_modify_admin_menu_highlight() { 86 86 } 87 87 88 88 // Keep the BuddyPress tools menu highlighted. 89 if ( 'bp-optouts' === $plugin_page ) {89 if ( 'bp-optouts' === $plugin_page || 'bp-members-invitations' === $plugin_page ) { 90 90 $submenu_file = 'bp-tools'; 91 91 } 92 92 } … … function bp_core_activation_notice() { 284 284 285 285 // Activate and Register are special cases. They are not components but they need WP pages. 286 286 // If user registration is disabled, we can skip this step. 287 if ( bp_get_signup_allowed() ) {287 if ( bp_get_signup_allowed() || bp_get_members_invitations_allowed() ) { 288 288 $wp_page_components[] = array( 289 289 'id' => 'activate', 290 290 'name' => __( 'Activate', 'buddypress' ), … … function bp_core_get_admin_tabs( $active_tab = '', $context = 'settings' ) { 479 479 'name' => __( 'Repair', 'buddypress' ), 480 480 ), 481 481 '1' => array( 482 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-members-invitations' ), $tools_page ) ), 483 'name' => __( 'Manage Invitations', 'buddypress' ), 484 ), 485 '2' => array( 482 486 'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-optouts' ), $tools_page ) ), 483 487 'name' => __( 'Manage Opt-outs', 'buddypress' ), 484 488 ), -
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 c09f809ca..b37b914ff 100644
function bp_admin_setting_callback_cover_image_uploads() { 182 182 <?php 183 183 } 184 184 185 /** 186 * Allow members to invite non-members to the network. 187 * 188 * @since 8.0.0 189 */ 190 function bp_admin_setting_callback_members_invitations() { 191 ?> 192 <input id="bp-enable-members-invitations" name="bp-enable-members-invitations" type="checkbox" value="1" <?php checked( bp_get_members_invitations_allowed() ); ?> /> 193 <label for="bp-enable-members-invitations"><?php _e( 'Allow registered members to invite people to join this network', 'buddypress' ); ?></label> 194 <?php if ( ! bp_get_signup_allowed() ) : ?> 195 <p class="description"><?php _e( 'Public registration is currently disabled. However, invitees will still be able to register if network invitations are enabled.', 'buddypress' ); ?></p> 196 <?php endif; ?> 197 <?php 198 /** 199 * Fires after the output of the invitations settings section. 200 * 201 * @since 8.0.0 202 */ 203 do_action( 'bp_admin_settings_after_members_invitations' ); 204 } 205 185 206 /** XProfile ******************************************************************/ 186 207 187 208 /** -
src/bp-core/admin/bp-core-admin-slugs.php
diff --git src/bp-core/admin/bp-core-admin-slugs.php src/bp-core/admin/bp-core-admin-slugs.php index 8fb9b9a40..52ef6e36c 100644
function bp_core_admin_slugs_options() { 187 187 188 188 <h3><?php _e( 'Registration', 'buddypress' ); ?></h3> 189 189 190 <?php if ( bp_get_signup_allowed() ) : ?>190 <?php if ( bp_get_signup_allowed() || bp_get_members_invitations_allowed() ) : ?> 191 191 <p><?php _e( 'Associate WordPress Pages with the following BuddyPress Registration pages.', 'buddypress' ); ?></p> 192 192 <?php else : ?> 193 193 <?php if ( is_multisite() ) : ?> … … function bp_core_admin_slugs_options() { 210 210 <table class="form-table"> 211 211 <tbody> 212 212 213 <?php if ( bp_get_signup_allowed() ) : foreach ( $static_pages as $name => $label ) : ?>213 <?php if ( bp_get_signup_allowed() || bp_get_members_invitations_allowed() ) : foreach ( $static_pages as $name => $label ) : ?> 214 214 215 215 <tr valign="top"> 216 216 <th scope="row"> -
src/bp-core/admin/bp-core-admin-tools.php
diff --git src/bp-core/admin/bp-core-admin-tools.php src/bp-core/admin/bp-core-admin-tools.php index 8141eccbe..245252360 100644
function bp_core_admin_available_tools_intro() { 558 558 ); 559 559 ?> 560 560 </dd> 561 562 <dt><?php esc_html_e( 'Manage Invitations', 'buddypress' ) ?></dt> 563 <dd> 564 <?php esc_html_e( 'When enabled, BuddyPress allows your users to invite nonmembers to join your site.', 'buddypress' ); ?> 565 <?php 566 $url = add_query_arg( 'page', 'bp-members-invitations', bp_get_admin_url( $page ) ); 567 printf( 568 /* translators: %s: the link to the BuddyPress Invitations management tool screen */ 569 esc_html_x( 'Visit %s to manage your site’s invitations.', 'buddypress invitations tool intro', 'buddypress' ), 570 '<a href="' . esc_url( $url ) . '">' . esc_html__( 'Invitations', 'buddypress' ) . '</a>' 571 ); 572 ?> 573 </dd> 574 561 575 <dt><?php esc_html_e( 'Manage Opt-outs', 'buddypress' ) ?></dt> 562 576 <dd> 563 577 <?php esc_html_e( 'BuddyPress stores opt-out requests from people who are not members of this site, but have been contacted via communication from this site, and wish to opt-out from future communication.', 'buddypress' ); ?> 564 578 <?php 565 579 $url = add_query_arg( 'page', 'bp-optouts', bp_get_admin_url( $page ) ); 566 580 printf( 567 /* translators: %s: the link to the BuddyPress Nonmember Opt-outs */581 /* translators: %s: the link to the BuddyPress Nonmember Opt-outs management tool screen */ 568 582 esc_html_x( 'Visit %s to manage your site’s opt-out requests.', 'buddypress opt-outs intro', 'buddypress' ), 569 583 '<a href="' . esc_url( $url ) . '">' . esc_html__( 'Nonmember Opt-outs', 'buddypress' ) . '</a>' 570 584 ); -
src/bp-core/bp-core-filters.php
diff --git src/bp-core/bp-core-filters.php src/bp-core/bp-core-filters.php index 735c7090a..219816b05 100644
function bp_email_set_default_headers( $headers, $property, $transform, $email ) 1068 1068 // Add 'List-Unsubscribe' header if applicable. 1069 1069 if ( ! empty( $tokens['unsubscribe'] ) && $tokens['unsubscribe'] !== wp_login_url() ) { 1070 1070 $user = get_user_by( 'email', $tokens['recipient.email'] ); 1071 $user_id = isset( $user->ID ) ? $user->ID : 0; 1071 1072 1072 $ link = bp_email_get_unsubscribe_link(array(1073 'user_id' => $user ->ID,1073 $args = array( 1074 'user_id' => $user_id, 1074 1075 'notification_type' => $email->get( 'type' ), 1075 ) ); 1076 ); 1077 // If this email is not to a current member, include the nonmember's email address. 1078 if ( ! $user_id ) { 1079 $args['email_address'] = $tokens['recipient.email']; 1080 } 1081 1082 $link = bp_email_get_unsubscribe_link( $args ); 1076 1083 1077 1084 if ( ! empty( $link ) ) { 1078 1085 $headers['List-Unsubscribe'] = sprintf( '<%s>', esc_url_raw( $link ) ); -
src/bp-core/bp-core-functions.php
diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php index afb941bf8..63ed2de5f 100644
function bp_core_add_page_mappings( $components, $existing = 'keep' ) { 702 702 703 703 // Register and Activate are not components, but need pages when 704 704 // registration is enabled. 705 if ( bp_get_signup_allowed() ) {705 if ( bp_get_signup_allowed() || bp_get_members_invitations_allowed() ) { 706 706 foreach ( array( 'register', 'activate' ) as $slug ) { 707 707 if ( ! isset( $pages[ $slug ] ) ) { 708 708 $pages_to_create[ $slug ] = $page_titles[ $slug ]; … … function bp_send_email( $email_type, $to, $args = array() ) { 3472 3472 // From, subject, content are set automatically. 3473 3473 if ( 'settings-verify-email-change' === $email_type && isset( $args['tokens']['displayname'] ) ) { 3474 3474 $email->set_to( $to, $args['tokens']['displayname'] ); 3475 // Emails sent to nonmembers will have no recipient.name populated. 3476 } else if ( 'bp-members-invitation' === $email_type ) { 3477 $email->set_to( $to, $to ); 3475 3478 } else { 3476 3479 $email->set_to( $to ); 3477 3480 } … … function bp_email_get_schema() { 3807 3810 /* translators: do not remove {} brackets or translate its contents. */ 3808 3811 'post_title' => __( '[{{{site.name}}}] You have an invitation to the group: "{{group.name}}"', 'buddypress' ), 3809 3812 /* translators: do not remove {} brackets or translate its contents. */ 3810 'post_content' => __( "<a href=\"{{{inviter.url}}}\">{{inviter.name}}</a> has invited you to join the group: "{{group.name}}".\n {{invite.message}}\n<a href=\"{{{invites.url}}}\">Go here to accept your invitation</a> or <a href=\"{{{group.url}}}\">visit the group</a> to learn more.", 'buddypress' ),3813 'post_content' => __( "<a href=\"{{{inviter.url}}}\">{{inviter.name}}</a> has invited you to join the group: "{{group.name}}".\n\n{{invite.message}}\n\n<a href=\"{{{invites.url}}}\">Go here to accept your invitation</a> or <a href=\"{{{group.url}}}\">visit the group</a> to learn more.", 'buddypress' ), 3811 3814 /* translators: do not remove {} brackets or translate its contents. */ 3812 'post_excerpt' => __( "{{inviter.name}} has invited you to join the group: \"{{group.name}}\".\n\n To accept your invitation, visit: {{{invites.url}}}\n\nTo learn more about the group, visit: {{{group.url}}}.\nTo view {{inviter.name}}'s profile, visit: {{{inviter.url}}}", 'buddypress' ),3815 'post_excerpt' => __( "{{inviter.name}} has invited you to join the group: \"{{group.name}}\".\n\n{{invite.message}}\n\nTo accept your invitation, visit: {{{invites.url}}}\n\nTo learn more about the group, visit: {{{group.url}}}.\nTo view {{inviter.name}}'s profile, visit: {{{inviter.url}}}", 'buddypress' ), 3813 3816 ), 3814 3817 'groups-member-promoted' => array( 3815 3818 /* translators: do not remove {} brackets or translate its contents. */ … … function bp_email_get_schema() { 3859 3862 /* translators: do not remove {} brackets or translate its contents. */ 3860 3863 'post_excerpt' => __( "Your membership request for the group \"{{group.name}}\" has been rejected.\n\nTo request membership again, visit: {{{group.url}}}", 'buddypress' ), 3861 3864 ), 3865 'bp-members-invitation' => array( 3866 /* translators: do not remove {} brackets or translate its contents. */ 3867 'post_title' => __( '{{inviter.name}} has invited you to join {{site.name}}', 'buddypress' ), 3868 /* translators: do not remove {} brackets or translate its contents. */ 3869 'post_content' => __( "<a href=\"{{{inviter.url}}}\">{{inviter.name}}</a> has invited you to join the site: "{{site.name}}".\n\n{{usermessage}}\n\n<a href=\"{{{invite.accept_url}}}\">Accept your invitation</a> or <a href=\"{{{site.url}}}\">visit the site</a> to learn more.", 'buddypress' ), 3870 /* translators: do not remove {} brackets or translate its contents. */ 3871 'post_excerpt' => __( "{{inviter.name}} has invited you to join the site: \"{{site.name}}\".\n\n{{usermessage}}\n\nTo accept your invitation, visit: {{{invite.accept_url}}}\n\nTo learn more about the site, visit: {{{site.url}}}.\nTo view {{inviter.name}}'s profile, visit: {{{inviter.url}}}", 'buddypress' ), 3872 ), 3862 3873 ) ); 3863 3874 } 3864 3875 … … function bp_email_get_type_schema( $field = 'description' ) { 4000 4011 ), 4001 4012 ); 4002 4013 4014 $members_invitation = array( 4015 'description' => __( 'A site member has sent a site invitation to the recipient.', 'buddypress' ), 4016 'unsubscribe' => array( 4017 'meta_key' => 'notification_bp_members_invite', 4018 'message' => __( 'You will no longer receive emails when you are invited to join a site.', 'buddypress' ), 4019 ), 4020 ); 4021 4003 4022 $types = array( 4004 4023 'activity-comment' => $activity_comment, 4005 4024 'activity-comment-author' => $activity_comment_author, … … function bp_email_get_type_schema( $field = 'description' ) { 4017 4036 'settings-verify-email-change' => $settings_verify_email_change, 4018 4037 'groups-membership-request-accepted' => $groups_membership_request_accepted, 4019 4038 'groups-membership-request-rejected' => $groups_membership_request_rejected, 4039 'bp-members-invitation' => $members_invitation, 4020 4040 ); 4021 4041 4022 4042 if ( $field !== 'all' ) { … … function bp_email_unsubscribe_handler() { 4036 4056 $raw_email_type = ! empty( $_GET['nt'] ) ? $_GET['nt'] : ''; 4037 4057 $raw_hash = ! empty( $_GET['nh'] ) ? $_GET['nh'] : ''; 4038 4058 $raw_user_id = ! empty( $_GET['uid'] ) ? absint( $_GET['uid'] ) : 0; 4039 $new_hash = hash_hmac( 'sha1', "{$raw_email_type}:{$raw_user_id}", bp_email_get_salt() ); 4059 $raw_user_email = ! empty( $_GET['uem'] ) ? $_GET['uem'] : ''; 4060 4061 $new_hash = ''; 4062 if ( ! empty( $raw_user_id ) ) { 4063 $new_hash = hash_hmac( 'sha1', "{$raw_email_type}:{$raw_user_id}", bp_email_get_salt() ); 4064 } else if ( ! empty( $raw_user_email ) ) { 4065 $new_hash = hash_hmac( 'sha1', "{$raw_email_type}:{$raw_user_email}", bp_email_get_salt() ); 4066 } 4040 4067 4041 4068 // Check required values. 4042 if ( ! $raw_user_id|| ! $raw_email_type || ! $raw_hash || ! array_key_exists( $raw_email_type, $emails ) ) {4069 if ( ( ! $raw_user_id && ! $raw_user_email ) || ! $raw_email_type || ! $raw_hash || ! array_key_exists( $raw_email_type, $emails ) ) { 4043 4070 $redirect_to = wp_login_url(); 4044 4071 $result_msg = __( 'Something has gone wrong.', 'buddypress' ); 4045 4072 $unsub_msg = __( 'Please log in and go to your settings to unsubscribe from notification emails.', 'buddypress' ); … … function bp_email_unsubscribe_handler() { 4065 4092 $redirect_to = bp_core_get_user_domain( get_current_user_id() ); 4066 4093 } 4067 4094 4095 // This is an unsubscribe request from a nonmember. 4096 } else if ( $raw_user_email ) { 4097 // Unsubscribe. 4098 error_log( 'caught unsubscribe request {$raw_user_email}' ); 4099 // @TODO: Create opt-out once opt-out logic is in place. 4100 $redirect_to = home_url(); 4101 4102 $result_msg = $emails[ $raw_email_type ]['unsubscribe']['message']; 4103 $unsub_msg = __( 'You have been unsubscribed.' ); 4104 // This is an unsubscribe request from a current member. 4068 4105 } else { 4069 4106 if ( bp_is_active( 'settings' ) ) { 4070 4107 $redirect_to = sprintf( … … function bp_email_unsubscribe_handler() { 4092 4129 ); 4093 4130 4094 4131 bp_core_add_message( $message ); 4095 bp_core_redirect( bp_core_get_user_domain( $raw_user_id ) ); 4132 4133 $page_redirect = ''; 4134 if ( $raw_user_id ) { 4135 $page_redirect = bp_core_get_user_domain( $raw_user_id ); 4136 } 4137 4138 bp_core_redirect(); 4096 4139 4097 4140 exit; 4098 4141 } … … function bp_email_unsubscribe_handler() { 4109 4152 * @type string $notification_type Which notification type is being sent. 4110 4153 * @type string $user_id The ID of the user to whom the notification is sent. 4111 4154 * @type string $redirect_to Optional. The url to which the user will be redirected. Default is the activity directory. 4155 * @type string $email Optional. The email address of the user to whom the notification is sent. 4112 4156 * } 4113 4157 * @return string The unsubscribe link. 4114 4158 */ … … function bp_email_get_unsubscribe_link( $args ) { 4128 4172 return ''; 4129 4173 } 4130 4174 4131 $link = add_query_arg( 4132 array( 4133 'action' => 'unsubscribe', 4134 'nh' => hash_hmac( 'sha1', "{$email_type}:{$user_id}", bp_email_get_salt() ), 4135 'nt' => $args['notification_type'], 4136 'uid' => $user_id, 4137 ), 4138 $redirect_to 4139 ); 4175 $link = ''; 4176 // Case where the recipient is a member of the site. 4177 if ( ! empty( $user_id ) ) { 4178 $link = add_query_arg( 4179 array( 4180 'action' => 'unsubscribe', 4181 'nh' => hash_hmac( 'sha1', "{$email_type}:{$user_id}", bp_email_get_salt() ), 4182 'nt' => $args['notification_type'], 4183 'uid' => $user_id, 4184 ), 4185 $redirect_to 4186 ); 4187 // Case where the recipient is not a member of the site. 4188 } else if ( ! empty( $args['email_address'] ) ) { 4189 $email_address = $args['email_address']; 4190 $link = add_query_arg( 4191 array( 4192 'action' => 'unsubscribe', 4193 'nh' => hash_hmac( 'sha1', "{$email_type}:{$email_address}", bp_email_get_salt() ), 4194 'nt' => $args['notification_type'], 4195 'uid' => $user_id, 4196 'uem' => $email_address, 4197 ), 4198 $redirect_to 4199 ); 4200 } 4140 4201 4141 4202 /** 4142 4203 * Filters the unsubscribe link. … … function bp_get_optouts( $args = array() ) { 4347 4408 return $optout_class::get( $args ); 4348 4409 } 4349 4410 4411 /** 4412 * Check an email address to see if that individual has opted out. 4413 * 4414 * @since 8.0.0 4415 * 4416 * @param string $email_address Email address to check. 4417 * @return bool True if the user has opted out, false otherwise. 4418 */ 4419 function bp_user_has_opted_out( $email_address = '' ) { 4420 $optout_class = new BP_Optout(); 4421 $optout_id = $optout_class->optout_exists( 4422 array( 4423 'email_address' => $email_address, 4424 ) 4425 ); 4426 return (bool) $optout_id; 4427 } 4428 4350 4429 /** 4351 4430 * Delete a BP_Optout by ID. 4352 4431 * -
src/bp-core/bp-core-template.php
diff --git src/bp-core/bp-core-template.php src/bp-core/bp-core-template.php index 799a69cdc..e840a7cd6 100644
function bp_is_settings_component() { 2247 2247 return (bool) bp_is_current_component( 'settings' ); 2248 2248 } 2249 2249 2250 /** 2251 * Check whether the current page is an Invitations screen. 2252 * 2253 * @since 8.0.0 2254 * 2255 * @return bool True if the current page is an Invitations screen. 2256 */ 2257 function bp_is_members_invitations_screen() { 2258 return (bool) bp_is_current_component( bp_get_members_invitations_slug() ); 2259 } 2260 2250 2261 /** 2251 2262 * Is the current component an active core component? 2252 2263 * … … function bp_is_user_settings_profile() { 2647 2658 return (bool) ( bp_is_user_settings() && bp_is_current_action( 'profile' ) ); 2648 2659 } 2649 2660 2661 /** 2662 * Is the current page a user's community invitations page? 2663 * 2664 * Eg http://example.com/members/cassie/invitations/ (or a subpage thereof). 2665 * 2666 * @since 8.0.0 2667 * 2668 * @return bool True if the current page is a user's community invitations page. 2669 */ 2670 function bp_is_user_members_invitations() { 2671 return (bool) ( bp_is_user() && bp_is_members_invitations_screen() ); 2672 } 2673 2674 /** 2675 * Is the current page a user's List Invites page? 2676 * 2677 * Eg http://example.com/members/cassie/invitations/list-invites/. 2678 * 2679 * @since 8.0.0 2680 * 2681 * @return bool True if the current page is a user's List Invites page. 2682 */ 2683 function bp_is_user_members_invitations_list() { 2684 return (bool) ( bp_is_user_members_invitations() && bp_is_current_action( 'list-invites' ) ); 2685 } 2686 2687 /** 2688 * Is the current page a user's Send Invites page? 2689 * 2690 * Eg http://example.com/members/cassie/invitations/send-invites/. 2691 * 2692 * @since 8.0.0 2693 * 2694 * @return bool True if the current page is a user's Send Invites page. 2695 */ 2696 function bp_is_user_members_invitations_send_screen() { 2697 return (bool) ( bp_is_user_members_invitations() && bp_is_current_action( 'send-invites' ) ); 2698 } 2699 2650 2700 /** Groups ********************************************************************/ 2651 2701 2652 2702 /** -
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 1e10deab7..bbf945471 100644
class BP_Admin { 411 411 register_setting( 'buddypress', 'bp-disable-cover-image-uploads', 'intval' ); 412 412 } 413 413 414 // Community Invitations. 415 if ( bp_is_active( 'members', 'invitations' ) ) { 416 add_settings_field( 'bp-enable-members-invitations', __( 'Invitations', 'buddypress' ), 'bp_admin_setting_callback_members_invitations', 'buddypress', 'bp_members' ); 417 register_setting( 'buddypress', 'bp-enable-members-invitations', 'intval' ); 418 } 419 414 420 /* XProfile Section **************************************************/ 415 421 416 422 if ( bp_is_active( 'xprofile' ) ) { -
src/bp-core/classes/class-bp-invitation-manager.php
diff --git src/bp-core/classes/class-bp-invitation-manager.php src/bp-core/classes/class-bp-invitation-manager.php index 0b7d2f009..726a78da4 100644
abstract class BP_Invitation_Manager { 99 99 return false; 100 100 } 101 101 102 // If an email address is specified, it must be a valid email address. 103 if ( $r['invitee_email'] && ! is_email( $r['invitee_email'] ) ) { 104 return false; 105 } 106 102 107 /** 103 108 * Is this user allowed to extend invitations in this situation? 104 109 * … … abstract class BP_Invitation_Manager { 157 162 * @param int $invitation_id ID of invitation to send. 158 163 * @param array $args See BP_Invitation::mark_sent(). 159 164 * 160 * @return int|bool The number of rows updated, or false on error.165 * @return bool The result of `run_send_action()`. 161 166 */ 162 167 public function send_invitation_by_id( $invitation_id = 0, $args = array() ) { 163 168 $updated = false; … … abstract class BP_Invitation_Manager { 195 200 } 196 201 197 202 // Perform the send action. 198 $ this->run_send_action( $invitation );203 $success = $this->run_send_action( $invitation ); 199 204 200 $updated = BP_Invitation::mark_sent( $invitation->id, $args ); 205 if ( $success ) { 206 BP_Invitation::mark_sent( $invitation->id, $args ); 207 } 201 208 202 return $ updated;209 return $success; 203 210 } 204 211 205 212 /** … … abstract class BP_Invitation_Manager { 309 316 * @param int $request_id ID of request to send. 310 317 * @param array $args See BP_Invitation::mark_sent(). 311 318 * 312 * @return int|bool The number of rows updated, or false on error.319 * @return bool The result of `run_send_action()`. 313 320 */ 314 321 public function send_request_notification_by_id( $request_id = 0, $args = array() ) { 315 322 $updated = false; … … abstract class BP_Invitation_Manager { 342 349 } 343 350 344 351 // Perform the send action. 345 $ this->run_send_action( $request );352 $success = $this->run_send_action( $request ); 346 353 347 $updated = BP_Invitation::mark_sent( $request->id, $args ); 354 if ( $success ) { 355 BP_Invitation::mark_sent( $request->id, $args ); 356 } 348 357 349 return $ updated;358 return $success; 350 359 } 351 360 352 361 /** Retrieve ******************************************************************/ … … abstract class BP_Invitation_Manager { 383 392 return BP_Invitation::get( $args ); 384 393 } 385 394 395 /** 396 * Get a count of the number of invitations that match provided filter parameters. 397 * 398 * @since 8.0.0 399 * 400 * @see BP_Invitation::get_total_count() for a description of accepted parameters. 401 * 402 * @return int Total number of invitations. 403 */ 404 public function get_invitations_total_count( $args = array() ) { 405 // Default to returning invitations, not requests. 406 if ( empty( $args['type'] ) ) { 407 $args['type'] = 'invite'; 408 } 409 // Use the class_name property value. 410 $args['class'] = $this->class_name; 411 412 return BP_Invitation::get_total_count( $args ); 413 } 414 386 415 /** 387 416 * Get requests, based on provided filter parameters. 388 417 * … … abstract class BP_Invitation_Manager { 703 732 ) ); 704 733 } 705 734 735 /** 736 * Delete an invitation by id. 737 * 738 * @since 8.0.0 739 * 740 * @param int $id ID of the invitation to delete. 741 * @return int|bool Number of rows deleted on success, false on failure. 742 */ 743 public function delete_by_id( $id ) { 744 // Ensure that the invitation exists and was created by this class. 745 $invite = new BP_Invitation( $id ); 746 if ( ! $invite->id || sanitize_key( $this->class_name ) !== $invite->class ) { 747 return false; 748 } 749 750 return BP_Invitation::delete_by_id( $id ); 751 } 752 753 754 706 755 /** 707 756 * This is where custom actions are added (in child classes) 708 757 * to determine whether an invitation should be allowed. -
src/bp-members/admin/bp-members-admin-classes.php
diff --git src/bp-members/admin/bp-members-admin-classes.php src/bp-members/admin/bp-members-admin-classes.php index 96e339e7a..4e2e79b54 100644
defined( 'ABSPATH' ) || exit; 12 12 13 13 if ( class_exists( 'WP_Users_List_Table' ) ) { 14 14 require dirname( dirname( __FILE__ ) ) . '/classes/class-bp-members-list-table.php'; 15 require dirname( dirname( __FILE__ ) ) . '/classes/class-bp-members-invitations-list-table.php'; 15 16 } 16 17 17 18 if ( class_exists( 'WP_MS_Users_List_Table' ) ) { -
src/bp-members/bp-members-activity.php
diff --git src/bp-members/bp-members-activity.php src/bp-members/bp-members-activity.php index 8907d0a7e..c905ff79c 100644
add_action( 'bp_register_activity_actions', 'bp_members_register_activity_action 56 56 * @return string $action 57 57 */ 58 58 function bp_members_format_activity_action_new_member( $action, $activity ) { 59 $userlink = bp_core_get_userlink( $activity->user_id ); 59 $userlink = bp_core_get_userlink( $activity->user_id ); 60 $inviter_userlink = false; 61 if ( $invite_id = bp_get_user_meta( $activity->user_id, 'accepted_members_invitation', true ) ) { 62 $invite = new BP_Invitation( (int) $invite_id ); 63 if ( $invite->inviter_id ) { 64 $inviter_userlink = bp_core_get_userlink( $invite->inviter_id ); 65 } 66 } 60 67 61 /* translators: %s: user link */ 62 $action = sprintf( esc_html__( '%s became a registered member', 'buddypress' ), $userlink ); 68 if ( $inviter_userlink ) { 69 $action = sprintf( 70 /* translators: 1: new user link. 2: inviter user link. */ 71 esc_html__( '%1$s accepted an invitation from %2$s and became a registered member', 'buddypress' ), 72 $userlink, 73 $inviter_userlink 74 ); 75 } else { 76 /* translators: %s: user link */ 77 $action = sprintf( esc_html__( '%s became a registered member', 'buddypress' ), $userlink ); 78 } 63 79 64 80 // Legacy filter - pass $user_id instead of $activity. 65 81 if ( has_filter( 'bp_core_activity_registered_member_action' ) ) { -
src/bp-members/bp-members-adminbar.php
diff --git src/bp-members/bp-members-adminbar.php src/bp-members/bp-members-adminbar.php index 10f784d09..f9b45ad38 100644
function bp_members_remove_edit_page_menu() { 178 178 } 179 179 } 180 180 add_action( 'add_admin_bar_menus', 'bp_members_remove_edit_page_menu' ); 181 182 /** 183 * Add the "Invitations" menu and submenus. 184 * 185 * @since 8.0.0 186 */ 187 function bp_members_admin_bar_add_invitations_menu() { 188 global $wp_admin_bar; 189 190 // Bail if this is an ajax request. 191 if ( defined( 'DOING_AJAX' ) ) { 192 return; 193 } 194 195 if ( is_user_logged_in() && bp_get_members_invitations_allowed() && ( bp_current_user_can( 'bp_members_send_invitation' ) || bp_members_invitations_user_has_sent_invites() ) ) { 196 $bp = buddypress(); 197 $invitations_link = trailingslashit( bp_loggedin_user_domain() . bp_get_members_invitations_slug() ); 198 199 $wp_admin_bar->add_node( 200 array( 201 'id' => $bp->my_account_menu_id . '-invitations', 202 'parent' => $bp->my_account_menu_id, 203 'title' => __( 'Invitations', 'buddypress' ), 204 'href' => $invitations_link, 205 'meta' => array( 206 'class' => 'ab-sub-secondary' 207 ) 208 ) 209 ); 210 211 if ( bp_current_user_can( 'bp_members_send_invitation' ) ) { 212 $wp_admin_bar->add_node( 213 array( 214 'id' => $bp->my_account_menu_id . '-invitations-send', 215 'parent' => $bp->my_account_menu_id . '-invitations', 216 'title' => __( 'Send Invites', 'buddypress' ), 217 'href' => $invitations_link, 218 'meta' => array( 219 'class' => 'ab-sub-secondary' 220 ) 221 ) 222 ); 223 } 224 225 $wp_admin_bar->add_node( 226 array( 227 'id' => $bp->my_account_menu_id . '-invitations-list', 228 'parent' => $bp->my_account_menu_id . '-invitations', 229 'title' => __( 'Pending Invites', 'buddypress' ), 230 'href' => $invitations_link . 'list-invites/', 231 'meta' => array( 232 'class' => 'ab-sub-secondary' 233 ) 234 ) 235 ); 236 } 237 } 238 add_action( 'bp_setup_admin_bar', 'bp_members_admin_bar_add_invitations_menu', 90 ); -
src/bp-members/bp-members-filters.php
diff --git src/bp-members/bp-members-filters.php src/bp-members/bp-members-filters.php index 5575ebef2..38f3433e6 100644
function bp_members_edit_profile_url( $url, $user_id, $scheme = 'admin' ) { 127 127 return apply_filters( 'bp_members_edit_profile_url', $profile_link, $url, $user_id, $scheme ); 128 128 } 129 129 add_filter( 'edit_profile_url', 'bp_members_edit_profile_url', 10, 3 ); 130 131 /** 132 * Filter the bp_user_can value to determine what the user can do in the members component. 133 * 134 * @since 8.0.0 135 * 136 * @param bool $retval Whether or not the current user has the capability. 137 * @param int $user_id 138 * @param string $capability The capability being checked for. 139 * @param int $site_id Site ID. Defaults to the BP root blog. 140 * @param array $args Array of extra arguments passed. 141 * 142 * @return bool 143 */ 144 function bp_members_user_can_filter( $retval, $user_id, $capability, $site_id, $args ) { 145 146 switch ( $capability ) { 147 case 'bp_members_manage_membership_requests': 148 $retval = bp_user_can( $user_id, 'bp_moderate' ); 149 break; 150 case 'bp_members_send_invitation': 151 // @todo Add restrictions? 152 if ( bp_get_members_invitations_allowed() ) { 153 $retval = true; 154 } 155 break; 156 case 'bp_members_receive_invitation': 157 if ( bp_get_members_invitations_allowed() ) { 158 $retval = true; 159 // The invited user must not already be a member of the network. 160 if ( empty( $args['invitee_email'] ) || false !== get_user_by( 'email', $args['invitee_email'] ) ) { 161 $retval = false; 162 } 163 // @TODO: The invited user must not have opted out from receiving invitations. 164 } 165 166 break; 167 } 168 169 return $retval; 170 171 } 172 add_filter( 'bp_user_can', 'bp_members_user_can_filter', 10, 5 ); 173 174 /** 175 * Do not allow the new user to change the email address 176 * if they are accepting a community invitation. 177 * 178 * @since 8.0.0 179 * 180 * @param array $attributes The field attributes. 181 * @param string $name The field name. 182 * 183 * @return array $attributes The field attributes. 184 */ 185 function bp_members_invitations_make_registration_email_input_readonly_if_invite( $attributes, $name ) { 186 if ( 'email' === $name && bp_get_members_invitations_allowed() ) { 187 $invite = bp_get_members_invitation_from_request(); 188 if ( $invite->id ) { 189 $attributes['readonly'] = 'readonly'; 190 } 191 } 192 return $attributes; 193 } 194 add_filter( 'bp_get_form_field_attributes', 'bp_members_invitations_make_registration_email_input_readonly_if_invite', 10, 2 ); 195 196 /** 197 * Provide a more-specific welcome message if the new user 198 * is accepting a network invitation. 199 * 200 * @since 8.0.0 201 * 202 * @return string $message The message text. 203 */ 204 function bp_members_invitations_get_registration_welcome_message() { 205 $message = ''; 206 if ( ! bp_get_members_invitations_allowed() ) { 207 return $message; 208 } 209 $invite = bp_get_members_invitation_from_request(); 210 if ( ! $invite->id ) { 211 return $message; 212 } 213 214 // Fetch the display names of all inviters to personalize the welcome message. 215 $all_invites = bp_members_invitations_get_invites( 216 array( 217 'invitee_email' => $invite->invitee_email, 218 'invite_sent' => 'sent', 219 ) 220 ); 221 $inviters = array(); 222 foreach ( $all_invites as $inv ) { 223 $inviters[] = bp_core_get_user_displayname( $inv->inviter_id ); 224 } 225 226 if ( ! empty( $inviters ) ) { 227 $message = sprintf( _n( 'Welcome! You’ve been invited to join the site by the following user: %s. ', 'Welcome! You’ve been invited to join the site by the following users: %s. ', count( $inviters ), 'buddypress' ), implode( ', ', $inviters ) ); 228 } else { 229 $message = __( 'Welcome! You’ve been invited to join the site. ', 'buddypress' ); 230 } 231 return $message; 232 } 233 234 /** 235 * Provide a more-specific "registration is disabled" message 236 * if registration is available by invitation only. 237 * Also provide failure note if new user is trying to accept 238 * a network invitation but there's a problem. 239 * 240 * @since 8.0.0 241 * 242 * @return string $message The message text. 243 */ 244 function bp_members_invitations_get_modified_registration_disabled_message() { 245 $message = ''; 246 if ( bp_get_members_invitations_allowed() ) { 247 $message = __( 'Member registration is allowed by invitation only.', 'buddypress' ); 248 // Is the user trying to accept an invitation but something is wrong? 249 if ( ! empty( $_GET['inv'] ) ) { 250 $message .= __( ' It looks like there is a problem with your invitation. Please try again.', 'buddypress' ); 251 } 252 } 253 return $message; 254 } 255 256 /** 257 * Sanitize the invitation property output. 258 * 259 * @since 8.0.0 260 * 261 * @param int|string $value The value for the requested property. 262 * @param string $property The name of the requested property. 263 * @param string $context The context of display. 264 * @return int|string The sanitized value. 265 */ 266 function bp_members_sanitize_invitation_property( $value = '', $property = '', $context = 'html' ) { 267 if ( ! $property ) { 268 return ''; 269 } 270 271 switch ( $property ) { 272 case 'id': 273 case 'user_id': 274 case 'item_id': 275 case 'secondary_item_id': 276 $value = absint( $value ); 277 break; 278 case 'invite_sent': 279 case 'accepted': 280 $value = absint( $value ) ? __( 'Yes', 'buddypress' ) : __( 'No', 'buddypress' ); 281 $value = 'attribute' === $context ? esc_attr( $value ) : esc_html( $value ); 282 break; 283 case 'invitee_email': 284 $value = sanitize_email( $value ); 285 break; 286 case 'content': 287 $value = wp_kses( $value, array() ); 288 $value = wptexturize( $value ); 289 break; 290 case 'date_modified': 291 $value = mysql2date( 'Y/m/d g:i:s a', $value ); 292 $value = 'attribute' === $context ? esc_attr( $value ) : esc_html( $value ); 293 break; 294 295 default: 296 $value = 'attribute' === $context ? esc_attr( $value ) : esc_html( $value ); 297 break; 298 } 299 300 return $value; 301 } 302 add_filter( 'bp_the_members_invitation_property', 'bp_members_sanitize_invitation_property', 10, 3 ); -
src/bp-members/bp-members-functions.php
diff --git src/bp-members/bp-members-functions.php src/bp-members/bp-members-functions.php index 165bc97c3..f57f916bb 100644
function bp_members_avatar_upload_dir( $directory = 'avatars', $user_id = 0 ) { 3306 3306 'error' => false 3307 3307 ) ); 3308 3308 } 3309 3310 /** 3311 * Get invitations to the BP community filtered by arguments. 3312 * 3313 * @since 8.0.0 3314 * 3315 * @param array $args Invitation arguments. 3316 * See BP_Invitation::get() for list. 3317 * 3318 * @return array $invites Matching BP_Invitation objects. 3319 */ 3320 function bp_members_invitations_get_invites( $args = array() ) { 3321 $invites_class = new BP_Members_Invitation_Manager(); 3322 return $invites_class->get_invitations( $args ); 3323 } 3324 3325 /** 3326 * Check whether a user has sent any community invitations. 3327 * 3328 * @since 8.0.0 3329 * 3330 * @param int $user_id ID of user to check for invitations sent by. 3331 * Defaults to the current user's ID. 3332 * 3333 * @return bool $invites True if user has sent invites. 3334 */ 3335 function bp_members_invitations_user_has_sent_invites( $user_id = 0 ) { 3336 if ( 0 === $user_id ) { 3337 $user_id = bp_loggedin_user_id(); 3338 if ( ! $user_id ) { 3339 return false; 3340 } 3341 } 3342 $invites_class = new BP_Members_Invitation_Manager(); 3343 $args = array( 3344 'inviter_id' => $user_id, 3345 ); 3346 return (bool) $invites_class->invitation_exists( $args ); 3347 } 3348 3349 /** 3350 * Invite a user to a BP community. 3351 * 3352 * @since 8.0.0 3353 * 3354 * @param array|string $args { 3355 * Array of arguments. 3356 * @type int $invitee_email Email address of the user being invited. 3357 * @type int $network_id ID of the network to which the user is being invited. 3358 * @type int $inviter_id Optional. ID of the inviting user. Default: 3359 * ID of the logged-in user. 3360 * @type string $date_modified Optional. Modified date for the invitation. 3361 * Default: current date/time. 3362 * @type string $content Optional. Message to invitee. 3363 * @type bool $send_invite Optional. Whether the invitation should be 3364 * sent now. Default: false. 3365 * } 3366 * @return bool True on success, false on failure. 3367 */ 3368 function bp_members_invitations_invite_user( $args ) { 3369 $r = bp_parse_args( $args, array( 3370 'invitee_email' => '', 3371 'network_id' => get_current_network_id(), 3372 'inviter_id' => bp_loggedin_user_id(), 3373 'date_modified' => bp_core_current_time(), 3374 'content' => '', 3375 'send_invite' => 0 3376 ), 'community_invite_user' ); 3377 3378 $inv_args = array( 3379 'invitee_email' => $r['invitee_email'], 3380 'item_id' => $r['network_id'], 3381 'inviter_id' => $r['inviter_id'], 3382 'date_modified' => $r['date_modified'], 3383 'content' => $r['content'], 3384 'send_invite' => $r['send_invite'] 3385 ); 3386 3387 // Create the invitataion. 3388 $invites_class = new BP_Members_Invitation_Manager(); 3389 $created = $invites_class->add_invitation( $inv_args ); 3390 3391 /** 3392 * Fires after the creation of a new network invite. 3393 * 3394 * @since 8.0.0 3395 * 3396 * @param array $r Array of parsed arguments for the network invite. 3397 * @param int|bool $created The ID of the invitation or false if it couldn't be created. 3398 */ 3399 do_action( 'bp_members_invitations_invite_user', $r, $created ); 3400 3401 return $created; 3402 } 3403 3404 /** 3405 * Resend a membership invitation email by id. 3406 * 3407 * @since 8.0.0 3408 * 3409 * @param int $id ID of the invitation to resend. 3410 * @return bool True on success, false on failure. 3411 */ 3412 function bp_members_invitation_resend_by_id( $id = 0 ) { 3413 3414 // Find the invitation before deleting it. 3415 $existing_invite = new BP_Invitation( $id ); 3416 $invites_class = new BP_Members_Invitation_Manager(); 3417 $success = $invites_class->send_invitation_by_id( $id ); 3418 3419 if ( ! $success ) { 3420 return $success; 3421 } 3422 3423 /** 3424 * Fires after the re-sending of a network invite. 3425 * 3426 * @since 8.0.0 3427 * 3428 * @param BP_Invitation $existing_invite The invitation that was resent. 3429 */ 3430 do_action( 'bp_members_invitations_resend_invitation', $existing_invite ); 3431 3432 return $success; 3433 } 3434 3435 /** 3436 * Delete a membership invitation by id. 3437 * 3438 * @since 8.0.0 3439 * 3440 * @param int $id ID of the invitation to delete. 3441 * @return int|bool Number of rows deleted on success, false on failure. 3442 */ 3443 function bp_members_invitations_delete_by_id( $id = 0 ) { 3444 3445 // Find the invitation before deleting it. 3446 $existing_invite = new BP_Invitation( $id ); 3447 $invites_class = new BP_Members_Invitation_Manager(); 3448 $success = $invites_class->delete_by_id( $id ); 3449 3450 if ( ! $success ) { 3451 return $success; 3452 } 3453 3454 // Run a different action depending on the status of the invite. 3455 if ( ! $existing_invite->invite_sent ) { 3456 /** 3457 * Fires after the deletion of an unsent community invite. 3458 * 3459 * @since 8.0.0 3460 * 3461 * @param BP_Invitation $existing_invite The invitation to be deleted. 3462 */ 3463 do_action( 'bp_members_invitations_canceled_invitation', $existing_invite ); 3464 } else if ( ! $existing_invite->accepted ) { 3465 /** 3466 * Fires after the deletion of a sent, but not yet accepted, community invite. 3467 * 3468 * @since 8.0.0 3469 * 3470 * @param BP_Invitation $existing_invite The invitation to be deleted. 3471 */ 3472 do_action( 'bp_members_invitations_revoked_invitation', $existing_invite ); 3473 } else { 3474 /** 3475 * Fires after the deletion of a sent and accepted community invite. 3476 * 3477 * @since 8.0.0 3478 * 3479 * @param BP_Invitation $existing_invite The invitation to be deleted. 3480 */ 3481 do_action( 'bp_members_invitations_deleted_invitation', $existing_invite ); 3482 } 3483 3484 return $success; 3485 } 3486 3487 /** 3488 * Delete a membership invitation. 3489 * 3490 * @since 8.0.0 3491 * 3492 * @param intring $args { 3493 * Array of arguments. 3494 * @type int|array $id Id(s) of the invitation(s) to remove. 3495 * @type int $invitee_email Email address of the user being invited. 3496 * @type int $network_id ID of the network to which the user is being invited. 3497 * @type int $inviter_id ID of the inviting user. 3498 * @type int $accepted Whether the invitation has been accepted yet. 3499 * @type int $invite_sent Whether the invitation has been sent yet. 3500 * } 3501 * @return bool True if all were deleted. 3502 */ 3503 function bp_members_invitations_delete_invites( $args ) { 3504 $r = bp_parse_args( $args, array( 3505 'id' => 0, 3506 'invitee_email' => '', 3507 'network_id' => get_current_network_id(), 3508 'inviter_id' => null, 3509 'accepted' => null, 3510 'invite_sent' => null 3511 ), 'community_invitation_delete_invites' ); 3512 3513 $inv_args = array( 3514 'id' => $r['id'], 3515 'invitee_email' => $r['invitee_email'], 3516 'item_id' => $r['network_id'], 3517 'inviter_id' => $r['inviter_id'], 3518 ); 3519 3520 // Find the invitation(s). 3521 $invites = bp_members_invitations_get_invites( $inv_args ); 3522 $total_count = count( $invites ); 3523 3524 // Loop through, deleting each invitation. 3525 $deleted = 0; 3526 foreach ( $invites as $invite ) { 3527 $success = bp_members_invitations_delete_by_id( $invite->id ); 3528 if ( $success ) { 3529 $deleted++; 3530 } 3531 } 3532 3533 return $deleted === $total_count; 3534 } 3535 3536 /** 3537 * Get hash based on details of a membership invitation and the inviter. 3538 * 3539 * @since 8.0.0 3540 * 3541 * @param BP_Invitation object $invitation Invitation to create hash from. 3542 * 3543 * @return string $hash Calculated sha1 hash. 3544 */ 3545 function bp_members_invitations_get_hash( BP_Invitation $invitation ) { 3546 $hash = false; 3547 3548 if ( ! empty( $invitation->id ) ) { 3549 $inviter_ud = get_userdata( $invitation->inviter_id ); 3550 if ( $inviter_ud ) { 3551 /* 3552 * Use some inviter details as part of the hash so that invitations from 3553 * users who are subsequently marked as spam will be invalidated. 3554 */ 3555 $hash = wp_hash( "{$invitation->inviter_id}:{$invitation->invitee_email}:{$inviter_ud->user_status}:{$inviter_ud->user_registered}" ); 3556 } 3557 } 3558 3559 // If there's a problem, return a string that will change and thus fail. 3560 if ( ! $hash ) { 3561 $hash = wp_generate_password( 32, false ); 3562 } 3563 3564 /** 3565 * Filters the hash calculated by the invitation details. 3566 * 3567 * @since 8.0.0 3568 * 3569 * @param string $hash Calculated sha1 hash. 3570 * @param BP_Invitation object $invitation Invitation hash was created from. 3571 */ 3572 return apply_filters( 'bp_members_invitations_get_hash', $hash, $invitation ); 3573 } 3574 3575 /** 3576 * Get the current invitation specified by the $_GET parameters. 3577 * 3578 * @since 8.0.0 3579 * 3580 * @return BP_Invitation $invite Invitation specified by the $_GET parameters. 3581 */ 3582 function bp_get_members_invitation_from_request() { 3583 $invites_class = new BP_Members_Invitation_Manager(); 3584 $invite = $invites_class->get_by_id( 0 ); 3585 3586 if ( bp_get_members_invitations_allowed() && ! empty( $_GET['inv'] ) ) { 3587 // Check to make sure the passed hash matches a calculated hash. 3588 $maybe_invite = $invites_class->get_by_id( absint( $_GET['inv'] ) ); 3589 $hash = bp_members_invitations_get_hash( $maybe_invite ); 3590 if ( $_GET['ih'] === $hash ) { 3591 $invite = $maybe_invite; 3592 } 3593 } 3594 3595 /** 3596 * Filters the invitation specified by the $_GET parameters. 3597 * 3598 * @since 8.0.0 3599 * 3600 * @param BP_Invitation $invite Invitation specified by the $_GET parameters. 3601 */ 3602 return apply_filters( 'bp_get_members_invitation_from_request', $invite ); 3603 } -
new file src/bp-members/bp-members-invitations.php
diff --git src/bp-members/bp-members-invitations.php src/bp-members/bp-members-invitations.php new file mode 100644 index 000000000..1d7df3a55
- + 1 <?php 2 /** 3 * BuddyPress Membersip Invitations 4 * 5 * @package BuddyPress 6 * @subpackage MembersInvitations 7 * @since 8.0.0 8 */ 9 10 // Exit if accessed directly. 11 defined( 'ABSPATH' ) || exit; 12 13 function bp_members_invitations_setup_nav() { 14 if ( ! bp_get_members_invitations_allowed() ) { 15 return; 16 } 17 18 $user_has_access = bp_user_has_access(); 19 $user_can_send = bp_user_can( bp_displayed_user_id(), 'bp_members_send_invitation' ); 20 $user_has_invites = bp_members_invitations_user_has_sent_invites(); 21 22 /* Add 'Invitations' to the main user profile navigation */ 23 bp_core_new_nav_item( 24 array( 25 'name' => __( 'Invitations', 'buddypress' ), 26 'slug' => bp_get_members_invitations_slug(), 27 'position' => 80, 28 'screen_function' => 'members_screen_send_invites', 29 'default_subnav_slug' => 'send-invites', 30 'show_for_displayed_user' => $user_has_access && ( $user_can_send || $user_has_invites ) 31 ) 32 ); 33 34 $parent_link = trailingslashit( bp_displayed_user_domain() . bp_get_members_invitations_slug() ); 35 36 /* Create two subnav items for community invitations */ 37 bp_core_new_subnav_item( 38 array( 39 'name' => __( 'Send Invites', 'buddypress' ), 40 'slug' => 'send-invites', 41 'parent_slug' => bp_get_members_invitations_slug(), 42 'parent_url' => $parent_link, 43 'screen_function' => 'members_screen_send_invites', 44 'position' => 10, 45 'user_has_access' => $user_has_access && $user_can_send && bp_is_my_profile() 46 ) 47 ); 48 49 bp_core_new_subnav_item( 50 array( 51 'name' => __( 'Pending Invites', 'buddypress' ), 52 'slug' => 'list-invites', 53 'parent_slug' => bp_get_members_invitations_slug(), 54 'parent_url' => $parent_link, 55 'screen_function' => 'members_screen_list_sent_invites', 56 'position' => 20, 57 'user_has_access' => $user_has_access && ( $user_can_send || $user_has_invites ) 58 ) 59 ); 60 } 61 add_action( 'bp_setup_nav', 'bp_members_invitations_setup_nav' ); 62 63 /** 64 * When a user joins the network via an invitation, skip sending the activation email. 65 * 66 * @param bool $send Whether or not to send the activation key. 67 * @param int $user_id User ID to send activation key to. 68 * @param string $user_email User email to send activation key to. 69 * @param string $activation_key Activation key to be sent. 70 * @param array $usermeta Miscellaneous metadata about the user (blog-specific 71 * signup data, xprofile data, etc). 72 */ 73 function bp_members_invitations_cancel_activation_email( $send, $user_id, $user_email, $activation_key, $usermeta ) { 74 $invite = bp_members_invitations_get_invites( 75 array( 76 'invitee_email' => $user_email, 77 'invite_sent' => 'sent' 78 ) 79 ); 80 81 if ( $invite ) { 82 $send = false; 83 } 84 85 return $send; 86 } 87 add_filter( 'bp_core_signup_send_activation_key', 'bp_members_invitations_cancel_activation_email', 10, 5 ); 88 89 /** 90 * When a user joins the network via an invitation: 91 * - mark all invitations and requests as accepted 92 * - activate the user upon signup 93 * 94 * @param bool|WP_Error $user_id True on success, WP_Error on failure. 95 * @param string $user_login Login name requested by the user. 96 * @param string $user_password Password requested by the user. 97 * @param string $user_email Email address requested by the user. 98 */ 99 function bp_members_invitations_complete_signup( $user_id, $user_login, $user_password, $user_email ) { 100 if ( ! $user_id ) { 101 return; 102 } 103 104 // Check to see if this signup is the result of a valid invitation. 105 $invite = bp_get_members_invitation_from_request(); 106 if ( ! $invite->id ) { 107 return; 108 } 109 110 // Add the accepted invitation ID to the user's meta. 111 bp_update_user_meta( $user_id, 'accepted_members_invitation', $invite->id ); 112 113 // We will mark all invitations to this user as "accepted." 114 $invites_class = new BP_Members_Invitation_Manager(); 115 $args = array( 116 'invitee_email' => $user_email, 117 'item_id' => get_current_network_id(), 118 'type' => 'all' 119 ); 120 $invites_class->mark_accepted( $args ); 121 122 // User has already verified their email by responding to the invitation, so we can activate. 123 $key = bp_get_user_meta( $user_id, 'activation_key', true ); 124 if ( $key ) { 125 /** 126 * Filters the activation signup. 127 * 128 * @since 1.1.0 129 * 130 * @param bool|int $value Value returned by activation. 131 * Integer on success, boolean on failure. 132 */ 133 $user = apply_filters( 'bp_core_activate_account', bp_core_activate_signup( $key ) ); 134 135 // If there were errors, add a message and redirect. 136 if ( ! empty( $user->errors ) ) { 137 bp_core_add_message( $user->get_error_message(), 'error' ); 138 bp_core_redirect( trailingslashit( bp_get_root_domain() . '/' . $bp->pages->activate->slug ) ); 139 } 140 141 bp_core_add_message( __( 'Your account is now active!', 'buddypress' ) ); 142 bp_core_redirect( add_query_arg( 'activated', '1', bp_get_activation_page() ) ); 143 } 144 } 145 add_action( 'bp_core_signup_user', 'bp_members_invitations_complete_signup', 10, 4 ); -
src/bp-members/bp-members-template.php
diff --git src/bp-members/bp-members-template.php src/bp-members/bp-members-template.php index 541b27479..117f6fcb6 100644
function bp_activate_slug() { 274 274 return apply_filters( 'bp_get_activate_slug', $slug ); 275 275 } 276 276 277 /** 278 * Output the members invitation pane slug. 279 * 280 * @since 8.0.0 281 * 282 */ 283 function bp_members_invitations_slug() { 284 echo bp_get_members_invitations_slug(); 285 } 286 /** 287 * Return the members invitations root slug. 288 * 289 * @since 8.0.0 290 * 291 * @return string 292 */ 293 function bp_get_members_invitations_slug() { 294 295 /** 296 * Filters the Members invitations pane root slug. 297 * 298 * @since 8.0.0 299 * 300 * @param string $slug Members invitations pane root slug. 301 */ 302 return apply_filters( 'bp_get_members_invitations_slug', _x( 'invitations', 'Member profile invitations pane URL base', 'buddypress' ) ); 303 } 304 277 305 /** 278 306 * Initialize the members loop. 279 307 * … … function bp_signup_email_value() { 2381 2409 */ 2382 2410 function bp_get_signup_email_value() { 2383 2411 $value = ''; 2384 if ( isset( $_POST['signup_email'] ) ) 2412 if ( isset( $_POST['signup_email'] ) ) { 2385 2413 $value = $_POST['signup_email']; 2414 } else if ( bp_get_members_invitations_allowed() ) { 2415 $invite = bp_get_members_invitation_from_request(); 2416 if ( $invite ) { 2417 $value = $invite->invitee_email; 2418 } 2419 } 2386 2420 2387 2421 /** 2388 2422 * Filters the email address submitted during signup. … … function bp_signup_allowed() { 2755 2789 return apply_filters( 'bp_get_signup_allowed', (bool) bp_get_option( 'users_can_register' ) ); 2756 2790 } 2757 2791 2792 /** 2793 * Are users allowed to invite users to join this site? 2794 * 2795 * @since 8.0.0 2796 * 2797 * @return bool 2798 */ 2799 function bp_get_members_invitations_allowed() { 2800 /** 2801 * Filters whether or not community invitations are allowed. 2802 * 2803 * @since 8.0.0 2804 * 2805 * @param bool $allowed Whether or not community invitations are allowed. 2806 */ 2807 return apply_filters( 'bp_get_members_invitations_allowed', bp_is_active( 'members', 'invitations' ) && (bool) bp_get_option( 'bp-enable-members-invitations' ) ); 2808 } 2809 2758 2810 /** 2759 2811 * Hook member activity feed to <head>. 2760 2812 * … … function bp_avatar_delete_link() { 2869 2921 */ 2870 2922 return apply_filters( 'bp_get_avatar_delete_link', wp_nonce_url( bp_displayed_user_domain() . bp_get_profile_slug() . '/change-avatar/delete-avatar/', 'bp_delete_avatar_link' ) ); 2871 2923 } 2924 2925 2926 /** The Members Invitations Loop ******************************************************************/ 2927 2928 /** 2929 * Initialize the community invitations loop. 2930 * 2931 * Based on the $args passed, bp_has_invitations() populates 2932 * buddypress()->invitations->query_loop global, enabling the use of BP 2933 * templates and template functions to display a list of invitations. 2934 * 2935 * @since 8.0.0 2936 * 2937 * @param array|string $args { 2938 * Arguments for limiting the contents of the invitations loop. Can be 2939 * passed as an associative array, or as a URL query string. 2940 * 2941 * See {@link BP_Invitations_Invitation::get()} for detailed 2942 * information on the arguments. In addition, also supports: 2943 * 2944 * @type int $max Optional. Max items to display. Default: false. 2945 * @type string $page_arg URL argument to use for pagination. 2946 * Default: 'ipage'. 2947 * } 2948 * @return bool 2949 */ 2950 function bp_has_members_invitations( $args = '' ) { 2951 2952 // Get the user ID. 2953 if ( bp_displayed_user_id() ) { 2954 $user_id = bp_displayed_user_id(); 2955 } else { 2956 $user_id = bp_loggedin_user_id(); 2957 } 2958 2959 // Set the search terms (by default an empty string to get all notifications) 2960 $search_terms = ''; 2961 2962 if ( isset( $_REQUEST['s'] ) ) { 2963 $search_terms = stripslashes( $_REQUEST['s'] ); 2964 } 2965 2966 // Parse the args. 2967 $r = bp_parse_args( $args, array( 2968 'id' => false, 2969 'inviter_id' => $user_id, 2970 'invitee_email' => false, 2971 'item_id' => false, 2972 'type' => 'invite', 2973 'invite_sent' => 'all', 2974 'accepted' => 'pending', 2975 'search_terms' => $search_terms, 2976 'order_by' => 'date_modified', 2977 'sort_order' => 'DESC', 2978 'page' => 1, 2979 'per_page' => 25, 2980 'fields' => 'all', 2981 2982 // These are additional arguments that are not available in 2983 // BP_Invitations_Invitation::get(). 2984 'page_arg' => 'ipage', 2985 ), 'has_community_invitations' ); 2986 2987 // Get the notifications. 2988 $query_loop = new BP_Members_Invitations_Template( $r ); 2989 2990 // Setup the global query loop. 2991 buddypress()->members->invitations->query_loop = $query_loop; 2992 2993 /** 2994 * Filters whether or not the user has network invitations to display. 2995 * 2996 * @since 8.0.0 2997 * 2998 * @param bool $value Whether or not there are network invitations to display. 2999 * @param BP_Notifications_Template $query_loop BP_Members_Invitations_Template object instance. 3000 * @param array $r Array of arguments passed into the BP_Members_Invitations_Template class. 3001 */ 3002 return apply_filters( 'bp_has_members_invitations', $query_loop->has_invitations(), $query_loop, $r ); 3003 } 3004 3005 /** 3006 * Get the network invitations returned by the template loop. 3007 * 3008 * @since 8.0.0 3009 * 3010 * @return array List of network invitations. 3011 */ 3012 function bp_the_members_invitations() { 3013 return buddypress()->members->invitations->query_loop->invitations(); 3014 } 3015 3016 /** 3017 * Get the current network invitation object in the loop. 3018 * 3019 * @since 8.0.0 3020 * 3021 * @return object The current network invitation within the loop. 3022 */ 3023 function bp_the_members_invitation() { 3024 return buddypress()->members->invitations->query_loop->the_invitation(); 3025 } 3026 3027 /** 3028 * Output the pagination count for the current network invitations loop. 3029 * 3030 * @since 8.0.0 3031 */ 3032 function bp_members_invitations_pagination_count() { 3033 echo bp_get_members_invitations_pagination_count(); 3034 } 3035 /** 3036 * Return the pagination count for the current network invitation loop. 3037 * 3038 * @since 8.0.0 3039 * 3040 * @return string HTML for the pagination count. 3041 */ 3042 function bp_get_members_invitations_pagination_count() { 3043 $query_loop = buddypress()->members->invitations->query_loop; 3044 $start_num = intval( ( $query_loop->pag_page - 1 ) * $query_loop->pag_num ) + 1; 3045 $from_num = bp_core_number_format( $start_num ); 3046 $to_num = bp_core_number_format( ( $start_num + ( $query_loop->pag_num - 1 ) > $query_loop->total_invitation_count ) ? $query_loop->total_invitation_count : $start_num + ( $query_loop->pag_num - 1 ) ); 3047 $total = bp_core_number_format( $query_loop->total_invitation_count ); 3048 3049 if ( 1 == $query_loop->total_invitation_count ) { 3050 $pag = __( 'Viewing 1 invitation', 'buddypress' ); 3051 } else { 3052 /* translators: 1: notification from number. 2: notification to number. 3: total notifications. */ 3053 $pag = sprintf( _n( 'Viewing %1$s - %2$s of %3$s invitation', 'Viewing %1$s - %2$s of %3$s invitations', $query_loop->total_invitation_count, 'buddypress' ), $from_num, $to_num, $total ); 3054 } 3055 3056 /** 3057 * Filters the pagination count for the current network invitation loop. 3058 * 3059 * @since 1.9.0 3060 * 3061 * @param string $pag HTML for the pagination count. 3062 */ 3063 return apply_filters( 'bp_get_members_invitations_pagination_count', $pag ); 3064 } 3065 3066 /** 3067 * Output the pagination links for the current network invitation loop. 3068 * 3069 * @since 8.0.0 3070 */ 3071 function bp_members_invitations_pagination_links() { 3072 echo bp_get_members_invitations_pagination_links(); 3073 } 3074 /** 3075 * Return the pagination links for the current network invitations loop. 3076 * 3077 * @since 8.0.0 3078 * 3079 * @return string HTML for the pagination links. 3080 */ 3081 function bp_get_members_invitations_pagination_links() { 3082 3083 /** 3084 * Filters the pagination links for the current network invitations loop. 3085 * 3086 * @since 8.0.0 3087 * 3088 * @param string $pag_links HTML for the pagination links. 3089 */ 3090 return apply_filters( 'bp_get_members_invitations_pagination_links', buddypress()->members->invitations->query_loop->pag_links ); 3091 } 3092 3093 /** 3094 * Output the requested property of the invitation currently being iterated on. 3095 * 3096 * @since 8.0.0 3097 * 3098 * @param string $property The name of the property to display. 3099 * @param string $context The context of display. 3100 * Possible values are 'attribute' and 'html'. 3101 */ 3102 function bp_the_members_invitation_property( $property = '', $context = 'html' ) { 3103 if ( ! $property ) { 3104 return; 3105 } 3106 3107 /** 3108 * Use this filter to sanitize the output. 3109 * 3110 * @since 8.0.0 3111 * 3112 * @param int|string $value The value for the requested property. 3113 * @param string $property The name of the requested property. 3114 * @param string $context The context of display. 3115 */ 3116 echo apply_filters( 'bp_the_members_invitation_property', bp_get_the_members_invitation_property( $property ), $property, $context ); 3117 } 3118 /** 3119 * Return the value for a property of the network invitation currently being iterated on. 3120 * 3121 * @since 8.0.0 3122 * 3123 * @return int ID of the current network invitation. 3124 */ 3125 function bp_get_the_members_invitation_property( $property = 'id' ) { 3126 3127 switch ( $property ) { 3128 case 'id': 3129 case 'user_id': 3130 case 'item_id': 3131 case 'secondary_item_id': 3132 case 'invite_sent': 3133 case 'accepted': 3134 $value = 0; 3135 break; 3136 case 'invitee_email': 3137 case 'type': 3138 case 'content': 3139 case 'date_modified': 3140 $value = ''; 3141 break; 3142 default: 3143 // A known property has not been specified. 3144 $property = null; 3145 $value = ''; 3146 break; 3147 } 3148 3149 if ( isset( buddypress()->members->invitations->query_loop->invitation->{$property} ) ) { 3150 $value = buddypress()->members->invitations->query_loop->invitation->{$property}; 3151 } 3152 3153 /** 3154 * Filters the property of the network invitation currently being iterated on. 3155 * 3156 * @since 8.0.0 3157 * 3158 * @param int|string $value Property value of the network invitation being iterated on. 3159 */ 3160 return apply_filters( 'bp_get_the_members_invitation_property_' . $property, $value ); 3161 } 3162 3163 /** 3164 * Output the action links for the current invitation. 3165 * 3166 * @since 8.0.0 3167 * 3168 * @param array|string $args Array of arguments. 3169 */ 3170 function bp_the_members_invitation_action_links( $args = '' ) { 3171 echo bp_get_the_members_invitation_action_links( $args ); 3172 } 3173 /** 3174 * Return the action links for the current invitation. 3175 * 3176 * @since 8.0.0 3177 * 3178 * @param array|string $args { 3179 * @type string $before HTML before the links. 3180 * @type string $after HTML after the links. 3181 * @type string $sep HTML between the links. 3182 * @type array $links Array of links to implode by 'sep'. 3183 * @type int $user_id User ID to fetch action links for. Defaults to displayed user ID. 3184 * } 3185 * @return string HTML links for actions to take on single notifications. 3186 */ 3187 function bp_get_the_members_invitation_action_links( $args = '' ) { 3188 // Set default user ID to use. 3189 $inviter_id = isset( $args['inviter_id'] ) ? $args['inviter_id'] : bp_displayed_user_id(); 3190 3191 // Parse. 3192 $r = wp_parse_args( $args, array( 3193 'before' => '', 3194 'after' => '', 3195 'sep' => ' | ', 3196 'links' => array( 3197 bp_get_the_members_invitation_resend_link( $inviter_id ), 3198 bp_get_the_members_invitation_delete_link( $inviter_id ) 3199 ) 3200 ) ); 3201 3202 // Build the links. 3203 $retval = $r['before'] . implode( $r['sep'], $r['links'] ) . $r['after']; 3204 3205 /** 3206 * Filters the action links for the current notification. 3207 * 3208 * @since 1.9.0 3209 * @since 2.6.0 Added the `$r` parameter. 3210 * 3211 * @param string $retval HTML links for actions to take on single notifications. 3212 * @param array $r Array of parsed arguments. 3213 */ 3214 return apply_filters( 'bp_get_the_members_invitation_action_links', $retval, $r ); 3215 } 3216 3217 /** 3218 * Output the resend link for the current invitation. 3219 * 3220 * @since 8.0.0 3221 * 3222 * @param int $user_id The user ID. 3223 */ 3224 function bp_the_members_invitations_resend_link( $user_id = 0 ) { 3225 echo bp_get_the_members_invitation_delete_link( $user_id ); 3226 } 3227 /** 3228 * Return the resend link for the current notification. 3229 * 3230 * @since 78.0.0 3231 * 3232 * @param int $user_id The user ID. 3233 * @return string 3234 */ 3235 function bp_get_the_members_invitation_resend_link( $user_id = 0 ) { 3236 // Set default user ID to use. 3237 $user_id = 0 === $user_id ? bp_displayed_user_id() : $user_id; 3238 3239 // Don't allow resending of accepted invitations. 3240 if ( bp_get_the_members_invitation_property( 'accepted' ) ) { 3241 return; 3242 } 3243 3244 $retval = sprintf( '<a href="%1$s" class="resend secondary confirm bp-tooltip">%2$s</a>', esc_url( bp_get_the_members_invitations_resend_url( $user_id ) ), __( 'Resend', 'buddypress' ) ); 3245 3246 /** 3247 * Filters the resend link for the current invitation. 3248 * 3249 * @since 8.0.0 3250 * 3251 * @param string $retval HTML for the delete link for the current notification. 3252 * @param int $user_id The user ID. 3253 */ 3254 return apply_filters( 'bp_get_the_members_invitation_resend_link', $retval, $user_id ); 3255 } 3256 3257 /** 3258 * Output the URL used for resending a single invitation. 3259 * 3260 * Since this function directly outputs a URL, it is escaped. 3261 * 3262 * @since 8.0.0 3263 * 3264 * @param int $user_id The user ID. 3265 */ 3266 function bp_the_members_invitations_resend_url( $user_id = 0 ) { 3267 echo esc_url( bp_get_the_members_invitations_resend_url( $user_id ) ); 3268 } 3269 /** 3270 * Return the URL used for resending a single invitation. 3271 * 3272 * @since 8.0.0 3273 * 3274 * @param int $user_id The user ID. 3275 * @return string 3276 */ 3277 function bp_get_the_members_invitations_resend_url( $user_id = 0 ) { 3278 // Set default user ID to use. 3279 $user_id = 0 === $user_id ? bp_displayed_user_id() : $user_id; 3280 $link = bp_get_members_invitations_list_invites_permalink( $user_id ); 3281 3282 // Get the ID. 3283 $id = bp_get_the_members_invitation_property( 'id' ); 3284 3285 // Get the args to add to the URL. 3286 $args = array( 3287 'action' => 'resend', 3288 'invitation_id' => $id 3289 ); 3290 3291 // Add the args. 3292 $url = add_query_arg( $args, $link ); 3293 3294 // Add the nonce. 3295 $url = wp_nonce_url( $url, 'bp_network_invitation_resend_' . $id ); 3296 3297 /** 3298 * Filters the URL used for resending a single invitation. 3299 * 3300 * @since 8.0.0 3301 * 3302 * @param string $url URL used for deleting a single invitation. 3303 * @param int $user_id The user ID. 3304 */ 3305 return apply_filters( 'bp_get_the_members_invitations_resend_url', $url, $user_id ); 3306 } 3307 3308 /** 3309 * Output the delete link for the current invitation. 3310 * 3311 * @since 8.0.0 3312 * 3313 * @param int $user_id The user ID. 3314 */ 3315 function bp_the_members_invitations_delete_link( $user_id = 0 ) { 3316 echo bp_get_the_members_invitation_delete_link( $user_id ); 3317 } 3318 /** 3319 * Return the delete link for the current invitation. 3320 * 3321 * @since 8.0.0 3322 * 3323 * @param int $user_id The user ID. 3324 * @return string 3325 */ 3326 function bp_get_the_members_invitation_delete_link( $user_id = 0 ) { 3327 // Set default user ID to use. 3328 $user_id = 0 === $user_id ? bp_displayed_user_id() : $user_id; 3329 3330 // Modify the message for accepted/not accepted invitatons. 3331 if ( bp_get_the_members_invitation_property( 'accepted' ) ) { 3332 $message = __( 'Delete', 'buddypress' ); 3333 } else { 3334 $message = __( 'Cancel', 'buddypress' ); 3335 } 3336 3337 $retval = sprintf( '<a href="%1$s" class="delete secondary confirm bp-tooltip">%2$s</a>', esc_url( bp_get_the_members_invitations_delete_url( $user_id ) ), $message ); 3338 3339 /** 3340 * Filters the delete link for the current invitation. 3341 * 3342 * @since 8.0.0 3343 * 3344 * @param string $retval HTML for the delete link for the current notification. 3345 * @param int $user_id The user ID. 3346 */ 3347 return apply_filters( 'bp_get_the_members_invitation_delete_link', $retval, $user_id ); 3348 } 3349 3350 /** 3351 * Output the URL used for deleting a single invitation. 3352 * 3353 * Since this function directly outputs a URL, it is escaped. 3354 * 3355 * @since 8.0.0 3356 * 3357 * @param int $user_id The user ID. 3358 */ 3359 function bp_the_members_invitations_delete_url( $user_id = 0 ) { 3360 echo esc_url( bp_get_the_members_invitations_delete_url( $user_id ) ); 3361 } 3362 /** 3363 * Return the URL used for deleting a single invitation. 3364 * 3365 * @since 8.0.0 3366 * 3367 * @param int $user_id The user ID. 3368 * @return string 3369 */ 3370 function bp_get_the_members_invitations_delete_url( $user_id = 0 ) { 3371 // Set default user ID to use. 3372 $user_id = 0 === $user_id ? bp_displayed_user_id() : $user_id; 3373 $link = bp_get_members_invitations_list_invites_permalink( $user_id ); 3374 3375 // Get the ID. 3376 $id = bp_get_the_members_invitation_property( 'id' ); 3377 3378 // Get the args to add to the URL. 3379 $args = array( 3380 'action' => 'cancel', 3381 'invitation_id' => $id 3382 ); 3383 3384 // Add the args. 3385 $url = add_query_arg( $args, $link ); 3386 3387 // Add the nonce. 3388 $url = wp_nonce_url( $url, 'bp_members_invitations_cancel_' . $id ); 3389 3390 /** 3391 * Filters the URL used for deleting a single invitation. 3392 * 3393 * @since 8.0.0 3394 * 3395 * @param string $url URL used for deleting a single invitation. 3396 * @param int $user_id The user ID. 3397 */ 3398 return apply_filters( 'bp_get_the_members_invitations_delete_url', $url, $user_id ); 3399 } 3400 3401 /** 3402 * Output the members invitations list permalink for a user. 3403 * 3404 * @since 8.0.0 3405 * 3406 * @param int $user_id The user ID. 3407 */ 3408 function bp_members_invitations_list_invites_permalink( $user_id = 0 ) { 3409 echo bp_get_members_invitations_list_invites_permalink( $user_id ); 3410 } 3411 /** 3412 * Return the members invitations list permalink for a user. 3413 * 3414 * @since 8.0.0 3415 * 3416 * @return string Members invitations list permalink for a user. 3417 */ 3418 function bp_get_members_invitations_list_invites_permalink( $user_id = 0 ) { 3419 if ( 0 === $user_id ) { 3420 $user_id = bp_loggedin_user_id(); 3421 $domain = bp_loggedin_user_domain(); 3422 } else { 3423 $domain = bp_core_get_user_domain( (int) $user_id ); 3424 } 3425 3426 $retval = trailingslashit( $domain . bp_get_members_invitations_slug() . '/list-invites' ); 3427 3428 /** 3429 * Filters the members invitations list permalink for a user. 3430 * 3431 * @since 8.0.0 3432 * 3433 * @param string $retval Permalink for the sent invitation list screen. 3434 * @param int $user_id The user ID. 3435 */ 3436 return apply_filters( 'bp_get_members_invitations_list_invites_permalink', $retval, $user_id ); 3437 } 3438 3439 /** 3440 * Output the send invitation permalink for a user. 3441 * 3442 * @since 8.0.0 3443 * 3444 * @param int $user_id The user ID. 3445 */ 3446 function bp_members_invitations_send_invites_permalink( $user_id = 0 ) { 3447 echo bp_get_members_invitations_send_invites_permalink( $user_id ); 3448 } 3449 /** 3450 * Return the send invitations permalink. 3451 * 3452 * @since 8.0.0 3453 * 3454 * @return string Read notifications permalink. 3455 */ 3456 function bp_get_members_invitations_send_invites_permalink( $user_id = 0 ) { 3457 if ( 0 === $user_id ) { 3458 $user_id = bp_loggedin_user_id(); 3459 $domain = bp_loggedin_user_domain(); 3460 } else { 3461 $domain = bp_core_get_user_domain( (int) $user_id ); 3462 } 3463 3464 $retval = trailingslashit( $domain . bp_get_members_invitations_slug() . '/send-invites' ); 3465 3466 /** 3467 * Filters the read notifications permalink. 3468 * 3469 * @since 8.0.0 3470 * 3471 * @param string $retval Permalink for the sent invitation list screen. 3472 * @param int $user_id The user ID. 3473 */ 3474 return apply_filters( 'bp_get_members_invitations_send_invites_permalink', $retval, $user_id ); 3475 } -
src/bp-members/classes/class-bp-members-admin.php
diff --git src/bp-members/classes/class-bp-members-admin.php src/bp-members/classes/class-bp-members-admin.php index 64903c107..3294a7765 100644
class BP_Members_Admin { 140 140 $this->users_url = bp_get_admin_url( 'users.php' ); 141 141 $this->users_screen = bp_core_do_network_admin() ? 'users-network' : 'users'; 142 142 143 $this->members_invites_page = ''; 144 143 145 // Specific config: BuddyPress is not network activated. 144 146 $this->subsite_activated = (bool) is_multisite() && ! bp_is_network_activated(); 145 147 … … class BP_Members_Admin { 219 221 // Registration is turned on. 220 222 add_action( 'update_site_option_registration', array( $this, 'multisite_registration_on' ), 10, 2 ); 221 223 add_action( 'update_option_users_can_register', array( $this, 'single_site_registration_on' ), 10, 2 ); 224 225 // Member invitations are enabled. 226 if ( bp_is_network_activated() ) { 227 add_action( 'update_site_option_bp-enable-members-invitations', array( $this, 'multisite_registration_on' ), 10, 2 ); 228 } else { 229 add_action( 'update_option_bp-enable-members-invitations', array( $this, 'single_site_registration_on' ), 10, 2 ); 230 } 222 231 } 223 232 224 233 /** Users List - Members Types *************************************** … … class BP_Members_Admin { 248 257 * @param string $value 249 258 */ 250 259 public function multisite_registration_on( $option_name, $value ) { 251 if ( 'user' === $value || 'all' === $value ) { 260 // Is registration enabled or are network invitations enabled? 261 if ( ( 'user' === $value || 'all' === $value ) 262 || bp_get_members_invitations_allowed() ) { 252 263 bp_core_add_page_mappings( array( 253 264 'register' => 1, 254 265 'activate' => 1 … … class BP_Members_Admin { 266 277 */ 267 278 public function single_site_registration_on( $old_value, $value ) { 268 279 // Single site. 269 if ( ! is_multisite() && ! empty( $value) ) {280 if ( ! is_multisite() && ( ! empty( $value ) || bp_get_members_invitations_allowed() ) ) { 270 281 bp_core_add_page_mappings( array( 271 282 'register' => 1, 272 283 'activate' => 1 … … class BP_Members_Admin { 490 501 ); 491 502 } 492 503 504 // For consistency with non-Multisite, we add a Tools menu in 505 // the Network Admin as a home for our Tools panel. 506 if ( is_multisite() && bp_core_do_network_admin() ) { 507 $tools_parent = 'network-tools'; 508 } else { 509 $tools_parent = 'tools.php'; 510 } 511 512 $hooks['members_invitations'] = $this->members_invites_page = add_submenu_page( 513 $tools_parent, 514 __( 'Manage Invitations', 'buddypress' ), 515 __( 'Manage Invitations', 'buddypress' ), 516 $this->capability, 517 'bp-members-invitations', 518 array( $this, 'invitations_admin' ) 519 ); 520 493 521 $edit_page = 'user-edit'; 494 522 $profile_page = 'profile'; 495 523 $this->users_page = 'users'; … … class BP_Members_Admin { 510 538 $this->users_page .= '-network'; 511 539 $this->signups_page .= '-network'; 512 540 513 $this->members_ optouts_page .= '-network';541 $this->members_invites_page .= '-network'; 514 542 } 515 543 516 544 // Setup the screen ID's. … … class BP_Members_Admin { 598 626 public function admin_head() { 599 627 remove_submenu_page( 'users.php', 'bp-profile-edit' ); 600 628 remove_submenu_page( 'profile.php', 'bp-profile-edit' ); 629 630 // Manage Invitations Tool screen is a tab of BP Tools. 631 if ( is_network_admin() ) { 632 remove_submenu_page( 'network-tools', 'bp-members-invitations' ); 633 } else { 634 remove_submenu_page( 'tools.php', 'bp-members-invitations' ); 635 } 601 636 } 602 637 603 638 /** Community Profile *****************************************************/ … … class BP_Members_Admin { 2566 2601 2567 2602 return $value; 2568 2603 } 2604 2605 /** 2606 * Set up the signups admin page. 2607 * 2608 * Loaded before the page is rendered, this function does all initial 2609 * setup, including: processing form requests, registering contextual 2610 * help, and setting up screen options. 2611 * 2612 * @since 8.0.0 2613 * 2614 * @global $bp_members_invitations_list_table 2615 */ 2616 public function members_invitations_admin_load() { 2617 global $bp_members_invitations_list_table; 2618 2619 // Build redirection URL. 2620 $redirect_to = remove_query_arg( array( 'action', 'error', 'updated', 'activated', 'notactivated', 'deleted', 'notdeleted', 'resent', 'notresent', 'do_delete', 'do_resend', 'do_activate', '_wpnonce', 'signup_ids' ), $_SERVER['REQUEST_URI'] ); 2621 $doaction = bp_admin_list_table_current_bulk_action(); 2622 2623 /** 2624 * Fires at the start of the member invitations admin load. 2625 * 2626 * @since 8.0.0 2627 * 2628 * @param string $doaction Current bulk action being processed. 2629 * @param array $_REQUEST Current $_REQUEST global. 2630 */ 2631 do_action( 'bp_members_invitations_admin_load', $doaction, $_REQUEST ); 2632 2633 /** 2634 * Filters the allowed actions for use in the user signups admin page. 2635 * 2636 * @since 8.0.0 2637 * 2638 * @param array $value Array of allowed actions to use. 2639 */ 2640 $allowed_actions = apply_filters( 'bp_members_invitations_admin_allowed_actions', array( 'do_delete', 'do_resend' ) ); 2641 2642 // Prepare the display of the bulk invitation action screen. 2643 if ( ! in_array( $doaction, $allowed_actions ) ) { 2644 2645 $bp_members_invitations_list_table = self::get_list_table_class( 'BP_Members_Invitations_List_Table', 'users' ); 2646 2647 // The per_page screen option. 2648 add_screen_option( 'per_page', array( 'label' => _x( 'Members Invitations', 'Members Invitations per page (screen options)', 'buddypress' ) ) ); 2649 2650 get_current_screen()->add_help_tab( array( 2651 'id' => 'bp-members-invitations-overview', 2652 'title' => __( 'Overview', 'buddypress' ), 2653 'content' => 2654 '<p>' . __( 'This is the administration screen for member invitations on your site.', 'buddypress' ) . '</p>' . 2655 '<p>' . __( 'From the screen options, you can customize the displayed columns and the pagination of this screen.', 'buddypress' ) . '</p>' . 2656 '<p>' . __( 'You can reorder the list of invitations by clicking on the Invitee, Inviter, Date Modified, Email Sent, or Accepted column headers.', 'buddypress' ) . '</p>' . 2657 '<p>' . __( 'Using the search form, you can find specific invitations more easily. The Invitee Email field will be included in the search.', 'buddypress' ) . '</p>' 2658 ) ); 2659 2660 get_current_screen()->add_help_tab( array( 2661 'id' => 'bp-members-invitations-actions', 2662 'title' => __( 'Actions', 'buddypress' ), 2663 'content' => 2664 '<p>' . __( 'Hovering over a row in the pending accounts list will display action links that allow you to manage pending accounts. You can perform the following actions:', 'buddypress' ) . '</p>' . 2665 '<ul><li>' . __( '"Send" or "Resend" takes you to the confirmation screen before being able to send or resend the invitation email to the desired pending invitee.', 'buddypress' ) . '</li>' . 2666 '<li>' . __( '"Delete" allows you to delete an unsent or accepted invitation from your site; "Cancel" allows you to cancel a sent, but not yet accepted, invitation. You will be asked to confirm this deletion.', 'buddypress' ) . '</li></ul>' . 2667 '<p>' . __( 'Bulk actions allow you to perform these actions for the selected rows.', 'buddypress' ) . '</p>' 2668 ) ); 2669 2670 // Help panel - sidebar links. 2671 get_current_screen()->set_help_sidebar( 2672 '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' . 2673 '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>' 2674 ); 2675 2676 // Add accessible hidden headings and text for the Pending Users screen. 2677 get_current_screen()->set_screen_reader_content( array( 2678 /* translators: accessibility text */ 2679 'heading_views' => __( 'Filter invitations list', 'buddypress' ), 2680 /* translators: accessibility text */ 2681 'heading_pagination' => __( 'Invitation list navigation', 'buddypress' ), 2682 /* translators: accessibility text */ 2683 'heading_list' => __( 'Invitations list', 'buddypress' ), 2684 ) ); 2685 2686 } else { 2687 if ( empty( $_REQUEST['invite_ids' ] ) ) { 2688 return; 2689 } 2690 $invite_ids = wp_parse_id_list( $_REQUEST['invite_ids' ] ); 2691 2692 // Handle resent invitations. 2693 if ( 'do_resend' == $doaction ) { 2694 2695 // Nonce check. 2696 check_admin_referer( 'invitations_resend' ); 2697 2698 $success = 0; 2699 foreach ( $invite_ids as $invite_id ) { 2700 if ( bp_members_invitation_resend_by_id( $invite_id ) ) { 2701 $success++; 2702 } 2703 } 2704 2705 $query_arg = array( 'updated' => 'resent' ); 2706 2707 if ( ! empty( $success ) ) { 2708 $query_arg['resent'] = $success; 2709 } 2710 2711 $not_sent = count( $invite_ids ) - $success; 2712 if ( $not_sent > 0 ) { 2713 $query_arg['notsent'] = $not_sent; 2714 } 2715 2716 $redirect_to = add_query_arg( $query_arg, $redirect_to ); 2717 2718 bp_core_redirect( $redirect_to ); 2719 2720 // Handle invitation deletion. 2721 } elseif ( 'do_delete' == $doaction ) { 2722 2723 // Nonce check. 2724 check_admin_referer( 'invitations_delete' ); 2725 2726 $success = 0; 2727 foreach ( $invite_ids as $invite_id ) { 2728 if ( bp_members_invitations_delete_by_id( $invite_id ) ) { 2729 $success++; 2730 } 2731 } 2732 2733 $query_arg = array( 'updated' => 'deleted' ); 2734 2735 if ( ! empty( $success ) ) { 2736 $query_arg['deleted'] = $success; 2737 } 2738 2739 $notdeleted = count( $invite_ids ) - $success; 2740 if ( $notdeleted > 0 ) { 2741 $query_arg['notdeleted'] = $notdeleted; 2742 } 2743 2744 $redirect_to = add_query_arg( $query_arg, $redirect_to ); 2745 2746 bp_core_redirect( $redirect_to ); 2747 2748 // Plugins can update other stuff from here. 2749 } else { 2750 $this->redirect = $redirect_to; 2751 2752 /** 2753 * Fires at end of member invitations admin load 2754 * if doaction does not match any actions. 2755 * 2756 * @since 8.0.0 2757 * 2758 * @param string $doaction Current bulk action being processed. 2759 * @param array $_REQUEST Current $_REQUEST global. 2760 * @param string $redirect Determined redirect url to send user to. 2761 */ 2762 do_action( 'bp_members_admin_update_invitations', $doaction, $_REQUEST, $this->redirect ); 2763 2764 bp_core_redirect( $this->redirect ); 2765 } 2766 } 2767 } 2768 2769 /** 2770 * Get admin notice when viewing the invitations management page. 2771 * 2772 * @since 8.0.0 2773 * 2774 * @return array 2775 */ 2776 private function get_members_invitations_notice() { 2777 2778 // Setup empty notice for return value. 2779 $notice = array(); 2780 2781 // Updates. 2782 if ( ! empty( $_REQUEST['updated'] ) ) { 2783 switch ( $_REQUEST['updated'] ) { 2784 case 'resent': 2785 $notice = array( 2786 'class' => 'updated', 2787 'message' => '' 2788 ); 2789 2790 if ( ! empty( $_REQUEST['resent'] ) ) { 2791 $notice['message'] .= sprintf( 2792 /* translators: %s: number of invitation emails sent */ 2793 _nx( '%s invtitation email successfully sent! ', '%s invitation emails successfully sent! ', 2794 absint( $_REQUEST['resent'] ), 2795 'members invitation resent', 2796 'buddypress' 2797 ), 2798 number_format_i18n( absint( $_REQUEST['resent'] ) ) 2799 ); 2800 } 2801 2802 if ( ! empty( $_REQUEST['notsent'] ) ) { 2803 $notice['message'] .= sprintf( 2804 /* translators: %s: number of unsent invitation emails */ 2805 _nx( '%s invitation email was not sent.', '%s invitation emails were not sent.', 2806 absint( $_REQUEST['notsent'] ), 2807 'members invitation notsent', 2808 'buddypress' 2809 ), 2810 number_format_i18n( absint( $_REQUEST['notsent'] ) ) 2811 ); 2812 2813 if ( empty( $_REQUEST['resent'] ) ) { 2814 $notice['class'] = 'error'; 2815 } 2816 } 2817 2818 break; 2819 2820 case 'deleted': 2821 $notice = array( 2822 'class' => 'updated', 2823 'message' => '' 2824 ); 2825 2826 if ( ! empty( $_REQUEST['deleted'] ) ) { 2827 $notice['message'] .= sprintf( 2828 /* translators: %s: number of deleted invitations */ 2829 _nx( '%s invitation successfully deleted!', '%s invitations successfully deleted!', 2830 absint( $_REQUEST['deleted'] ), 2831 'members invitation deleted', 2832 'buddypress' 2833 ), 2834 number_format_i18n( absint( $_REQUEST['deleted'] ) ) 2835 ); 2836 } 2837 2838 if ( ! empty( $_REQUEST['notdeleted'] ) ) { 2839 $notice['message'] .= sprintf( 2840 /* translators: %s: number of invitations that failed to be deleted */ 2841 _nx( '%s invitation was not deleted.', '%s invitations were not deleted.', 2842 absint( $_REQUEST['notdeleted'] ), 2843 'members invitation notdeleted', 2844 'buddypress' 2845 ), 2846 number_format_i18n( absint( $_REQUEST['notdeleted'] ) ) 2847 ); 2848 2849 if ( empty( $_REQUEST['deleted'] ) ) { 2850 $notice['class'] = 'error'; 2851 } 2852 } 2853 2854 break; 2855 } 2856 } 2857 2858 // Errors. 2859 if ( ! empty( $_REQUEST['error'] ) ) { 2860 switch ( $_REQUEST['error'] ) { 2861 case 'do_resend': 2862 $notice = array( 2863 'class' => 'error', 2864 'message' => esc_html__( 'There was a problem sending the invitation emails. Please try again.', 'buddypress' ), 2865 ); 2866 break; 2867 2868 case 'do_delete': 2869 $notice = array( 2870 'class' => 'error', 2871 'message' => esc_html__( 'There was a problem deleting invitations. Please try again.', 'buddypress' ), 2872 ); 2873 break; 2874 } 2875 } 2876 2877 return $notice; 2878 } 2879 2880 /** 2881 * Member invitations admin page router. 2882 * 2883 * Depending on the context, display 2884 * - the list of invitations, 2885 * - or the delete confirmation screen, 2886 * - or the "resend" email confirmation screen. 2887 * 2888 * Also prepare the admin notices. 2889 * 2890 * @since 8.0.0 2891 */ 2892 public function invitations_admin() { 2893 $doaction = bp_admin_list_table_current_bulk_action(); 2894 2895 // Prepare notices for admin. 2896 $notice = $this->get_members_invitations_notice(); 2897 2898 // Display notices. 2899 if ( ! empty( $notice ) ) : 2900 if ( 'updated' === $notice['class'] ) : ?> 2901 2902 <div id="message" class="<?php echo esc_attr( $notice['class'] ); ?> notice is-dismissible"> 2903 2904 <?php else: ?> 2905 2906 <div class="<?php echo esc_attr( $notice['class'] ); ?> notice is-dismissible"> 2907 2908 <?php endif; ?> 2909 2910 <p><?php echo $notice['message']; ?></p> 2911 </div> 2912 2913 <?php endif; 2914 2915 // Show the proper screen. 2916 switch ( $doaction ) { 2917 case 'delete' : 2918 case 'resend' : 2919 $this->invitations_admin_manage( $doaction ); 2920 break; 2921 2922 default: 2923 $this->invitations_admin_index(); 2924 break; 2925 } 2926 } 2927 2928 /** 2929 * This is the list of invitations. 2930 * 2931 * @since 8.0.0 2932 * 2933 * @global $plugin_page 2934 * @global $bp_members_invitations_list_table 2935 */ 2936 public function invitations_admin_index() { 2937 global $plugin_page, $bp_members_invitations_list_table; 2938 2939 $usersearch = ! empty( $_REQUEST['s'] ) ? stripslashes( $_REQUEST['s'] ) : ''; 2940 2941 // Prepare the group items for display. 2942 $bp_members_invitations_list_table->prepare_items(); 2943 2944 if ( is_network_admin() ) { 2945 $form_url = network_admin_url( 'admin.php' ); 2946 } else { 2947 $form_url = bp_get_admin_url( 'tools.php' ); 2948 } 2949 2950 $form_url = add_query_arg( 2951 array( 2952 'page' => 'bp-members-invitations', 2953 ), 2954 $form_url 2955 ); 2956 2957 $search_form_url = remove_query_arg( 2958 array( 2959 'action', 2960 'deleted', 2961 'notdeleted', 2962 'error', 2963 'updated', 2964 'delete', 2965 'activate', 2966 'activated', 2967 'notactivated', 2968 'resend', 2969 'resent', 2970 'notresent', 2971 'do_delete', 2972 'do_activate', 2973 'do_resend', 2974 'action2', 2975 '_wpnonce', 2976 'invite_ids' 2977 ), $_SERVER['REQUEST_URI'] 2978 ); 2979 2980 ?> 2981 2982 <div class="wrap"> 2983 <h1 class="wp-heading-inline"><?php esc_html_e( 'BuddyPress tools', 'buddypress' ); ?></h1> 2984 <hr class="wp-header-end"> 2985 2986 <h2 class="nav-tab-wrapper"><?php bp_core_admin_tabs( __( 'Manage Invitations', 'buddypress' ), 'tools' ); ?></h2> 2987 2988 <?php 2989 if ( $usersearch ) { 2990 printf( '<span class="subtitle">' . __( 'Search results for “%s”', 'buddypress' ) . '</span>', esc_html( $usersearch ) ); 2991 } 2992 ?> 2993 2994 <hr class="wp-header-end"> 2995 2996 <?php // Display each invitation on its own row. ?> 2997 <?php $bp_members_invitations_list_table->views(); ?> 2998 2999 <form id="bp-members-invitations-search-form" action="<?php echo esc_url( $search_form_url ) ;?>"> 3000 <input type="hidden" name="page" value="<?php echo esc_attr( $plugin_page ); ?>" /> 3001 <?php $bp_members_invitations_list_table->search_box( __( 'Search Invitations', 'buddypress' ), 'bp-members-invitations' ); ?> 3002 </form> 3003 3004 <form id="bp-members-invitations-form" action="<?php echo esc_url( $form_url );?>" method="post"> 3005 <?php $bp_members_invitations_list_table->display(); ?> 3006 </form> 3007 </div> 3008 <?php 3009 } 3010 3011 /** 3012 * This is the confirmation screen for actions. 3013 * 3014 * @since 2.0.0 3015 * 3016 * @param string $action Delete or resend invitation. 3017 * 3018 * @return null|false 3019 */ 3020 public function invitations_admin_manage( $action = '' ) { 3021 if ( ! current_user_can( $this->capability ) || empty( $action ) ) { 3022 die( '-1' ); 3023 } 3024 3025 // Get the IDs from the URL. 3026 $ids = false; 3027 if ( ! empty( $_POST['invite_ids'] ) ) { 3028 $ids = wp_parse_id_list( $_POST['invite_ids'] ); 3029 } elseif ( ! empty( $_GET['invite_id'] ) ) { 3030 $ids = absint( $_GET['invite_id'] ); 3031 } 3032 3033 3034 if ( empty( $ids ) ) { 3035 return false; 3036 } 3037 3038 // Check invite IDs and set up strings. 3039 switch ( $action ) { 3040 case 'delete' : 3041 // Query for matching invites, and filter out bad IDs. 3042 $args = array( 3043 'id' => $ids, 3044 'invite_sent' => 'all', 3045 'accepted' => 'all', 3046 ); 3047 $invites = bp_members_invitations_get_invites( $args ); 3048 $invite_ids = wp_list_pluck( $invites, 'id' ); 3049 3050 $header_text = __( 'Delete Invitations', 'buddypress' ); 3051 if ( 0 === count( $invite_ids ) ) { 3052 $helper_text = __( 'No invites were found, nothing to delete!', 'buddypress' ); 3053 } else { 3054 $helper_text = _n( 'You are about to delete the following invitation:', 'You are about to delete the following invitations:', count( $invite_ids ), 'buddypress' ); 3055 } 3056 break; 3057 3058 case 'resend' : 3059 /** 3060 * Query for matching invites, and filter out bad IDs 3061 * or those that have already been accepted. 3062 */ 3063 $args = array( 3064 'id' => $ids, 3065 'invite_sent' => 'all', 3066 'accepted' => 'pending', 3067 ); 3068 $invites = bp_members_invitations_get_invites( $args ); 3069 $invite_ids = wp_list_pluck( $invites, 'id' ); 3070 3071 $header_text = __( 'Resend Invitation Emails', 'buddypress' ); 3072 if ( 0 === count( $invite_ids ) ) { 3073 $helper_text = __( 'No pending invites were found, nothing to resend!', 'buddypress' ); 3074 } else { 3075 $helper_text = _n( 'You are about to resend an invitation email to the following address:', 'You are about to resend invitation emails to the following addresses:', count( $invite_ids ), 'buddypress' ); 3076 } 3077 break; 3078 } 3079 3080 // These arguments are added to all URLs. 3081 $url_args = array( 'page' => 'bp-members-invitations' ); 3082 3083 // These arguments are only added when performing an action. 3084 $action_args = array( 3085 'action' => 'do_' . $action, 3086 'invite_ids' => implode( ',', $invite_ids ) 3087 ); 3088 3089 if ( is_network_admin() ) { 3090 $form_url = network_admin_url( 'admin.php' ); 3091 } else { 3092 $form_url = bp_get_admin_url( 'tools.php' ); 3093 } 3094 3095 $cancel_url = add_query_arg( $url_args, $base_url ); 3096 $action_url = wp_nonce_url( 3097 add_query_arg( 3098 array_merge( $url_args, $action_args ), 3099 $base_url 3100 ), 3101 'invitations_' . $action 3102 ); 3103 3104 ?> 3105 3106 <div class="wrap"> 3107 <h1 class="wp-heading-inline"><?php echo esc_html( $header_text ); ?></h1> 3108 <hr class="wp-header-end"> 3109 3110 <p><?php echo esc_html( $helper_text ); ?></p> 3111 3112 <?php if ( $invites ) : ?> 3113 3114 <ol class="bp-invitations-list"> 3115 <?php foreach ( $invites as $invite ) : 3116 if ( $invite->invite_sent ) { 3117 $last_notified = mysql2date( 'Y/m/d g:i:s a', $invite->date_modified ); 3118 } else { 3119 $last_notified = __( 'Not yet notified', 'buddypress'); 3120 } 3121 ?> 3122 3123 <li> 3124 <strong><?php echo esc_html( $invite->invitee_email ) ?></strong> 3125 3126 <?php if ( 'resend' === $action ) : ?> 3127 3128 <p class="description"> 3129 <?php 3130 /* translators: %s: notification date */ 3131 printf( esc_html__( 'Last notified: %s', 'buddypress'), $last_notified ); 3132 ?> 3133 </p> 3134 3135 <?php endif; ?> 3136 3137 </li> 3138 3139 <?php endforeach; ?> 3140 </ol> 3141 3142 <?php endif ; ?> 3143 3144 <?php if ( 'delete' === $action ) : ?> 3145 3146 <p><strong><?php esc_html_e( 'This action cannot be undone.', 'buddypress' ) ?></strong></p> 3147 3148 <?php endif; ?> 3149 3150 <?php if ( $invites ) : ?> 3151 3152 <a class="button-primary" href="<?php echo esc_url( $action_url ); ?>" <?php disabled( ! $invites ); ?>><?php esc_html_e( 'Confirm', 'buddypress' ); ?></a> 3153 3154 <?php endif; ?> 3155 3156 <a class="button" href="<?php echo esc_url( $cancel_url ); ?>"><?php esc_html_e( 'Cancel', 'buddypress' ) ?></a> 3157 </div> 3158 3159 <?php 3160 } 3161 2569 3162 } 2570 3163 endif; // End class_exists check. -
src/bp-members/classes/class-bp-members-component.php
diff --git src/bp-members/classes/class-bp-members-component.php src/bp-members/classes/class-bp-members-component.php index 4db47da8d..ec10398ae 100644
class BP_Members_Component extends BP_Component { 39 39 buddypress()->plugin_dir, 40 40 array( 41 41 'adminbar_myaccount_order' => 20, 42 'search_query_arg' => 'members_search', 42 'search_query_arg' => 'members_search', 43 'features' => array( 'invitations' ) 43 44 ) 44 45 ); 45 46 } … … class BP_Members_Component extends BP_Component { 64 65 'blocks', 65 66 'widgets', 66 67 'cache', 68 'invitations', 67 69 ); 68 70 69 71 if ( bp_is_active( 'activity' ) ) { … … class BP_Members_Component extends BP_Component { 137 139 // Theme compatibility. 138 140 new BP_Registration_Theme_Compat(); 139 141 } 142 143 // Invitations. 144 if ( is_user_logged_in() && bp_is_user_members_invitations() ) { 145 if ( bp_is_user_members_invitations_list() ) { 146 require $this->path . 'bp-members/screens/list-invites.php'; 147 } else { 148 require $this->path . 'bp-members/screens/send-invites.php'; 149 } 150 } 140 151 } 141 152 142 153 /** … … class BP_Members_Component extends BP_Component { 233 244 $bp->profile->slug = 'profile'; 234 245 $bp->profile->id = 'profile'; 235 246 } 247 248 /** Network Invitations ************************************************** 249 */ 250 251 $bp->members->invitations = new stdClass; 236 252 } 237 253 238 254 /** … … class BP_Members_Component extends BP_Component { 468 484 } 469 485 } 470 486 471 472 487 parent::setup_nav( $main_nav, $sub_nav ); 473 488 } 474 489 … … class BP_Members_Component extends BP_Component { 549 564 return $wp_admin_nav; 550 565 } 551 566 567 /** 568 * Get the members invitations admin bar navs. 569 * 570 * @since 8.0.0 571 * 572 * @param string $admin_bar_menu_id The Admin bar menu ID to attach sub items to. 573 * @return array The members invitations admin navs. 574 */ 575 public function get_members_invitations_admin_navs( $admin_bar_menu_id = '' ) { 576 $wp_admin_nav = array(); 577 $invite_link = trailingslashit( bp_loggedin_user_domain() . bp_get_profile_slug() ); 578 579 if ( ! $admin_bar_menu_id ) { 580 $admin_bar_menu_id = $this->id; 581 } 582 583 return $wp_admin_nav; 584 } 585 552 586 /** 553 587 * Set up the Admin Bar. 554 588 * … … class BP_Members_Component extends BP_Component { 590 624 } else { 591 625 add_filter( 'bp_xprofile_admin_nav', array( $this, 'setup_xprofile_admin_nav' ), 2 ); 592 626 } 627 628 // $wp_admin_nav = array_merge( $wp_admin_nav, $this->get_members_invitations_admin_navs() ); 593 629 } 594 630 595 631 parent::setup_admin_bar( $wp_admin_nav ); -
new file src/bp-members/classes/class-bp-members-invitation-manager.php
diff --git src/bp-members/classes/class-bp-members-invitation-manager.php src/bp-members/classes/class-bp-members-invitation-manager.php new file mode 100644 index 000000000..139caf279
- + 1 <?php 2 /** 3 * Membership invitations class. 4 * 5 * @package BuddyPress 6 * @subpackage Core 7 * @since 8.0.0 8 */ 9 10 // Exit if accessed directly. 11 defined( 'ABSPATH' ) || exit; 12 13 /** 14 * Membership invitations class. 15 * 16 * An extension of the core Invitations class that adapts the 17 * core logic to accommodate site membership invitation behavior. 18 * 19 * @since 8.0.0 20 */ 21 class BP_Members_Invitation_Manager extends BP_Invitation_Manager { 22 /** 23 * Construct parameters. 24 * 25 * @since 8.0.0 26 * 27 * @param array|string $args. 28 */ 29 public function __construct( $args = '' ) { 30 parent::__construct(); 31 } 32 33 /** 34 * This is where custom actions are added to run when notifications of an 35 * invitation or request need to be generated & sent. 36 * 37 * @since 8.0.0 38 * 39 * @param obj BP_Invitation $invitation The invitation to send. 40 * @return bool True on success, false on failure. 41 */ 42 public function run_send_action( BP_Invitation $invitation ) { 43 // Notify site admins of the pending request 44 if ( 'request' === $invitation->type ) { 45 // @TODO 46 return true; 47 // Notify the invitee of the invitation. 48 } else { 49 // Stop if the invitation has already been accepted. 50 if ( $invitation->accepted ) { 51 return false; 52 } 53 54 $inviter_ud = bp_core_get_core_userdata( $invitation->inviter_id ); 55 56 $invite_url = esc_url( 57 add_query_arg( 58 array( 59 'inv' => $invitation->id, 60 'ih' => bp_members_invitations_get_hash( $invitation ), 61 ), bp_get_signup_page() 62 ) 63 ); 64 $unsubscribe_args = array( 65 'user_id' => 0, 66 'email_address' => $invitation->invitee_email, 67 'notification_type' => 'bp-members-invitation', 68 ); 69 70 $args = array( 71 'tokens' => array( 72 'inviter.name' => bp_core_get_userlink( $invitation->inviter_id, true, false, true ), 73 'inviter.url' => bp_core_get_user_domain( $invitation->inviter_id ), 74 'inviter.id' => $invitation->inviter_id, 75 'invite.accept_url' => esc_url( $invite_url ), 76 'usermessage' => $invitation->content, 77 'unsubscribe' => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ), 78 ), 79 ); 80 81 return bp_send_email( 'bp-members-invitation', $invitation->invitee_email, $args ); 82 } 83 } 84 85 /** 86 * This is where custom actions are added to run when an invitation 87 * or request is accepted. 88 * 89 * @since 8.0.0 90 * 91 * @param string $type Are we accepting an invitation or request? 92 * @param array $r Parameters that describe the invitation being accepted. 93 * @return bool True on success, false on failure. 94 */ 95 public function run_acceptance_action( $type = 'invite', $r ) { 96 // If the user is already a member (because BP at one point allowed two invitations to 97 // slip through), return early. 98 99 if ( 'request' === $type ) { 100 /** 101 * Fires after a network membership request has been accepted. 102 * 103 * @since 8.0.0 104 * 105 * @param int $user_id ID of the user who accepted membership. 106 * @param int $network_id ID of the network that was accepted membership to. 107 */ 108 do_action( 'network_membership_request_accepted', $r['user_id'], $r['item_id'] ); 109 } else { 110 /** 111 * Fires after a user has accepted a site membership invite. 112 * 113 * @since 8.0.0 114 * 115 * @param int $user_id ID of the user who accepted the membership invite. 116 * @param int $inviter_id ID of the user who invited this user to the group. 117 */ 118 do_action( 'network_membership_invite_accepted', $r['user_id'], $inviter_id ); 119 } 120 121 122 return true; 123 } 124 125 /** 126 * Should this invitation be created? 127 * 128 * @since 8.0.0 129 * 130 * @param array $args. 131 * @return bool 132 */ 133 public function allow_invitation( $args ) { 134 // Does the inviter have this capability? 135 if ( ! bp_user_can( $args['inviter_id'], 'bp_members_send_invitation' ) ) { 136 return false; 137 } 138 139 // Is the invited user eligible to receive an invitation? Hasn't opted out? 140 if ( ! bp_user_can( 0, 'bp_members_receive_invitation', $args ) ) { 141 return false; 142 } 143 144 return true; 145 } 146 147 /** 148 * Should this request be created? 149 * 150 * @since 8.0.0 151 * 152 * @param array $args. 153 * @return bool. 154 */ 155 public function allow_request( $args ) { 156 // Does the requester have this capability? 157 if ( ! bp_user_can( 0, 'bp_network_request_membership', $args ) ) { 158 return false; 159 } 160 161 return true; 162 } 163 } -
new file src/bp-members/classes/class-bp-members-invitations-list-table.php
diff --git src/bp-members/classes/class-bp-members-invitations-list-table.php src/bp-members/classes/class-bp-members-invitations-list-table.php new file mode 100644 index 000000000..90f35d921
- + 1 <?php 2 /** 3 * BuddyPress Membership Invitation List Table class. 4 * 5 * @package BuddyPress 6 * @subpackage MembersAdminClasses 7 * @since 8.0.0 8 */ 9 10 // Exit if accessed directly. 11 defined( 'ABSPATH' ) || exit; 12 13 /** 14 * List table class for signups admin page. 15 * 16 * @since 8.0.0 17 */ 18 class BP_Members_Invitations_List_Table extends WP_Users_List_Table { 19 20 /** 21 * The type of view currently being displayed. 22 * 23 * E.g. "All", "Pending", "Sent", "Unsent"... 24 * 25 * @since 8.0.0 26 * @var string 27 */ 28 public $active_filters = array(); 29 30 /** 31 * Signup counts. 32 * 33 * @since 8.0.0 34 * 35 * @var int 36 */ 37 public $total_items = 0; 38 39 /** 40 * Constructor. 41 * 42 * @since 8.0.0 43 */ 44 public function __construct() { 45 // Define singular and plural labels, as well as whether we support AJAX. 46 parent::__construct( array( 47 'ajax' => false, 48 'plural' => 'invitations', 49 'singular' => 'invitation', 50 'screen' => get_current_screen()->id, 51 ) ); 52 } 53 54 /** 55 * Set up items for display in the list table. 56 * 57 * Handles filtering of data, sorting, pagination, and any other data 58 * manipulation required prior to rendering. 59 * 60 * @since 8.0.0 61 */ 62 public function prepare_items() { 63 global $usersearch; 64 65 $search = isset( $_REQUEST['s'] ) ? $_REQUEST['s'] : ''; 66 $per_page = $this->get_items_per_page( str_replace( '-', '_', "{$this->screen->id}_per_page" ) ); 67 $paged = $this->get_pagenum(); 68 69 $args = array( 70 'invite_sent' => 'all', 71 'accepted' => 'all', 72 'search_terms' => $search, 73 'order_by' => 'date_modified', 74 'sort_order' => 'DESC', 75 'page' => $paged, 76 'per_page' => $per_page, 77 ); 78 79 if ( isset( $_REQUEST['accepted'] ) && in_array( $_REQUEST['accepted'], array( 'pending', 'accepted' ), true ) ) { 80 $args['accepted'] = $_REQUEST['accepted']; 81 $this->active_filters[] = $_REQUEST['accepted']; 82 } 83 if ( isset( $_REQUEST['sent'] ) && in_array( $_REQUEST['sent'], array( 'draft', 'sent' ), true ) ) { 84 $args['invite_sent'] = $_REQUEST['sent']; 85 $this->active_filters[] = $_REQUEST['sent']; 86 } 87 88 if ( isset( $_REQUEST['orderby'] ) ) { 89 $args['order_by'] = $_REQUEST['orderby']; 90 } 91 92 if ( isset( $_REQUEST['order'] ) ) { 93 $args['sort_order'] = $_REQUEST['order']; 94 } 95 96 $invites_class = new BP_Members_Invitation_Manager(); 97 $this->items = $invites_class->get_invitations( $args ); 98 $this->total_items = $invites_class->get_invitations_total_count( $args ); 99 100 $this->set_pagination_args( array( 101 'total_items' => $this->total_items, 102 'per_page' => $per_page, 103 ) ); 104 } 105 106 /** 107 * Get the list of views available on this table (e.g. "all", "public"). 108 * 109 * @since 8.0.0 110 */ 111 public function views() { 112 $url_base = add_query_arg( 113 array( 114 'page' => 'bp-members-invitations', 115 ), 116 bp_get_admin_url( 'users.php' ) 117 ); 118 119 ?> 120 121 <h2 class="screen-reader-text"><?php 122 /* translators: accessibility text */ 123 _e( 'Filter invitations list', 'buddypress' ); 124 ?></h2> 125 <ul class="subsubsub"> 126 <li class="all"> 127 <a href="<?php echo esc_url( $url_base ); ?>" class="<?php if ( empty( $this->active_filters ) ) echo 'current'; ?>"> 128 <?php esc_html_e( 'All', 'buddypress' ); ?> 129 </a> | 130 </li> 131 <li class="pending"> 132 <a href="<?php echo esc_url( add_query_arg( 'accepted', 'pending', $url_base ) ); ?>" class="<?php if ( in_array( 'pending', $this->active_filters, true ) ) echo 'current'; ?>"> 133 <?php esc_html_e( 'Pending', 'buddypress' ); ?> 134 </a> | 135 </li> 136 <li class="accepted"> 137 <a href="<?php echo esc_url( add_query_arg( 'accepted', 'accepted', $url_base ) ); ?>" class="<?php if ( in_array( 'accepted', $this->active_filters, true ) ) echo 'current'; ?>"> 138 <?php esc_html_e( 'Accepted', 'buddypress' ); ?> 139 </a> | 140 </li> 141 <li class="draft"> 142 <a href="<?php echo esc_url( add_query_arg( 'sent', 'draft', $url_base ) ); ?>" class="<?php if ( in_array( 'draft', $this->active_filters, true ) ) echo 'current'; ?>"> 143 <?php esc_html_e( 'Draft (Unsent)', 'buddypress' ); ?> 144 </a> | 145 </li> 146 <li class="sent"> 147 <a href="<?php echo esc_url( add_query_arg( 'sent', 'sent', $url_base ) ); ?>" class="<?php if ( in_array( 'sent', $this->active_filters, true ) ) echo 'current'; ?>"> 148 <?php esc_html_e( 'Sent', 'buddypress' ); ?> 149 </a> | 150 </li> 151 152 <?php 153 154 /** 155 * Fires inside listing of views so plugins can add their own. 156 * 157 * @since 8.0.0 158 * 159 * @param string $url_base Current URL base for view. 160 * @param array $active_filters Current filters being requested. 161 */ 162 do_action( 'bp_members_invitations_list_table_get_views', $url_base, $this->active_filters ); ?> 163 </ul> 164 <?php 165 } 166 167 /** 168 * Get rid of the extra nav. 169 * 170 * WP_Users_List_Table will add an extra nav to change user's role. 171 * As we're dealing with invitations, we don't need this. 172 * 173 * @since 8.0.0 174 * 175 * @param array $which Current table nav item. 176 */ 177 public function extra_tablenav( $which ) { 178 return; 179 } 180 181 /** 182 * Specific signups columns. 183 * 184 * @since 8.0.0 185 * 186 * @return array 187 */ 188 public function get_columns() { 189 190 /** 191 * Filters the single site Members signup columns. 192 * 193 * @since 8.0.0 194 * 195 * @param array $value Array of columns to display. 196 */ 197 return apply_filters( 'bp_members_invitations_list_columns', array( 198 'cb' => '<input type="checkbox" />', 199 'invitee_email' => __( 'Invitee', 'buddypress' ), 200 'username' => __( 'Inviter', 'buddypress' ), 201 'inviter_registered_date' => __( 'Inviter Registered', 'buddypress' ), 202 'invitation_date_modified' => __( 'Date Modified', 'buddypress' ), 203 'invitation_sent' => __( 'Email Sent', 'buddypress' ), 204 'invitation_accepted' => __( 'Accepted', 'buddypress' ) 205 ) ); 206 } 207 208 /** 209 * Specific bulk actions for signups. 210 * 211 * @since 8.0.0 212 */ 213 public function get_bulk_actions() { 214 $actions = array( 215 'resend' => _x( 'Resend Email', 'Pending invitation action', 'buddypress' ), 216 ); 217 218 if ( current_user_can( 'delete_users' ) ) { 219 $actions['delete'] = _x( 'Delete', 'Pending invitation action', 'buddypress' ); 220 } 221 222 return $actions; 223 } 224 225 /** 226 * The text shown when no items are found. 227 * 228 * Nice job, clean sheet! 229 * 230 * @since 8.0.0 231 */ 232 public function no_items() { 233 234 if ( bp_get_members_invitations_allowed() ) { 235 esc_html_e( 'No pending invitations found.', 'buddypress' ); 236 } else { 237 $link = sprintf( '<a href="%1$s">%2$s</a>', esc_url( bp_get_admin_url( add_query_arg( array( 'page' => 'bp-settings' ), 'admin.php' ) ) ), esc_html__( 'Edit settings', 'buddypress' ) ); 238 239 /* translators: %s: url to site settings */ 240 printf( __( 'Invitations are not allowed. %s', 'buddypress' ), $link ); 241 } 242 243 } 244 245 /** 246 * The columns invitations can be reordered by. 247 * 248 * @since 8.0.0 249 */ 250 public function get_sortable_columns() { 251 return array( 252 'invitee_email' => 'invitee_email', 253 'username' => 'inviter_id', 254 'invitation_date_modified' => 'date_modified', 255 'invitation_sent' => 'invite_sent', 256 'invitation_accepted' => 'accepted', 257 ); 258 } 259 260 /** 261 * Display invitation rows. 262 * 263 * @since 8.0.0 264 */ 265 public function display_rows() { 266 $style = ''; 267 foreach ( $this->items as $invite ) { 268 $style = ( ' class="alternate"' == $style ) ? '' : ' class="alternate"'; 269 echo "\n\t" . $this->single_row( $invite, $style ); 270 } 271 } 272 273 /** 274 * Display an invitation row. 275 * 276 * @since 8.0.0 277 * 278 * @see WP_List_Table::single_row() for explanation of params. 279 * 280 * @param BP_Invitation $invite BP_Invitation object. 281 * @param string $style Styles for the row. 282 * @param string $role Role to be assigned to user. 283 * @param int $numposts Number of posts. 284 * @return void 285 */ 286 public function single_row( $invite = null, $style = '', $role = '', $numposts = 0 ) { 287 echo '<tr' . $style . ' id="invitation-' . esc_attr( $invite->id ) . '">'; 288 echo $this->single_row_columns( $invite ); 289 echo '</tr>'; 290 } 291 292 /** 293 * Markup for the checkbox used to select items for bulk actions. 294 * 295 * @since 8.0.0 296 * 297 * @param BP_Invitation $invite BP_Invitation object. 298 */ 299 public function column_cb( $invite = null ) { 300 ?> 301 <label class="screen-reader-text" for="invitation_<?php echo intval( $invite->id ); ?>"><?php 302 /* translators: accessibility text */ 303 printf( esc_html__( 'Select invitation: %s', 'buddypress' ), $invite->id ); 304 ?></label> 305 <input type="checkbox" id="invitation_<?php echo intval( $invite->id ) ?>" name="invite_ids[]" value="<?php echo esc_attr( $invite->id ) ?>" /> 306 <?php 307 } 308 309 /** 310 * Markup for the checkbox used to select items for bulk actions. 311 * 312 * @since 8.0.0 313 * 314 * @param BP_Invitation $invite BP_Invitation object. 315 */ 316 public function column_invitee_email( $invite = null ) { 317 echo esc_html( $invite->invitee_email ); 318 319 $actions = array(); 320 321 // Resend action only if pending 322 if ( ! $invite->accepted ) { 323 // Resend invitation email link. 324 $email_link = add_query_arg( 325 array( 326 'page' => 'bp-members-invitations', 327 'invite_id' => $invite->id, 328 'action' => 'resend', 329 ), 330 bp_get_admin_url( 'users.php' ) 331 ); 332 if ( ! $invite->invite_sent ) { 333 $resend_label = __( 'Send', 'buddypress' ); 334 } else { 335 $resend_label = __( 'Resend', 'buddypress' ); 336 } 337 $actions['resend'] = sprintf( '<a href="%1$s">%2$s</a>', esc_url( $email_link ), $resend_label ); 338 } 339 340 // Delete link. Could be cleanup or revoking the invitation. 341 $delete_link = add_query_arg( 342 array( 343 'page' => 'bp-members-invitations', 344 'invite_id' => $invite->id, 345 'action' => 'delete', 346 ), 347 bp_get_admin_url( 'users.php' ) 348 ); 349 // Two cases: unsent and accepted (cleanup), and pending (cancels invite). 350 if ( ! $invite->invite_sent || $invite->accepted ) { 351 $actions['delete'] = sprintf( '<a href="%1$s" class="delete">%2$s</a>', esc_url( $delete_link ), __( 'Delete', 'buddypress' ) ); 352 } else { 353 $actions['delete'] = sprintf( '<a href="%1$s" class="delete">%2$s</a>', esc_url( $delete_link ), __( 'Cancel', 'buddypress' ) ); 354 } 355 356 /** 357 * Filters the row actions for each invitation in list. 358 * 359 * @since 8.0.0 360 * 361 * @param array $actions Array of actions and corresponding links. 362 * @param object $invite The BP_Invitation. 363 */ 364 $actions = apply_filters( 'bp_members_invitations_management_row_actions', $actions, $invite ); 365 366 echo $this->row_actions( $actions ); 367 } 368 369 /** 370 * Display invited user's email address. 371 * 372 * @since 8.0.0 373 * 374 * @param BP_Invitation $invite BP_Invitation object. 375 */ 376 public function column_email( $invite = null ) { 377 printf( '<a href="mailto:%1$s">%2$s</a>', esc_attr( $invite->user_email ), esc_html( $invite->user_email ) ); 378 } 379 380 /** 381 * The inviter. 382 * 383 * @since 8.0.0 384 * 385 * @param BP_Invitation $invite BP_Invitation object. 386 */ 387 public function column_username( $invite = null ) { 388 $avatar = get_avatar( $invite->inviter_id, 32 ); 389 $inviter = get_user_by( 'id', $invite->inviter_id ); 390 if ( ! $inviter ) { 391 return; 392 } 393 $user_link = bp_core_get_user_domain( $invite->inviter_id ); 394 echo $avatar . sprintf( '<strong><a href="%1$s" class="edit">%2$s</a></strong><br/>', esc_url( $user_link ), $inviter->user_login ); 395 } 396 397 /** 398 * Display invitation date. 399 * 400 * @since 8.0.0 401 * 402 * @param BP_Invitation $invite BP_Invitation object. 403 */ 404 public function column_inviter_registered_date( $invite = null ) { 405 $inviter = get_user_by( 'id', $invite->inviter_id ); 406 if ( ! $inviter ) { 407 return; 408 } 409 echo esc_html( $inviter->user_registered ); 410 } 411 412 /** 413 * Display invitation date. 414 * 415 * @since 8.0.0 416 * 417 * @param BP_Invitation $invite BP_Invitation object. 418 */ 419 public function column_invitation_date_modified( $invite = null ) { 420 echo esc_html( $invite->date_modified ); 421 } 422 423 /** 424 * Display invitation date. 425 * 426 * @since 8.0.0 427 * 428 * @param BP_Invitation $invite BP_Invitation object. 429 */ 430 public function column_invitation_sent( $invite = null ) { 431 if ( $invite->invite_sent) { 432 esc_html_e( 'Yes', 'buddypress' ); 433 } else { 434 esc_html_e( 'No', 'buddypress' ); 435 } 436 } 437 438 /** 439 * Display invitation acceptance status. 440 * 441 * @since 8.0.0 442 * 443 * @param BP_Invitation $invite BP_Invitation object. 444 */ 445 public function column_invitation_accepted( $invite = null ) { 446 if ( $invite->accepted ) { 447 esc_html_e( 'Yes', 'buddypress' ); 448 } else { 449 esc_html_e( 'No', 'buddypress' ); 450 } 451 } 452 453 /** 454 * Allow plugins to add their custom column. 455 * 456 * @since 8.0.0 457 * 458 * @param BP_Invitation $invite BP_Invitation object. 459 * @param string $column_name The column name. 460 * @return string 461 */ 462 function column_default( $invite = null, $column_name = '' ) { 463 464 /** 465 * Filters the single site custom columns for plugins. 466 * 467 * @since 8.0.0 468 * 469 * @param string $column_name The column name. 470 * @param object $invite The BP_Invitation object.. 471 */ 472 return apply_filters( 'bp_members_invitations_management_custom_column', '', $column_name, $invite ); 473 } 474 } -
new file src/bp-members/classes/class-bp-members-invitations-template.php
diff --git src/bp-members/classes/class-bp-members-invitations-template.php src/bp-members/classes/class-bp-members-invitations-template.php new file mode 100644 index 000000000..1c5da5c42
- + 1 <?php 2 /** 3 * BuddyPress Members Invitation Template Loop Class. 4 * 5 * @package BuddyPress 6 * @subpackage TonificationsTemplate 7 * @since 8.0.0 8 */ 9 10 // Exit if accessed directly. 11 defined( 'ABSPATH' ) || exit; 12 13 /** 14 * The main membership invitations template loop class. 15 * 16 * Responsible for loading a group of membership invitations into a loop for display. 17 * 18 * @since 8.0.0 19 */ 20 class BP_Members_Invitations_Template { 21 22 /** 23 * The loop iterator. 24 * 25 * @since 8.0.0 26 * @var int 27 */ 28 public $current_invitation = -1; 29 30 /** 31 * The number of invitations returned by the paged query. 32 * 33 * @since 8.0.0 34 * @var int 35 */ 36 public $current_invitation_count; 37 38 /** 39 * Total number of invitations matching the query. 40 * 41 * @since 8.0.0 42 * @var int 43 */ 44 public $total_invitation_count; 45 46 /** 47 * Array of network invitations located by the query. 48 * 49 * @since 8.0.0 50 * @var array 51 */ 52 public $invitations; 53 54 /** 55 * The invitation object currently being iterated on. 56 * 57 * @since 8.0.0 58 * @var object 59 */ 60 public $invitation; 61 62 /** 63 * A flag for whether the loop is currently being iterated. 64 * 65 * @since 8.0.0 66 * @var bool 67 */ 68 public $in_the_loop; 69 70 /** 71 * The ID of the user to whom the displayed invitations were sent. 72 * 73 * @since 8.0.0 74 * @var int 75 */ 76 public $user_id; 77 78 /** 79 * The ID of the user to whom the displayed invitations belong. 80 * 81 * @since 8.0.0 82 * @var int 83 */ 84 public $inviter_id; 85 86 /** 87 * The page number being requested. 88 * 89 * @since 8.0.0 90 * @var int 91 */ 92 public $pag_page; 93 94 /** 95 * The $_GET argument used in URLs for determining pagination. 96 * 97 * @since 8.0.0 98 * @var int 99 */ 100 public $pag_arg; 101 102 /** 103 * The number of items to display per page of results. 104 * 105 * @since 8.0.0 106 * @var int 107 */ 108 public $pag_num; 109 110 /** 111 * An HTML string containing pagination links. 112 * 113 * @since 8.0.0 114 * @var string 115 */ 116 public $pag_links; 117 118 /** 119 * A string to match against. 120 * 121 * @since 8.0.0 122 * @var string 123 */ 124 public $search_terms; 125 126 /** 127 * A database column to order the results by. 128 * 129 * @since 8.0.0 130 * @var string 131 */ 132 public $order_by; 133 134 /** 135 * The direction to sort the results (ASC or DESC). 136 * 137 * @since 8.0.0 138 * @var string 139 */ 140 public $sort_order; 141 142 /** 143 * Array of variables used in this invitation query. 144 * 145 * @since 2.2.2 146 * @var array 147 */ 148 public $query_vars; 149 150 /** 151 * Constructor method. 152 * 153 * @see bp_has_members_invitations() For information on the array format. 154 * 155 * @since 8.0.0 156 * 157 * @param array $args { 158 * An array of arguments. See {@link bp_has_members_invitations()} 159 * for more details. 160 * } 161 */ 162 public function __construct( $args = array() ) { 163 164 // Parse arguments. 165 $r = wp_parse_args( $args, array( 166 'id' => false, 167 'user_id' => false, 168 'inviter_id' => false, 169 'invitee_email' => false, 170 'item_id' => false, 171 'type' => 'invite', 172 'invite_sent' => 'all', 173 'accepted' => 'all', 174 'search_terms' => '', 175 'order_by' => 'date_modified', 176 'sort_order' => 'DESC', 177 'page' => 1, 178 'per_page' => 25, 179 'fields' => 'all', 180 'page_arg' => 'ipage', 181 ) ); 182 183 // Sort order direction. 184 $orders = array( 'ASC', 'DESC' ); 185 if ( ! empty( $_GET['sort_order'] ) && in_array( $_GET['sort_order'], $orders ) ) { 186 $r['sort_order'] = $_GET['sort_order']; 187 } else { 188 $r['sort_order'] = in_array( $r['sort_order'], $orders ) ? $r['sort_order'] : 'DESC'; 189 } 190 191 // Setup variables. 192 $this->pag_arg = sanitize_key( $r['page_arg'] ); 193 $this->pag_page = bp_sanitize_pagination_arg( $this->pag_arg, $r['page'] ); 194 $this->pag_num = bp_sanitize_pagination_arg( 'num', $r['per_page'] ); 195 $this->user_id = $r['user_id']; 196 $this->search_terms = $r['search_terms']; 197 $this->order_by = $r['order_by']; 198 $this->sort_order = $r['sort_order']; 199 $this->query_vars = array( 200 'id' => $r['id'], 201 'user_id' => $r['user_id'], 202 'inviter_id' => $r['inviter_id'], 203 'invitee_email' => $r['invitee_email'], 204 'item_id' => $r['item_id'], 205 'type' => $r['type'], 206 'invite_sent' => $r['invite_sent'], 207 'accepted' => $r['accepted'], 208 'search_terms' => $this->search_terms, 209 'order_by' => $this->order_by, 210 'sort_order' => $this->sort_order, 211 'page' => $this->pag_page, 212 'per_page' => $this->pag_num, 213 ); 214 215 // Setup the invitations to loop through. 216 $invites_class = new BP_Members_Invitation_Manager(); 217 218 $this->invitations = $invites_class->get_invitations( $this->query_vars ); 219 $this->current_invitation_count = count( $this->invitations ); 220 $this->total_invitation_count = $invites_class->get_invitations_total_count( $this->query_vars ); 221 222 if ( (int) $this->total_invitation_count && (int) $this->pag_num ) { 223 $add_args = array( 224 'sort_order' => $this->sort_order, 225 ); 226 227 $this->pag_links = paginate_links( array( 228 'base' => add_query_arg( $this->pag_arg, '%#%' ), 229 'format' => '', 230 'total' => ceil( (int) $this->total_invitation_count / (int) $this->pag_num ), 231 'current' => $this->pag_page, 232 'prev_text' => _x( '←', 'Network invitation pagination previous text', 'buddypress' ), 233 'next_text' => _x( '→', 'Network invitation pagination next text', 'buddypress' ), 234 'mid_size' => 1, 235 'add_args' => $add_args, 236 ) ); 237 } 238 } 239 240 /** 241 * Whether there are invitations available in the loop. 242 * 243 * @since 8.0.0 244 * 245 * @see bp_has_members_invitations() 246 * 247 * @return bool True if there are items in the loop, otherwise false. 248 */ 249 public function has_invitations() { 250 if ( $this->current_invitation_count ) { 251 return true; 252 } 253 254 return false; 255 } 256 257 /** 258 * Set up the next invitation and iterate index. 259 * 260 * @since 8.0.0 261 * 262 * @return object The next invitation to iterate over. 263 */ 264 public function next_invitation() { 265 266 $this->current_invitation++; 267 268 $this->invitation = $this->invitations[ $this->current_invitation ]; 269 270 return $this->invitation; 271 } 272 273 /** 274 * Rewind the blogs and reset blog index. 275 * 276 * @since 8.0.0 277 */ 278 public function rewind_invitations() { 279 280 $this->current_invitation = -1; 281 282 if ( $this->current_invitation_count > 0 ) { 283 $this->invitation = $this->invitations[0]; 284 } 285 } 286 287 /** 288 * Whether there are invitations left in the loop to iterate over. 289 * 290 * This method is used by {@link bp_members_invitations()} as part of the 291 * while loop that controls iteration inside the invitations loop, eg: 292 * while ( bp_members_invitations() ) { ... 293 * 294 * @since 8.0.0 295 * 296 * @see bp_members_invitations() 297 * 298 * @return bool True if there are more invitations to show, 299 * otherwise false. 300 */ 301 public function invitations() { 302 303 if ( $this->current_invitation + 1 < $this->current_invitation_count ) { 304 return true; 305 306 } elseif ( $this->current_invitation + 1 === $this->current_invitation_count ) { 307 308 /** 309 * Fires right before the rewinding of invitation posts. 310 * 311 * @since 8.0.0 312 */ 313 do_action( 'members_invitations_loop_end'); 314 315 $this->rewind_invitations(); 316 } 317 318 $this->in_the_loop = false; 319 return false; 320 } 321 322 /** 323 * Set up the current invitation inside the loop. 324 * 325 * Used by {@link bp_the_invitation()} to set up the current 326 * invitation data while looping, so that template tags used during 327 * that iteration make reference to the current invitation. 328 * 329 * @since 8.0.0 330 * 331 * @see bp_the_invitation() 332 */ 333 public function the_invitation() { 334 $this->in_the_loop = true; 335 $this->invitation = $this->next_invitation(); 336 337 // Loop has just started. 338 if ( 0 === $this->current_invitation ) { 339 340 /** 341 * Fires if the current invitation item is the first in the invitation loop. 342 * 343 * @since 8.0.0 344 */ 345 do_action( 'members_invitations_loop_start' ); 346 } 347 } 348 } -
new file src/bp-members/screens/list-invites.php
diff --git src/bp-members/screens/list-invites.php src/bp-members/screens/list-invites.php new file mode 100644 index 000000000..8242dd279
- + 1 <?php 2 /** 3 * Members: Sent Invitations Status 4 * 5 * @package BuddyPress 6 * @subpackage MembersScreens 7 * @since 8.0.0 8 */ 9 10 /** 11 * Catch and process the Send Invites page. 12 * 13 * @since 8.0.0 14 */ 15 function members_screen_list_sent_invites() { 16 17 /** 18 * Fires before the loading of template for the send membership invitations page. 19 * 20 * @since 8.0.0 21 */ 22 do_action( 'members_screen_list_sent_invites' ); 23 24 /** 25 * Filters the template used to display the send membership invitations page. 26 * 27 * @since 8.0.0 28 * 29 * @param string $template Path to the send membership invitations template to load. 30 */ 31 bp_core_load_template( apply_filters( 'members_template_list_sent_invites', 'members/single/invitations' ) ); 32 } 33 34 /** 35 * Handle canceling or resending single invitations. 36 * 37 * @since 8.0.0 38 * 39 * @return bool 40 */ 41 function bp_members_invitations_action_handling() { 42 43 // Bail if not the read screen. 44 if ( ! bp_is_user_members_invitations_list() ) { 45 return false; 46 } 47 48 // Get the action. 49 $action = ! empty( $_GET['action'] ) ? $_GET['action'] : ''; 50 $nonce = ! empty( $_GET['_wpnonce'] ) ? $_GET['_wpnonce'] : ''; 51 $id = ! empty( $_GET['invitation_id'] ) ? $_GET['invitation_id'] : ''; 52 53 // Bail if no action or no ID. 54 if ( empty( $action ) || empty( $id ) ) { 55 return false; 56 } 57 58 if ( 'cancel' === $action ) { 59 // Check the nonce and delete the invitation. 60 if ( bp_verify_nonce_request( 'bp_members_invitations_cancel_' . $id ) && bp_members_invitations_delete_by_id( $id ) ) { 61 bp_core_add_message( __( 'Invitation successfully canceled.', 'buddypress' ) ); 62 } else { 63 bp_core_add_message( __( 'There was a problem canceling that invitation.', 'buddypress' ), 'error' ); 64 } 65 } else if ( 'resend' === $action ) { 66 // Check the nonce and resend the invitation. 67 if ( bp_verify_nonce_request( 'bp_network_invitation_resend_' . $id ) && bp_members_invitation_resend_by_id( $id ) ) { 68 bp_core_add_message( __( 'Invitation successfully resent.', 'buddypress' ) ); 69 } else { 70 bp_core_add_message( __( 'There was a problem resending that invitation.', 'buddypress' ), 'error' ); 71 } 72 } else { 73 return false; 74 } 75 76 // Redirect. 77 $user_id = bp_displayed_user_id(); 78 bp_core_redirect( bp_get_members_invitations_list_invites_permalink( $user_id ) ); 79 } 80 add_action( 'bp_actions', 'bp_members_invitations_action_handling' ); -
src/bp-members/screens/register.php
diff --git src/bp-members/screens/register.php src/bp-members/screens/register.php index 54b6facd5..b08f6ece8 100644
function bp_core_screen_signup() { 42 42 43 43 $bp->signup->step = 'request-details'; 44 44 45 if ( !bp_get_signup_allowed() ) { 46 $bp->signup->step = 'registration-disabled'; 45 // Could the user be accepting an invitation? 46 $active_invite = false; 47 if ( bp_get_members_invitations_allowed() ) { 48 // Check to see if there's a valid invitation. 49 $maybe_invite = bp_get_members_invitation_from_request(); 50 if ( $maybe_invite->id ) { 51 $active_invite = true; 52 } 53 } 47 54 55 if ( ! bp_get_signup_allowed() && ! $active_invite ) { 56 $bp->signup->step = 'registration-disabled'; 48 57 // If the signup page is submitted, validate and save. 49 58 } elseif ( isset( $_POST['signup_submit'] ) && bp_verify_nonce_request( 'bp_new_signup' ) ) { 50 59 -
new file src/bp-members/screens/send-invites.php
diff --git src/bp-members/screens/send-invites.php src/bp-members/screens/send-invites.php new file mode 100644 index 000000000..6471ebf1d
- + 1 <?php 2 /** 3 * Members: Send Invitations 4 * 5 * @package BuddyPress 6 * @subpackage MembersScreens 7 * @since 8.0.0 8 */ 9 10 /** 11 * Catch and process the Send Invites page. 12 * 13 * @since 8.0.0 14 */ 15 function members_screen_send_invites() { 16 17 /** 18 * Fires before the loading of template for the send membership invitations page. 19 * 20 * @since 8.0.0 21 */ 22 do_action( 'members_screen_send_invites' ); 23 24 /** 25 * Filters the template used to display the send membership invitations page. 26 * 27 * @since 8.0.0 28 * 29 * @param string $template Path to the send membership invitations template to load. 30 */ 31 bp_core_load_template( apply_filters( 'members_template_send_invites', 'members/single/invitations' ) ); 32 } 33 34 /** 35 * Handle sending invitations. 36 * 37 * @since 8.0.0 38 * 39 * @return bool 40 */ 41 function bp_network_invitations_catch_send_action() { 42 43 // Bail if not the read screen. 44 if ( ! bp_is_user_members_invitations_send_screen() ) { 45 return false; 46 } 47 48 // Get the action. 49 $action = ! empty( $_REQUEST['action'] ) ? $_REQUEST['action'] : ''; 50 $nonce = ! empty( $_REQUEST['_wpnonce'] ) ? $_REQUEST['_wpnonce'] : ''; 51 $email = ! empty( $_REQUEST['invitee_email'] ) ? $_REQUEST['invitee_email'] : ''; 52 $message = ! empty( $_REQUEST['invite_message'] ) ? $_REQUEST['invite_message'] : ''; 53 54 // Bail if missing required info. 55 if ( ( 'send-invite' !== $action ) ) { 56 return false; 57 } 58 59 $invite_args = array( 60 'invitee_email' => $email, 61 'inviter_id' => bp_displayed_user_id(), 62 'content' => $message, 63 'send_invite' => 1 64 ); 65 66 // Check the nonce and delete the invitation. 67 if ( bp_verify_nonce_request( 'bp_members_invitation_send_' . bp_displayed_user_id() ) && bp_members_invitations_invite_user( $invite_args ) ) { 68 bp_core_add_message( __( 'Invitation successfully sent!', 'buddypress' ) ); 69 } else { 70 bp_core_add_message( __( 'There was a problem sending that invitation.', 'buddypress' ), 'error' ); 71 } 72 73 // Redirect. 74 $user_id = bp_displayed_user_id(); 75 bp_core_redirect( bp_get_members_invitations_send_invites_permalink( $user_id ) ); 76 } 77 add_action( 'bp_actions', 'bp_network_invitations_catch_send_action' ); -
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 f4a3e1016..03c09ac00 100644
function bp_legacy_theme_group_manage_members_add_search() { 2014 2014 <?php 2015 2015 endif; 2016 2016 } 2017 2018 /** 2019 * Modify welcome message in Legacy template pack when 2020 * community invitations are enabled. 2021 * 2022 * @since 8.0.0 2023 * 2024 * @return string $message The message text. 2025 */ 2026 function bp_members_invitations_add_legacy_welcome_message() { 2027 $message = bp_members_invitations_get_registration_welcome_message(); 2028 if ( $message ) { 2029 echo '<p>' . esc_html( $message ) . '</p>'; 2030 } 2031 } 2032 add_action( 'bp_before_register_page', 'bp_members_invitations_add_legacy_welcome_message' ); 2033 2034 2035 /** 2036 * Modify "registration disabled" message in Legacy template pack when 2037 * community invitations are enabled. 2038 * 2039 * @since 8.0.0 2040 * 2041 * @return string $message The message text. 2042 */ 2043 function bp_members_invitations_add_legacy_registration_disabled_message() { 2044 $message = bp_members_invitations_get_modified_registration_disabled_message(); 2045 if ( $message ) { 2046 echo '<p>' . esc_html( $message ) . '</p>'; 2047 } 2048 } 2049 add_action( 'bp_after_registration_disabled', 'bp_members_invitations_add_legacy_registration_disabled_message' ); -
src/bp-templates/bp-legacy/buddypress/members/single/home.php
diff --git src/bp-templates/bp-legacy/buddypress/members/single/home.php src/bp-templates/bp-legacy/buddypress/members/single/home.php index f56af6e9c..bed9da1bf 100644
89 89 elseif ( bp_is_user_notifications() ) : 90 90 bp_get_template_part( 'members/single/notifications' ); 91 91 92 elseif ( bp_is_user_members_invitations() ) : 93 bp_get_template_part( 'members/single/invitations' ); 94 92 95 elseif ( bp_is_user_settings() ) : 93 96 bp_get_template_part( 'members/single/settings' ); 94 97 -
new file src/bp-templates/bp-legacy/buddypress/members/single/invitations.php
diff --git src/bp-templates/bp-legacy/buddypress/members/single/invitations.php src/bp-templates/bp-legacy/buddypress/members/single/invitations.php new file mode 100644 index 000000000..876a2e314
- + 1 <?php 2 /** 3 * BuddyPress - membership invitations 4 * 5 * @package BuddyPress 6 * @subpackage bp-legacy 7 * @version 8.0.0 8 */ 9 10 ?> 11 12 <div class="item-list-tabs no-ajax" id="subnav" aria-label="<?php esc_attr_e( 'Member secondary navigation', 'buddypress' ); ?>" role="navigation"> 13 <ul> 14 <?php bp_get_options_nav(); ?> 15 </ul> 16 </div> 17 18 <?php 19 switch ( bp_current_action() ) : 20 21 case 'send-invites' : 22 bp_get_template_part( 'members/single/invitations/send-invites' ); 23 break; 24 25 case 'list-invites' : 26 default : 27 bp_get_template_part( 'members/single/invitations/list-invites' ); 28 break; 29 30 endswitch; 31 -
new file src/bp-templates/bp-legacy/buddypress/members/single/invitations/invitations-loop.php
diff --git src/bp-templates/bp-legacy/buddypress/members/single/invitations/invitations-loop.php src/bp-templates/bp-legacy/buddypress/members/single/invitations/invitations-loop.php new file mode 100644 index 000000000..f73857cc8
- + 1 <?php 2 /** 3 * BuddyPress - Membership Invitations Loop 4 * 5 * @package BuddyPress 6 * @subpackage bp-legacy 7 * @version 8.0.0 8 */ 9 10 ?> 11 <form action="" method="post" id="invitations-bulk-management"> 12 <table class="invitations"> 13 <thead> 14 <tr> 15 <th class="icon"></th> 16 <th class="bulk-select-all"><input id="select-all-invitations" type="checkbox"> 17 <label class="bp-screen-reader-text" for="select-all-invitations"> 18 <?php 19 /* translators: accessibility text */ 20 esc_html_e( 'Select all', 'buddypress' ); 21 ?> 22 </label> 23 </th> 24 <th class="title"><?php esc_html_e( 'Invitee', 'buddypress' ); ?></th> 25 <th class="content"><?php esc_html_e( 'Message', 'buddypress' ); ?></th> 26 <th class="sent"><?php esc_html_e( 'Sent', 'buddypress' ); ?></th> 27 <th class="accepted"><?php esc_html_e( 'Accepted', 'buddypress' ); ?></th> 28 <th class="date"><?php esc_html_e( 'Date Modified', 'buddypress' ); ?></th> 29 <th class="actions"><?php esc_html_e( 'Actions', 'buddypress' ); ?></th> 30 </tr> 31 </thead> 32 33 <tbody> 34 35 <?php while ( bp_the_members_invitations() ) : bp_the_members_invitation(); ?> 36 37 <tr> 38 <td></td> 39 <td class="bulk-select-check"> 40 <label for="<?php bp_the_members_invitation_property( 'id', 'attribute' ); ?>"> 41 <input id="<?php bp_the_members_invitation_property( 'id', 'attribute' ); ?>" type="checkbox" name="network_invitations[]" value="<?php bp_the_members_invitation_property( 'id', 'attribute' ); ?>" class="invitation-check"> 42 <span class="bp-screen-reader-text"> 43 <?php 44 /* translators: accessibility text */ 45 esc_html_e( 'Select this invitation', 'buddypress' ); 46 ?> 47 </span> 48 </label> 49 </td> 50 <td class="invitation-invitee"><?php bp_the_members_invitation_property( 'invitee_email' ); ?></td> 51 <td class="invitation-content"><?php bp_the_members_invitation_property( 'content' ); ?></td> 52 <td class="invitation-sent"><?php bp_the_members_invitation_property( 'invite_sent' ); ?></td> 53 <td class="invitation-accepted"><?php bp_the_members_invitation_property( 'accepted' ); ?></td> 54 <td class="invitation-date-modified"><?php bp_the_members_invitation_property( 'date_modified' ); ?></td> 55 <td class="invitation-actions"><?php bp_the_members_invitation_action_links(); ?></td> 56 </tr> 57 58 <?php endwhile; ?> 59 60 </tbody> 61 </table> 62 63 <div class="invitations-options-nav"> 64 <?php // @TODO //bp_invitations_bulk_management_dropdown(); ?> 65 </div><!-- .invitations-options-nav --> 66 67 <?php wp_nonce_field( 'invitations_bulk_nonce', 'invitations_bulk_nonce' ); ?> 68 </form> -
new file src/bp-templates/bp-legacy/buddypress/members/single/invitations/list-invites.php
diff --git src/bp-templates/bp-legacy/buddypress/members/single/invitations/list-invites.php src/bp-templates/bp-legacy/buddypress/members/single/invitations/list-invites.php new file mode 100644 index 000000000..8e299f1d6
- + 1 <?php 2 /** 3 * BuddyPress - Sent Membership Invitations 4 * 5 * @package BuddyPress 6 * @subpackage bp-legacy 7 * @version 8.0.0 8 */ 9 ?> 10 11 <?php if ( bp_has_members_invitations() ) : ?> 12 13 <h2 class="bp-screen-reader-text"> 14 <?php 15 /* translators: accessibility text */ 16 esc_html_e( 'Invitations', 'buddypress' ); 17 ?> 18 </h2> 19 20 <div id="pag-top" class="pagination no-ajax"> 21 <div class="pag-count" id="invitations-count-top"> 22 <?php bp_members_invitations_pagination_count(); ?> 23 </div> 24 25 <div class="pagination-links" id="invitations-pag-top"> 26 <?php bp_members_invitations_pagination_links(); ?> 27 </div> 28 </div> 29 30 <?php bp_get_template_part( 'members/single/invitations/invitations-loop' ); ?> 31 32 <div id="pag-bottom" class="pagination no-ajax"> 33 <div class="pag-count" id="invitations-count-bottom"> 34 <?php bp_members_invitations_pagination_count(); ?> 35 </div> 36 37 <div class="pagination-links" id="invitations-pag-bottom"> 38 <?php bp_members_invitations_pagination_links(); ?> 39 </div> 40 </div> 41 42 <?php else : ?> 43 44 <p><?php esc_html_e( 'There are no invitations to display.', 'buddypress' ); ?></p> 45 46 <?php endif; -
new file src/bp-templates/bp-legacy/buddypress/members/single/invitations/send-invites.php
diff --git src/bp-templates/bp-legacy/buddypress/members/single/invitations/send-invites.php src/bp-templates/bp-legacy/buddypress/members/single/invitations/send-invites.php new file mode 100644 index 000000000..6eeb3b62f
- + 1 <?php 2 /** 3 * BuddyPress - Sent Membership Invitations 4 * 5 * @package BuddyPress 6 * @subpackage bp-legacy 7 * @version 8.0.0 8 */ 9 ?> 10 <h2 class="bp-screen-reader-text"> 11 <?php 12 /* translators: accessibility text */ 13 esc_html_e( 'Send Invitations', 'buddypress' ); 14 ?> 15 </h2> 16 17 <form class="standard-form members-invitation-form" id="members-invitation-form" method="post"> 18 <p class="description"><?php esc_html_e( 'Fill out the form below to invite a new user to join this site. Upon submission of the form, an email will be sent to the invitee containing a link to accept your invitation. You may also add a custom message to the email.', 'buddypress' ); ?></p> 19 20 <label for="bp_members_invitation_invitee_email"><?php esc_html_e( 'Email address of new user', 'buddypress' ); ?></label> 21 <input id="bp_members_invitation_invitee_email" type="email" name="invitee_email" required="required"> 22 23 <label for="bp_members_invitation_message"><?php esc_html_e( 'Add a personalized message to the invitation (optional)', 'buddypress' ); ?></label> 24 <textarea id="bp_members_invitation_message" name="invite_message"></textarea> 25 26 <input type="hidden" name="action" value="send-invite"> 27 28 <?php wp_nonce_field( 'bp_members_invitation_send_' . bp_displayed_user_id() ) ?> 29 <p> 30 <input id="submit" type="submit" name="submit" class="submit" value="<?php esc_attr_e( 'Send Invitation', 'buddypress' ) ?>" /> 31 </p> 32 </form> -
src/bp-templates/bp-nouveau/buddypress-functions.php
diff --git src/bp-templates/bp-nouveau/buddypress-functions.php src/bp-templates/bp-nouveau/buddypress-functions.php index 892bf2e33..f93134f74 100644
class BP_Nouveau extends BP_Theme_Compat { 195 195 // Set the BP Uri for the Ajax customizer preview. 196 196 add_filter( 'bp_uri', array( $this, 'customizer_set_uri' ), 10, 1 ); 197 197 198 // Modify "registration disabled" and welcome message if invitations are enabled. 199 add_action( 'bp_nouveau_feedback_messages', array( $this, 'filter_registration_messages' ), 99 ); 200 198 201 /** Override **********************************************************/ 199 202 200 203 /** … … class BP_Nouveau extends BP_Theme_Compat { 676 679 677 680 return $path; 678 681 } 682 /** 683 * Modify "registration disabled" message in Nouveau template pack. 684 * Modify welcome message in Nouveau template pack. 685 * 686 * @since 8.0.0 687 * 688 * @param array $messages The list of feedback messages. 689 * 690 * @return array $messages 691 */ 692 function filter_registration_messages( $messages ) { 693 // Change the "registration is disabled" message. 694 $disallowed_message = bp_members_invitations_get_modified_registration_disabled_message(); 695 if ( $disallowed_message ) { 696 $messages['registration-disabled']['message'] = $disallowed_message; 697 } 698 // Add information about invitations to the welcome block. 699 $welcome_message = bp_members_invitations_get_registration_welcome_message(); 700 if ( $welcome_message ) { 701 $messages['request-details']['message'] = $welcome_message . $messages['request-details']['message']; 702 } 703 return $messages; 704 } 679 705 } 680 706 681 707 /** -
new file src/bp-templates/bp-nouveau/buddypress/members/single/invitations.php
diff --git src/bp-templates/bp-nouveau/buddypress/members/single/invitations.php src/bp-templates/bp-nouveau/buddypress/members/single/invitations.php new file mode 100644 index 000000000..1fd36bab1
- + 1 <?php 2 /** 3 * BuddyPress - Membership invitations 4 * 5 * @since 8.0.0 6 * @version 8.0.0 7 */ 8 ?> 9 10 <nav class="<?php bp_nouveau_single_item_subnav_classes(); ?>" id="subnav" role="navigation" aria-label="<?php esc_attr_e( 'Groups menu', 'buddypress' ); ?>"> 11 <ul class="subnav"> 12 <?php bp_get_template_part( 'members/single/parts/item-subnav' ); ?> 13 </ul> 14 </nav><!-- .bp-navs --> 15 16 <?php 17 switch ( bp_current_action() ) : 18 19 case 'send-invites' : 20 bp_get_template_part( 'members/single/invitations/send-invites' ); 21 break; 22 23 case 'list-invites' : 24 default : 25 bp_get_template_part( 'members/single/invitations/list-invites' ); 26 break; 27 28 endswitch; 29 -
new file src/bp-templates/bp-nouveau/buddypress/members/single/invitations/invitations-loop.php
diff --git src/bp-templates/bp-nouveau/buddypress/members/single/invitations/invitations-loop.php src/bp-templates/bp-nouveau/buddypress/members/single/invitations/invitations-loop.php new file mode 100644 index 000000000..48576e8cf
- + 1 <?php 2 /** 3 * BuddyPress - Membership Invitations Loop 4 * 5 * @since 8.0.0 6 * @version 8.0.0 7 */ 8 ?> 9 <form action="" method="post" id="invitations-bulk-management"> 10 <table class="invitations"> 11 <thead> 12 <tr> 13 <th class="icon"></th> 14 <th class="bulk-select-all"><input id="select-all-invitations" type="checkbox"><label class="bp-screen-reader-text" for="select-all-invitations"><?php 15 /* translators: accessibility text */ 16 esc_html_e( 'Select all', 'buddypress' ); 17 ?></label></th> 18 <th class="title"><?php esc_html_e( 'Invitee', 'buddypress' ); ?></th> 19 <th class="content"><?php esc_html_e( 'Message', 'buddypress' ); ?></th> 20 <th class="sent"><?php esc_html_e( 'Sent', 'buddypress' ); ?></th> 21 <th class="accepted"><?php esc_html_e( 'Accepted', 'buddypress' ); ?></th> 22 <th class="date"><?php esc_html_e( 'Date Modified', 'buddypress' ); ?></th> 23 <th class="actions"><?php esc_html_e( 'Actions', 'buddypress' ); ?></th> 24 </tr> 25 </thead> 26 27 <tbody> 28 29 <?php while ( bp_the_members_invitations() ) : bp_the_members_invitation(); ?> 30 31 <tr> 32 <td></td> 33 <td class="bulk-select-check"> 34 <label for="<?php bp_the_members_invitation_property( 'id', 'attribute' ); ?>"> 35 <input id="<?php bp_the_members_invitation_property( 'id', 'attribute' ); ?>" type="checkbox" name="network_invitations[]" value="<?php bp_the_members_invitation_property( 'id', 'attribute' ); ?>" class="invitation-check"> 36 <span class="bp-screen-reader-text"> 37 <?php 38 /* translators: accessibility text */ 39 esc_html_e( 'Select this invitation', 'buddypress' ); 40 ?> 41 </span> 42 </label> 43 </td> 44 <td class="invitation-invitee"><?php bp_the_members_invitation_property( 'invitee_email' ); ?></td> 45 <td class="invitation-content"><?php bp_the_members_invitation_property( 'content' ); ?></td> 46 <td class="invitation-sent"><?php bp_the_members_invitation_property( 'invite_sent' ); ?></td> 47 <td class="invitation-accepted"><?php bp_the_members_invitation_property( 'accepted' ); ?></td> 48 <td class="invitation-date-modified"><?php bp_the_members_invitation_property( 'date_modified' ); ?></td> 49 <td class="invitation-actions"><?php bp_the_members_invitation_action_links(); ?></td> 50 </tr> 51 52 <?php endwhile; ?> 53 54 </tbody> 55 </table> 56 57 <div class="invitations-options-nav"> 58 <?php // @TODO //bp_invitations_bulk_management_dropdown(); ?> 59 </div><!-- .invitations-options-nav --> 60 61 <?php wp_nonce_field( 'invitations_bulk_nonce', 'invitations_bulk_nonce' ); ?> 62 </form> -
new file src/bp-templates/bp-nouveau/buddypress/members/single/invitations/list-invites.php
diff --git src/bp-templates/bp-nouveau/buddypress/members/single/invitations/list-invites.php src/bp-templates/bp-nouveau/buddypress/members/single/invitations/list-invites.php new file mode 100644 index 000000000..92d92879f
- + 1 <?php 2 /** 3 * BuddyPress - Pending Membership Invitations 4 * 5 * @since 8.0.0 6 * @version 8.0.0 7 */ 8 ?> 9 10 <?php if ( bp_has_members_invitations() ) : ?> 11 12 <h2 class="bp-screen-reader-text"> 13 <?php 14 /* translators: accessibility text */ 15 esc_html_e( 'Invitations', 'buddypress' ); 16 ?> 17 </h2> 18 19 <div id="pag-top" class="pagination no-ajax"> 20 <div class="pag-count" id="invitations-count-top"> 21 <?php bp_members_invitations_pagination_count(); ?> 22 </div> 23 24 <div class="pagination-links" id="invitations-pag-top"> 25 <?php bp_members_invitations_pagination_links(); ?> 26 </div> 27 </div> 28 29 <?php bp_get_template_part( 'members/single/invitations/invitations-loop' ); ?> 30 31 <div id="pag-bottom" class="pagination no-ajax"> 32 <div class="pag-count" id="invitations-count-bottom"> 33 <?php bp_members_invitations_pagination_count(); ?> 34 </div> 35 36 <div class="pagination-links" id="invitations-pag-bottom"> 37 <?php bp_members_invitations_pagination_links(); ?> 38 </div> 39 </div> 40 41 <?php else : ?> 42 43 <?php bp_nouveau_user_feedback( 'member-invites-none' ); ?> 44 45 <?php endif; -
new file src/bp-templates/bp-nouveau/buddypress/members/single/invitations/send-invites.php
diff --git src/bp-templates/bp-nouveau/buddypress/members/single/invitations/send-invites.php src/bp-templates/bp-nouveau/buddypress/members/single/invitations/send-invites.php new file mode 100644 index 000000000..077c1fa24
- + 1 <?php 2 /** 3 * BuddyPress - Send a Membership Invitation. 4 * 5 * @since 8.0.0 6 * @version 8.0.0 7 */ 8 ?> 9 <h2 class="bp-screen-reader-text"> 10 <?php 11 /* translators: accessibility text */ 12 esc_html_e( 'Send Invitation', 'buddypress' ); 13 ?> 14 </h2> 15 16 <p class="bp-feedback info"> 17 <span class="bp-icon" aria-hidden="true"></span> 18 <span class="bp-help-text"> 19 <?php esc_html_e( 'Fill out the form below to invite a new user to join this site. Upon submission of the form, an email will be sent to the invitee containing a link to accept your invitation. You may also add a custom message to the email.', 'buddypress' ); ?> 20 </span> 21 </p> 22 23 <form class="standard-form network-invitation-form" id="network-invitation-form" method="post"> 24 <label for="bp_members_invitation_invitee_email"> 25 <?php esc_html_e( 'Email', 'buddypress' ); ?> 26 <span class="bp-required-field-label"><?php esc_html_e( '(required)', 'buddypress' ); ?></span> 27 </label> 28 <input id="bp_members_invitation_invitee_email" type="email" name="invitee_email" required="required"> 29 30 <label for="bp_members_invitation_message"> 31 <?php esc_html_e( 'Add a personalized message to the invitation (optional)', 'buddypress' ); ?> 32 </label> 33 <textarea id="bp_members_invitation_message" name="invite_message"></textarea> 34 35 <input type="hidden" name="action" value="send-invite"> 36 37 <?php bp_nouveau_submit_button( 'member-send-invite' ); ?> 38 </form> -
src/bp-templates/bp-nouveau/includes/functions.php
diff --git src/bp-templates/bp-nouveau/includes/functions.php src/bp-templates/bp-nouveau/includes/functions.php index 69a72e110..6a7bc097b 100644
function bp_nouveau_theme_cover_image( $params = array() ) { 927 927 * All user feedback messages are available here 928 928 * 929 929 * @since 3.0.0 930 * @since 8.0.0 Adds the 'member-invites-none' feedback. 930 931 * 931 932 * @param string $feedback_id The ID of the message. 932 933 * … … function bp_nouveau_get_user_feedback( $feedback_id = '' ) { 939 940 * Use this filter to add your custom feedback messages. 940 941 * 941 942 * @since 3.0.0 943 * @since 8.0.0 Adds the 'member-invites-none' feedback. 942 944 * 943 945 * @param array $value The list of feedback messages. 944 946 */ 945 $feedback_messages = apply_filters( 'bp_nouveau_feedback_messages', array( 946 'registration-disabled' => array( 947 'type' => 'info', 948 'message' => __( 'Member registration is currently not allowed.', 'buddypress' ), 949 'before' => 'bp_before_registration_disabled', 950 'after' => 'bp_after_registration_disabled' 951 ), 952 'request-details' => array( 953 'type' => 'info', 954 'message' => __( 'Registering for this site is easy. Just fill in the fields below, and we\'ll get a new account set up for you in no time.', 'buddypress' ), 955 'before' => false, 956 'after' => false, 957 ), 958 'completed-confirmation' => array( 959 'type' => 'info', 960 'message' => __( 'You have successfully created your account! Please log in using the username and password you have just created.', 'buddypress' ), 961 'before' => 'bp_before_registration_confirmed', 962 'after' => 'bp_after_registration_confirmed', 963 ), 964 'directory-activity-loading' => array( 965 'type' => 'loading', 966 'message' => __( 'Loading the community updates. Please wait.', 'buddypress' ), 967 ), 968 'single-activity-loading' => array( 969 'type' => 'loading', 970 'message' => __( 'Loading the update. Please wait.', 'buddypress' ), 971 ), 972 'activity-loop-none' => array( 973 'type' => 'info', 974 'message' => __( 'Sorry, there was no activity found. Please try a different filter.', 'buddypress' ), 975 ), 976 'blogs-loop-none' => array( 977 'type' => 'info', 978 'message' => __( 'Sorry, there were no sites found.', 'buddypress' ), 979 ), 980 'blogs-no-signup' => array( 981 'type' => 'info', 982 'message' => __( 'Site registration is currently disabled.', 'buddypress' ), 983 ), 984 'directory-blogs-loading' => array( 985 'type' => 'loading', 986 'message' => __( 'Loading the sites of the network. Please wait.', 'buddypress' ), 987 ), 988 'directory-groups-loading' => array( 989 'type' => 'loading', 990 'message' => __( 'Loading the groups of the community. Please wait.', 'buddypress' ), 991 ), 992 'groups-loop-none' => array( 993 'type' => 'info', 994 'message' => __( 'Sorry, there were no groups found.', 'buddypress' ), 995 ), 996 'group-activity-loading' => array( 997 'type' => 'loading', 998 'message' => __( 'Loading the group updates. Please wait.', 'buddypress' ), 999 ), 1000 'group-members-loading' => array( 1001 'type' => 'loading', 1002 'message' => __( 'Requesting the group members. Please wait.', 'buddypress' ), 1003 ), 1004 'group-members-none' => array( 1005 'type' => 'info', 1006 'message' => __( 'Sorry, there were no group members found.', 'buddypress' ), 1007 ), 1008 'group-members-search-none' => array( 1009 'type' => 'info', 1010 'message' => __( 'Sorry, there was no member of that name found in this group.', 'buddypress' ), 1011 ), 1012 'group-manage-members-none' => array( 1013 'type' => 'info', 1014 'message' => __( 'This group has no members.', 'buddypress' ), 1015 ), 1016 'group-requests-none' => array( 1017 'type' => 'info', 1018 'message' => __( 'There are no pending membership requests.', 'buddypress' ), 1019 ), 1020 'group-requests-loading' => array( 1021 'type' => 'loading', 1022 'message' => __( 'Loading the members who requested to join the group. Please wait.', 'buddypress' ), 1023 ), 1024 'group-delete-warning' => array( 1025 'type' => 'warning', 1026 'message' => __( 'WARNING: Deleting this group will completely remove ALL content associated with it. There is no way back. Please be careful with this option.', 'buddypress' ), 1027 ), 1028 'group-avatar-delete-info' => array( 1029 'type' => 'info', 1030 'message' => __( 'If you\'d like to remove the existing group profile photo but not upload a new one, please use the delete group profile photo button.', 'buddypress' ), 1031 ), 1032 'directory-members-loading' => array( 1033 'type' => 'loading', 1034 'message' => __( 'Loading the members of your community. Please wait.', 'buddypress' ), 1035 ), 1036 'members-loop-none' => array( 1037 'type' => 'info', 1038 'message' => __( 'Sorry, no members were found.', 'buddypress' ), 1039 ), 1040 'member-requests-none' => array( 1041 'type' => 'info', 1042 'message' => __( 'You have no pending friendship requests.', 'buddypress' ), 1043 ), 1044 'member-invites-none' => array( 1045 'type' => 'info', 1046 'message' => __( 'You have no outstanding group invites.', 'buddypress' ), 1047 ), 1048 'member-notifications-none' => array( 1049 'type' => 'info', 1050 'message' => __( 'This member has no notifications.', 'buddypress' ), 1051 ), 1052 'member-wp-profile-none' => array( 1053 'type' => 'info', 1054 /* translators: %s: member name */ 1055 'message' => __( '%s did not save any profile information yet.', 'buddypress' ), 1056 ), 1057 'member-delete-account' => array( 1058 'type' => 'warning', 1059 'message' => __( 'Deleting this account will delete all of the content it has created. It will be completely unrecoverable.', 'buddypress' ), 1060 ), 1061 'member-activity-loading' => array( 1062 'type' => 'loading', 1063 'message' => __( 'Loading the member\'s updates. Please wait.', 'buddypress' ), 1064 ), 1065 'member-blogs-loading' => array( 1066 'type' => 'loading', 1067 'message' => __( 'Loading the member\'s blogs. Please wait.', 'buddypress' ), 1068 ), 1069 'member-friends-loading' => array( 1070 'type' => 'loading', 1071 'message' => __( 'Loading the member\'s friends. Please wait.', 'buddypress' ), 1072 ), 1073 'member-groups-loading' => array( 1074 'type' => 'loading', 1075 'message' => __( 'Loading the member\'s groups. Please wait.', 'buddypress' ), 1076 ), 1077 'member-notifications-loading' => array( 1078 'type' => 'loading', 1079 'message' => __( 'Loading notifications. Please wait.', 'buddypress' ), 1080 ), 1081 'member-group-invites-all' => array( 1082 'type' => 'info', 1083 'message' => __( 'Currently every member of the community can invite you to join their groups. If you are not comfortable with it, you can always restrict group invites to your friends only.', 'buddypress' ), 1084 ), 1085 'member-group-invites-friends-only' => array( 1086 'type' => 'info', 1087 'message' => __( 'Currently only your friends can invite you to groups. Uncheck the box to allow any member to send invites.', 'buddypress' ), 1088 ), 1089 ) ); 947 $feedback_messages = apply_filters( 948 'bp_nouveau_feedback_messages', 949 array( 950 'registration-disabled' => array( 951 'type' => 'info', 952 'message' => __( 'Member registration is currently not allowed.', 'buddypress' ), 953 'before' => 'bp_before_registration_disabled', 954 'after' => 'bp_after_registration_disabled' 955 ), 956 'request-details' => array( 957 'type' => 'info', 958 'message' => __( 'Registering for this site is easy. Just fill in the fields below, and we\'ll get a new account set up for you in no time.', 'buddypress' ), 959 'before' => false, 960 'after' => false, 961 ), 962 'completed-confirmation' => array( 963 'type' => 'info', 964 'message' => __( 'You have successfully created your account! Please log in using the username and password you have just created.', 'buddypress' ), 965 'before' => 'bp_before_registration_confirmed', 966 'after' => 'bp_after_registration_confirmed', 967 ), 968 'directory-activity-loading' => array( 969 'type' => 'loading', 970 'message' => __( 'Loading the community updates. Please wait.', 'buddypress' ), 971 ), 972 'single-activity-loading' => array( 973 'type' => 'loading', 974 'message' => __( 'Loading the update. Please wait.', 'buddypress' ), 975 ), 976 'activity-loop-none' => array( 977 'type' => 'info', 978 'message' => __( 'Sorry, there was no activity found. Please try a different filter.', 'buddypress' ), 979 ), 980 'blogs-loop-none' => array( 981 'type' => 'info', 982 'message' => __( 'Sorry, there were no sites found.', 'buddypress' ), 983 ), 984 'blogs-no-signup' => array( 985 'type' => 'info', 986 'message' => __( 'Site registration is currently disabled.', 'buddypress' ), 987 ), 988 'directory-blogs-loading' => array( 989 'type' => 'loading', 990 'message' => __( 'Loading the sites of the network. Please wait.', 'buddypress' ), 991 ), 992 'directory-groups-loading' => array( 993 'type' => 'loading', 994 'message' => __( 'Loading the groups of the community. Please wait.', 'buddypress' ), 995 ), 996 'groups-loop-none' => array( 997 'type' => 'info', 998 'message' => __( 'Sorry, there were no groups found.', 'buddypress' ), 999 ), 1000 'group-activity-loading' => array( 1001 'type' => 'loading', 1002 'message' => __( 'Loading the group updates. Please wait.', 'buddypress' ), 1003 ), 1004 'group-members-loading' => array( 1005 'type' => 'loading', 1006 'message' => __( 'Requesting the group members. Please wait.', 'buddypress' ), 1007 ), 1008 'group-members-none' => array( 1009 'type' => 'info', 1010 'message' => __( 'Sorry, there were no group members found.', 'buddypress' ), 1011 ), 1012 'group-members-search-none' => array( 1013 'type' => 'info', 1014 'message' => __( 'Sorry, there was no member of that name found in this group.', 'buddypress' ), 1015 ), 1016 'group-manage-members-none' => array( 1017 'type' => 'info', 1018 'message' => __( 'This group has no members.', 'buddypress' ), 1019 ), 1020 'group-requests-none' => array( 1021 'type' => 'info', 1022 'message' => __( 'There are no pending membership requests.', 'buddypress' ), 1023 ), 1024 'group-requests-loading' => array( 1025 'type' => 'loading', 1026 'message' => __( 'Loading the members who requested to join the group. Please wait.', 'buddypress' ), 1027 ), 1028 'group-delete-warning' => array( 1029 'type' => 'warning', 1030 'message' => __( 'WARNING: Deleting this group will completely remove ALL content associated with it. There is no way back. Please be careful with this option.', 'buddypress' ), 1031 ), 1032 'group-avatar-delete-info' => array( 1033 'type' => 'info', 1034 'message' => __( 'If you\'d like to remove the existing group profile photo but not upload a new one, please use the delete group profile photo button.', 'buddypress' ), 1035 ), 1036 'directory-members-loading' => array( 1037 'type' => 'loading', 1038 'message' => __( 'Loading the members of your community. Please wait.', 'buddypress' ), 1039 ), 1040 'members-loop-none' => array( 1041 'type' => 'info', 1042 'message' => __( 'Sorry, no members were found.', 'buddypress' ), 1043 ), 1044 'member-requests-none' => array( 1045 'type' => 'info', 1046 'message' => __( 'You have no pending friendship requests.', 'buddypress' ), 1047 ), 1048 'member-invites-none' => array( 1049 'type' => 'info', 1050 'message' => __( 'You have no outstanding group invites.', 'buddypress' ), 1051 ), 1052 'member-notifications-none' => array( 1053 'type' => 'info', 1054 'message' => __( 'This member has no notifications.', 'buddypress' ), 1055 ), 1056 'member-wp-profile-none' => array( 1057 'type' => 'info', 1058 /* translators: %s: member name */ 1059 'message' => __( '%s did not save any profile information yet.', 'buddypress' ), 1060 ), 1061 'member-delete-account' => array( 1062 'type' => 'warning', 1063 'message' => __( 'Deleting this account will delete all of the content it has created. It will be completely unrecoverable.', 'buddypress' ), 1064 ), 1065 'member-activity-loading' => array( 1066 'type' => 'loading', 1067 'message' => __( 'Loading the member\'s updates. Please wait.', 'buddypress' ), 1068 ), 1069 'member-blogs-loading' => array( 1070 'type' => 'loading', 1071 'message' => __( 'Loading the member\'s blogs. Please wait.', 'buddypress' ), 1072 ), 1073 'member-friends-loading' => array( 1074 'type' => 'loading', 1075 'message' => __( 'Loading the member\'s friends. Please wait.', 'buddypress' ), 1076 ), 1077 'member-groups-loading' => array( 1078 'type' => 'loading', 1079 'message' => __( 'Loading the member\'s groups. Please wait.', 'buddypress' ), 1080 ), 1081 'member-notifications-loading' => array( 1082 'type' => 'loading', 1083 'message' => __( 'Loading notifications. Please wait.', 'buddypress' ), 1084 ), 1085 'member-group-invites-all' => array( 1086 'type' => 'info', 1087 'message' => __( 'Currently every member of the community can invite you to join their groups. If you are not comfortable with it, you can always restrict group invites to your friends only.', 'buddypress' ), 1088 ), 1089 'member-group-invites-friends-only' => array( 1090 'type' => 'info', 1091 'message' => __( 'Currently only your friends can invite you to groups. Uncheck the box to allow any member to send invites.', 'buddypress' ), 1092 ), 1093 'member-invites-none' => array( 1094 'type' => 'info', 1095 'message' => __( 'There are no invitations to display.', 'buddypress' ), 1096 ), 1097 ) 1098 ); 1090 1099 1091 1100 if ( ! isset( $feedback_messages[ $feedback_id ] ) ) { 1092 1101 return false; … … function bp_nouveau_get_signup_fields( $section = '' ) { 1229 1238 * Get Some submit buttons data. 1230 1239 * 1231 1240 * @since 3.0.0 1241 * @since 8.0.0 Adds the 'member-send-invite' button. 1232 1242 * 1233 1243 * @param string $action The action requested. 1234 1244 * … … function bp_nouveau_get_submit_button( $action = '' ) { 1244 1254 * Filter the Submit buttons to add your own. 1245 1255 * 1246 1256 * @since 3.0.0 1257 * @since 8.0.0 Adds the 'member-send-invite' button. 1247 1258 * 1248 1259 * @param array $value The list of submit buttons. 1249 1260 * 1250 1261 * @return array|false 1251 1262 */ 1252 $actions = apply_filters( 'bp_nouveau_get_submit_button', array( 1253 'register' => array( 1254 'before' => 'bp_before_registration_submit_buttons', 1255 'after' => 'bp_after_registration_submit_buttons', 1256 'nonce' => 'bp_new_signup', 1257 'attributes' => array( 1258 'name' => 'signup_submit', 1259 'id' => 'submit', 1260 'value' => __( 'Complete Sign Up', 'buddypress' ), 1263 $actions = apply_filters( 1264 'bp_nouveau_get_submit_button', 1265 array( 1266 'register' => array( 1267 'before' => 'bp_before_registration_submit_buttons', 1268 'after' => 'bp_after_registration_submit_buttons', 1269 'nonce' => 'bp_new_signup', 1270 'attributes' => array( 1271 'name' => 'signup_submit', 1272 'id' => 'submit', 1273 'value' => __( 'Complete Sign Up', 'buddypress' ), 1274 ), 1261 1275 ), 1262 ),1263 'member-profile-edit' => array(1264 'before'=> '',1265 'after' => '',1266 'nonce' => 'bp_xprofile_edit',1267 'attributes' => array(1268 'name'=> 'profile-group-edit-submit',1269 'id' => 'profile-group-edit-submit',1270 'value' => __( 'Save Changes', 'buddypress'),1276 'member-profile-edit' => array( 1277 'before' => '', 1278 'after' => '', 1279 'nonce' => 'bp_xprofile_edit', 1280 'attributes' => array( 1281 'name' => 'profile-group-edit-submit', 1282 'id' => 'profile-group-edit-submit', 1283 'value' => __( 'Save Changes', 'buddypress' ), 1284 ), 1271 1285 ), 1272 ),1273 'member-capabilities' => array(1274 'before' => 'bp_members_capabilities_account_before_submit',1275 'after' => 'bp_members_capabilities_account_after_submit',1276 'nonce' => 'capabilities',1277 'attributes' => array(1278 'name'=> 'capabilities-submit',1279 'id' => 'capabilities-submit',1280 'value' => __( 'Save', 'buddypress'),1286 'member-capabilities' => array( 1287 'before' => 'bp_members_capabilities_account_before_submit', 1288 'after' => 'bp_members_capabilities_account_after_submit', 1289 'nonce' => 'capabilities', 1290 'attributes' => array( 1291 'name' => 'capabilities-submit', 1292 'id' => 'capabilities-submit', 1293 'value' => __( 'Save', 'buddypress' ), 1294 ), 1281 1295 ), 1282 ),1283 'member-delete-account' => array(1284 'before' => 'bp_members_delete_account_before_submit',1285 'after' => 'bp_members_delete_account_after_submit',1286 'nonce' => 'delete-account',1287 'attributes' => array(1288 'disabled' => 'disabled',1289 'name'=> 'delete-account-button',1290 'id' => 'delete-account-button',1291 'value' => __( 'Delete Account', 'buddypress'),1296 'member-delete-account' => array( 1297 'before' => 'bp_members_delete_account_before_submit', 1298 'after' => 'bp_members_delete_account_after_submit', 1299 'nonce' => 'delete-account', 1300 'attributes' => array( 1301 'disabled' => 'disabled', 1302 'name' => 'delete-account-button', 1303 'id' => 'delete-account-button', 1304 'value' => __( 'Delete Account', 'buddypress' ), 1305 ), 1292 1306 ), 1293 ),1294 'members-general-settings' => array(1295 'before' => 'bp_core_general_settings_before_submit',1296 'after' => 'bp_core_general_settings_after_submit',1297 'nonce' => 'bp_settings_general',1298 'attributes' => array(1299 'name'=> 'submit',1300 'id' => 'submit',1301 'value' => __( 'Save Changes', 'buddypress' ),1302 'class' => 'auto',1307 'members-general-settings' => array( 1308 'before' => 'bp_core_general_settings_before_submit', 1309 'after' => 'bp_core_general_settings_after_submit', 1310 'nonce' => 'bp_settings_general', 1311 'attributes' => array( 1312 'name' => 'submit', 1313 'id' => 'submit', 1314 'value' => __( 'Save Changes', 'buddypress' ), 1315 'class' => 'auto', 1316 ), 1303 1317 ), 1304 ),1305 'member-notifications-settings' => array(1306 'before' => 'bp_members_notification_settings_before_submit',1307 'after' => 'bp_members_notification_settings_after_submit',1308 'nonce' => 'bp_settings_notifications',1309 'attributes' => array(1310 'name'=> 'submit',1311 'id' => 'submit',1312 'value' => __( 'Save Changes', 'buddypress' ),1313 'class' => 'auto',1318 'member-notifications-settings' => array( 1319 'before' => 'bp_members_notification_settings_before_submit', 1320 'after' => 'bp_members_notification_settings_after_submit', 1321 'nonce' => 'bp_settings_notifications', 1322 'attributes' => array( 1323 'name' => 'submit', 1324 'id' => 'submit', 1325 'value' => __( 'Save Changes', 'buddypress' ), 1326 'class' => 'auto', 1327 ), 1314 1328 ), 1315 ),1316 'members-profile-settings' => array(1317 'before' => 'bp_core_xprofile_settings_before_submit',1318 'after' => 'bp_core_xprofile_settings_after_submit',1319 'nonce' => 'bp_xprofile_settings',1320 'attributes' => array(1321 'name' => 'xprofile-settings-submit',1322 'id' => 'submit',1323 'value' => __( 'Save Changes', 'buddypress' ),1324 'class' => 'auto',1329 'members-profile-settings' => array( 1330 'before' => 'bp_core_xprofile_settings_before_submit', 1331 'after' => 'bp_core_xprofile_settings_after_submit', 1332 'nonce' => 'bp_xprofile_settings', 1333 'attributes' => array( 1334 'name' => 'xprofile-settings-submit', 1335 'id' => 'submit', 1336 'value' => __( 'Save Changes', 'buddypress' ), 1337 'class' => 'auto', 1338 ), 1325 1339 ), 1326 ),1327 'member-group-invites' => array(1328 'nonce' => 'bp_nouveau_group_invites_settings',1329 'attributes' => array(1330 'name' => 'member-group-invites-submit',1331 'id' => 'submit',1332 'value' => __( 'Save', 'buddypress' ),1333 'class' => 'auto',1340 'member-group-invites' => array( 1341 'nonce' => 'bp_nouveau_group_invites_settings', 1342 'attributes' => array( 1343 'name' => 'member-group-invites-submit', 1344 'id' => 'submit', 1345 'value' => __( 'Save', 'buddypress' ), 1346 'class' => 'auto', 1347 ), 1334 1348 ), 1335 ),1336 'activity-new-comment' => array(1337 'after' => 'bp_activity_entry_comments',1338 'nonce' => 'new_activity_comment',1339 'nonce_key' => '_wpnonce_new_activity_comment',1340 'wrapper' => false,1341 'attributes' => array(1342 'name' => 'ac_form_submit',1343 'value' => _x( 'Post', 'button', 'buddypress'),1349 'member-send-invite' => array( 1350 'nonce' => 'bp_members_invitation_send_%d', 1351 'nonce_placeholder_value' => bp_displayed_user_id() ? bp_displayed_user_id() : bp_loggedin_user_id(), 1352 'attributes' => array( 1353 'name' => 'member-send-invite-submit', 1354 'id' => 'submit', 1355 'value' => __( 'Send', 'buddypress' ), 1356 'class' => 'auto', 1357 ), 1344 1358 ), 1345 ), 1346 ) ); 1359 'activity-new-comment' => array( 1360 'after' => 'bp_activity_entry_comments', 1361 'nonce' => 'new_activity_comment', 1362 'nonce_key' => '_wpnonce_new_activity_comment', 1363 'wrapper' => false, 1364 'attributes' => array( 1365 'name' => 'ac_form_submit', 1366 'value' => _x( 'Post', 'button', 'buddypress' ), 1367 ), 1368 ), 1369 ) 1370 ); 1347 1371 1348 1372 if ( isset( $actions[ $action ] ) ) { 1349 1373 return $actions[ $action ]; -
src/bp-templates/bp-nouveau/includes/members/template-tags.php
diff --git src/bp-templates/bp-nouveau/includes/members/template-tags.php src/bp-templates/bp-nouveau/includes/members/template-tags.php index b4fc3ae63..1c9385047 100644
function bp_nouveau_member_template_part() { 660 660 $template = 'profile'; 661 661 } elseif ( bp_is_user_notifications() ) { 662 662 $template = 'notifications'; 663 } elseif ( bp_is_user_members_invitations() ) { 664 $template = 'invitations'; 663 665 } elseif ( bp_is_user_settings() ) { 664 666 $template = 'settings'; 665 667 } -
src/bp-templates/bp-nouveau/includes/template-tags.php
diff --git src/bp-templates/bp-nouveau/includes/template-tags.php src/bp-templates/bp-nouveau/includes/template-tags.php index e195c22a5..c7bf7b702 100644
function bp_nouveau_submit_button( $action, $object_id = 0 ) { 2641 2641 printf( '<div class="submit">%s</div>', $submit_input ); 2642 2642 } 2643 2643 2644 $nonce = $submit_data['nonce']; 2645 if ( isset( $submit_data['nonce_placeholder_value'] ) ) { 2646 $nonce = sprintf( $nonce, $submit_data['nonce_placeholder_value'] ); 2647 } 2648 2644 2649 if ( empty( $submit_data['nonce_key'] ) ) { 2645 wp_nonce_field( $ submit_data['nonce']);2650 wp_nonce_field( $nonce ); 2646 2651 } else { 2647 2652 if ( $object_id ) { 2648 2653 $submit_data['nonce_key'] .= '_' . (int) $object_id; 2649 2654 } 2650 2655 2651 wp_nonce_field( $ submit_data['nonce'], $submit_data['nonce_key'] );2656 wp_nonce_field( $nonce, $submit_data['nonce_key'] ); 2652 2657 } 2653 2658 2654 2659 if ( ! empty( $submit_data['after'] ) ) { -
src/class-buddypress.php
diff --git src/class-buddypress.php src/class-buddypress.php index 1af41585b..789cc418a 100644
class BuddyPress { 622 622 'BP_REST_Attachments_Member_Avatar_Endpoint' => 'members', 623 623 'BP_REST_Attachments_Member_Cover_Endpoint' => 'members', 624 624 'BP_REST_Signup_Endpoint' => 'members', 625 'BP_Members_Invitation_Manager' => 'members', 626 'BP_Members_Invitations_Template' => 'members', 625 627 626 628 'BP_REST_Messages_Endpoint' => 'messages', 627 629