Skip to:
Content

BuddyPress.org

Ticket #8582: 8582.6-refreshed.patch

File 8582.6-refreshed.patch, 64.9 KB (added by imath, 3 years ago)
  • 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 023d2cea4..e2f4cffcc 100644
    function bp_admin_setting_callback_members_invitations() { 
    203203        do_action( 'bp_admin_settings_after_members_invitations' );
    204204}
    205205
     206/**
     207 * Allow new users to request membership to the network.
     208 *
     209 * @since 10.0.0
     210 */
     211function bp_admin_setting_callback_membership_requests() {
     212?>
     213        <input id="bp-enable-membership-requests" name="bp-enable-membership-requests" type="checkbox" value="1" <?php checked( bp_get_membership_requests_required( 'raw' ) ); ?> <?php if ( bp_get_signup_allowed() ) { echo 'disabled="disabled"'; } ?> />
     214        <label for="bp-enable-membership-requests"><?php esc_html_e( 'Allow visitors to request site membership. If enabled, an administrator must approve each new site membership request.', 'buddypress' ); ?></label>
     215        <?php if ( bp_get_signup_allowed() ) : ?>
     216                <p class="description"><?php esc_html_e( 'Public registration is currently enabled. If you wish to require approval for new memberships, disable public registration and enable the membership requests feature.', 'buddypress' ); ?></p>
     217        <?php endif; ?>
     218        <?php
     219        /**
     220         * Fires after the output of the membership requests settings section.
     221         *
     222         * @since 10.0.0
     223         */
     224        do_action( 'bp_admin_settings_after_membership_requests' );
     225}
     226
    206227/** XProfile ******************************************************************/
    207228
    208229/**
  • src/bp-core/bp-core-functions.php

    diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php
    index 0e66f4cb7..fd938861f 100644
    function bp_core_replace_tokens_in_text( $text, $tokens ) { 
    37923792 * Get a list of emails for populating the email post type.
    37933793 *
    37943794 * @since 2.5.1
     3795 * @since 10.0.0 Added members-membership-request and
     3796 *               members-membership-request-rejected email types.
    37953797 *
    37963798 * @return array
    37973799 */
    function bp_email_get_schema() { 
    39523954                        /* translators: do not remove {} brackets or translate its contents. */
    39533955                        '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' ),
    39543956                ),
     3957                'members-membership-request' => array(
     3958                        /* translators: do not remove {} brackets or translate its contents. */
     3959                        'post_title'   => __( '{{requesting-user.user_login}} would like to join {{site.name}}', 'buddypress' ),
     3960                        /* translators: do not remove {} brackets or translate its contents. */
     3961                        'post_content' => __( "{{requesting-user.user_login}} would like to join the site: &quot;{{site.name}}&quot;.\n\n<a href=\"{{{manage.url}}}\">Manage the request</a>.", 'buddypress' ),
     3962                        /* translators: do not remove {} brackets or translate its contents. */
     3963                        'post_excerpt' => __( "{{requesting-user.user_login}} would like to join the site \"{{site.name}}\".\n\nTo manage the request, visit: {{{manage.url}}}.", 'buddypress' ),
     3964                ),
     3965                'members-membership-request-rejected' => array(
     3966                        /* translators: do not remove {} brackets or translate its contents. */
     3967                        'post_title'   => __( 'Your request to join {{site.name}} has been declined', 'buddypress' ),
     3968                        /* translators: do not remove {} brackets or translate its contents. */
     3969                        'post_content' => __( "Sorry, your request to join the site &quot;{{site.name}}&quot; has been declined.", 'buddypress' ),
     3970                        /* translators: do not remove {} brackets or translate its contents. */
     3971                        'post_excerpt' => __( "Sorry, your request to join the site \"{{site.name}}\" has been declined.", 'buddypress' ),
     3972                ),
    39553973        ) );
    39563974}
    39573975
    function bp_email_get_type_schema( $field = 'description' ) { 
    41244142                ),
    41254143        );
    41264144
     4145        $members_membership_request= array(
     4146                'description'      => __( 'Someone has requested membership on this site.', 'buddypress' ),
     4147                'named_salutation' => true,
     4148                'unsubscribe'      => array(
     4149                        'meta_key' => 'notification_members_membership_request',
     4150                        'message'  => __( 'You will no longer receive emails when people submit requests to join this site.', 'buddypress' ),
     4151                ),
     4152        );
     4153
     4154        $members_membership_request_rejected= array(
     4155                'description'      => __( 'A site membership request has been rejected.', 'buddypress' ),
     4156                'named_salutation' => false,
     4157                'unsubscribe'      => false,
     4158        );
     4159
    41274160        $types = array(
    4128                 'activity-comment'                   => $activity_comment,
    4129                 'activity-comment-author'            => $activity_comment_author,
    4130                 'activity-at-message'                => $activity_at_message,
    4131                 'groups-at-message'                  => $groups_at_message,
    4132                 'core-user-registration'             => $core_user_registration,
    4133                 'core-user-registration-with-blog'   => $core_user_registration_with_blog,
    4134                 'friends-request'                    => $friends_request,
    4135                 'friends-request-accepted'           => $friends_request_accepted,
    4136                 'groups-details-updated'             => $groups_details_updated,
    4137                 'groups-invitation'                  => $groups_invitation,
    4138                 'groups-member-promoted'             => $groups_member_promoted,
    4139                 'groups-membership-request'          => $groups_membership_request,
    4140                 'messages-unread'                    => $messages_unread,
    4141                 'settings-verify-email-change'       => $settings_verify_email_change,
    4142                 'groups-membership-request-accepted' => $groups_membership_request_accepted,
    4143                 'groups-membership-request-rejected' => $groups_membership_request_rejected,
    4144                 'core-user-activation'               => $core_user_activation,
    4145                 'bp-members-invitation'              => $members_invitation,
     4161                'activity-comment'                    => $activity_comment,
     4162                'activity-comment-author'             => $activity_comment_author,
     4163                'activity-at-message'                 => $activity_at_message,
     4164                'groups-at-message'                   => $groups_at_message,
     4165                'core-user-registration'              => $core_user_registration,
     4166                'core-user-registration-with-blog'    => $core_user_registration_with_blog,
     4167                'friends-request'                     => $friends_request,
     4168                'friends-request-accepted'            => $friends_request_accepted,
     4169                'groups-details-updated'              => $groups_details_updated,
     4170                'groups-invitation'                   => $groups_invitation,
     4171                'groups-member-promoted'              => $groups_member_promoted,
     4172                'groups-membership-request'           => $groups_membership_request,
     4173                'messages-unread'                     => $messages_unread,
     4174                'settings-verify-email-change'        => $settings_verify_email_change,
     4175                'groups-membership-request-accepted'  => $groups_membership_request_accepted,
     4176                'groups-membership-request-rejected'  => $groups_membership_request_rejected,
     4177                'core-user-activation'                => $core_user_activation,
     4178                'bp-members-invitation'               => $members_invitation,
     4179                'members-membership-request'          => $members_membership_request,
     4180                'members-membership-request-rejected' => $members_membership_request_rejected,
    41464181        );
    41474182
    41484183        if ( $field !== 'all' ) {
  • src/bp-core/bp-core-template.php

    diff --git src/bp-core/bp-core-template.php src/bp-core/bp-core-template.php
    index a88cd6800..9ef914ed9 100644
    function bp_get_title_parts( $seplocation = 'right' ) { 
    31923192
    31933193        // Sign up page.
    31943194        } elseif ( bp_is_register_page() ) {
    3195                 $bp_title_parts = array( __( 'Create an Account', 'buddypress' ) );
     3195                if ( bp_get_membership_requests_required() ) {
     3196                        $bp_title_parts = array( __( 'Request Membership', 'buddypress' ) );
     3197                } else {
     3198                        $bp_title_parts = array( __( 'Create an Account', 'buddypress' ) );
     3199                }
    31963200
    31973201        // Activation page.
    31983202        } elseif ( bp_is_activation_page() ) {
  • src/bp-core/bp-core-update.php

    diff --git src/bp-core/bp-core-update.php src/bp-core/bp-core-update.php
    index 03710213c..6468ace39 100644
    function bp_version_updater() { 
    278278                if ( $raw_db_version < 12850 ) {
    279279                        bp_update_to_8_0();
    280280                }
     281
     282                // Version 10.0.0.
     283                if ( $raw_db_version < 13150 ) {
     284                        bp_update_to_10_0();
     285                }
     286
    281287        }
    282288
    283289        /* All done! *************************************************************/
    function bp_core_get_8_0_upgrade_email_schema( $emails ) { 
    704710        return $new_emails;
    705711}
    706712
     713/**
     714 * 10.0.0 update routine.
     715 *
     716 * - Install new BP Emails for membership requests.
     717 *
     718 * @since 10.0.0
     719 */
     720function bp_update_to_10_0() {
     721
     722        // Install membership request emails.
     723        add_filter( 'bp_email_get_schema', 'bp_core_get_10_0_upgrade_email_schema' );
     724
     725        bp_core_install_emails();
     726
     727        remove_filter( 'bp_email_get_schema', 'bp_core_get_10_0_upgrade_email_schema' );
     728}
     729
     730/**
     731 * Select only the emails that need to be installed with version 10.0.
     732 *
     733 * @since 10.0.0
     734 *
     735 * @param array $emails The array of emails schema.
     736 */
     737function bp_core_get_10_0_upgrade_email_schema( $emails ) {
     738        $new_emails = array();
     739
     740        if ( isset( $emails['members-membership-request'] ) ) {
     741                $new_emails['members-membership-request'] = $emails['members-membership-request'];
     742        }
     743
     744        if ( isset( $emails['members-membership-request-rejected'] ) ) {
     745                $new_emails['members-membership-request-rejected'] = $emails['members-membership-request-rejected'];
     746        }
     747
     748        return $new_emails;
     749}
     750
    707751/**
    708752 * Updates the component field for new_members type.
    709753 *
  • 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 9b7a87508..24d3678ee 100644
    class BP_Admin { 
    482482                        register_setting( 'buddypress', 'bp-enable-members-invitations', 'intval' );
    483483                }
    484484
     485                // Membership requests.
     486                if ( bp_is_active( 'members', 'membership_requests' ) ) {
     487                        add_settings_field( 'bp-enable-membership-requests', __( 'Membership Requests', 'buddypress' ), 'bp_admin_setting_callback_membership_requests', 'buddypress', 'bp_members' );
     488                        register_setting( 'buddypress', 'bp-enable-membership-requests', 'intval' );
     489                }
     490
    485491                /* XProfile Section **************************************************/
    486492
    487493                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 d92a76b7a..718384e7d 100644
    abstract class BP_Invitation_Manager { 
    227227         *         @type int    $item_id ID associated with the invitation and class.
    228228         *         @type int    $secondary_item_id secondary ID associated with the
    229229         *                              invitation and class.
    230          *         @type string $type @TODO. < missing description.
     230         *         @type string $type    Type of record this is: 'invite' or 'request'.
    231231         *         @type string $content Extra information provided by the requester
    232232         *                              or inviter.
    233233         *         @type string $date_modified Date the invitation was last modified.
  • src/bp-members/bp-members-functions.php

    diff --git src/bp-members/bp-members-functions.php src/bp-members/bp-members-functions.php
    index 93fd7cafd..141c545fa 100644
    function bp_core_signup_send_validation_email( $user_id, $user_email, $key, $sal 
    23882388        bp_send_email( 'core-user-registration', $to, $args );
    23892389
    23902390        // Record that the activation email has been sent.
    2391         $signups = BP_Signup::get(
    2392                 array(
    2393                         'activation_key' => $key,
    2394                 )
    2395         );
     2391        $signup = bp_members_get_signup_by( 'activation_key', $key );
    23962392
    2397         if ( ! empty( $signups['signups'] ) ) {
    2398                 foreach ( $signups['signups'] as $signup ) {
    2399                         $meta = array(
    2400                                 'sent_date'  => current_time( 'mysql', true ),
    2401                                 'count_sent' => $signup->count_sent + 1
    2402                         );
     2393        if ( $signup ) {
     2394                $meta = array(
     2395                        'sent_date'  => current_time( 'mysql', true ),
     2396                        'count_sent' => $signup->count_sent + 1
     2397                );
    24032398
    2404                         BP_Signup::update( array(
    2405                                 'signup_id' => $signup->id,
    2406                                 'meta'      => $meta,
    2407                         ) );
    2408                 }
     2399                BP_Signup::update( array(
     2400                        'signup_id' => $signup->id,
     2401                        'meta'      => $meta,
     2402                ) );
    24092403        }
    24102404}
    24112405
    function bp_core_signup_disable_inactive( $user = null, $username = '', $passwor 
    24502444        }
    24512445
    24522446        // Unactivated user account found!
    2453         // Set up the feedback message.
    2454         $signup_id = $signup['signups'][0]->signup_id;
     2447        /*
     2448         * Don't allow users to resend their own activation email
     2449         * when membership requests are enabled.
     2450         */
     2451        if ( bp_get_membership_requests_required() ) {
     2452                return new WP_Error( 'bp_account_not_activated', __( '<strong>Error</strong>: Your membership request has not yet been approved.', 'buddypress' ) );
     2453        } else {
     2454                // Set up the feedback message.
     2455                $signup_id = $signup['signups'][0]->signup_id;
    24552456
    2456         $resend_url_params = array(
    2457                 'action' => 'bp-resend-activation',
    2458                 'id'     => $signup_id,
    2459         );
     2457                $resend_url_params = array(
     2458                        'action' => 'bp-resend-activation',
     2459                        'id'     => $signup_id,
     2460                );
    24602461
    2461         $resend_url = wp_nonce_url(
    2462                 add_query_arg( $resend_url_params, wp_login_url() ),
    2463                 'bp-resend-activation'
    2464         );
     2462                $resend_url = wp_nonce_url(
     2463                        add_query_arg( $resend_url_params, wp_login_url() ),
     2464                        'bp-resend-activation'
     2465                );
    24652466
    2466         $resend_string = '<br /><br />';
     2467                $resend_string = '<br /><br />';
    24672468
    2468         /* translators: %s: the activation url */
    2469         $resend_string .= sprintf( __( 'If you have not received an email yet, <a href="%s">click here to resend it</a>.', 'buddypress' ), esc_url( $resend_url ) );
     2469                /* translators: %s: the activation url */
     2470                $resend_string .= sprintf( __( 'If you have not received an email yet, <a href="%s">click here to resend it</a>.', 'buddypress' ), esc_url( $resend_url ) );
    24702471
    2471         return new WP_Error( 'bp_account_not_activated', __( '<strong>Error</strong>: Your account has not been activated. Check your email for the activation link.', 'buddypress' ) . $resend_string );
     2472                return new WP_Error( 'bp_account_not_activated', __( '<strong>Error</strong>: Your account has not been activated. Check your email for the activation link.', 'buddypress' ) . $resend_string );
     2473        }
    24722474}
    24732475add_filter( 'authenticate', 'bp_core_signup_disable_inactive', 30, 3 );
    24742476
    function bp_get_members_invitation_from_request() { 
    36943696         */
    36953697        return apply_filters( 'bp_get_members_invitation_from_request', $invite );
    36963698}
     3699
     3700/**
     3701 * Get WP_User object corresponding to a record in the signups table.
     3702 *
     3703 * @since 10.0.0
     3704 *
     3705 * @param string $field Which fields to search by. Possible values are
     3706 *                      activation_key, user_email, id.
     3707 * @param string $value Value to search by.
     3708 * @return bool|BP_Signup $signup Found signup, returns first found
     3709 *                                if more than one is found.
     3710 */
     3711function bp_members_get_signup_by( $field = 'activation_key', $value ) {
     3712        switch ( $field ) {
     3713                case 'activation_key':
     3714                case 'user_email':
     3715                        $key = $field;
     3716                        break;
     3717
     3718                case 'id':
     3719                default:
     3720                        $key = 'include';
     3721                        break;
     3722        }
     3723
     3724        $signups = BP_Signup::get(
     3725                array(
     3726                        $key => $value,
     3727                )
     3728        );
     3729
     3730        if ( ! empty( $signups['signups'] ) ) {
     3731                $signup = current( $signups['signups'] );
     3732        } else {
     3733                $signup = false;
     3734        }
     3735
     3736        return $signup;
     3737}
  • src/bp-members/bp-members-invitations.php

    diff --git src/bp-members/bp-members-invitations.php src/bp-members/bp-members-invitations.php
    index 73f50e09b..7e95c791d 100644
    function bp_members_invitations_delete_optedout_invites( $optout ) { 
    183183        );
    184184}
    185185add_action( 'bp_optout_after_save', 'bp_members_invitations_delete_optedout_invites' );
     186
     187/**
     188 * If a user submits a site membership request, but there's a
     189 * sent invitation to her, bypass the manual approval of the request.
     190 *
     191 * @since 10.0.0
     192 *
     193 * @param bool  $send    Whether or not this membership request should be approved
     194 *                       immediately and the activation email sent.
     195 *                       Default is `false` meaning that the request should be
     196 *                       manually approved by a site admin.
     197 * @param array $details The details of the request.
     198 */
     199function bp_members_invitations_maybe_bypass_request_approval( $send, $details ) {
     200        if ( ! bp_get_members_invitations_allowed() ) {
     201                return $send;
     202        }
     203
     204        // We'll need the prospective user's email address.
     205        if ( empty( $details['user_email'] ) ) {
     206                return $send;
     207        }
     208
     209        $invites = bp_members_invitations_get_invites(
     210                array(
     211                        'invitee_email' => $details['user_email'],
     212                        'invite_sent'   => 'sent'
     213                )
     214        );
     215        // If pending invitations exist, send the verification mail.
     216        if ( $invites ) {
     217                $send = true;
     218        }
     219        return $send;
     220}
     221add_filter( 'bp_members_membership_requests_bypass_manual_approval', 'bp_members_invitations_maybe_bypass_request_approval', 10, 2 );
  • new file src/bp-members/bp-members-membership-requests.php

    diff --git src/bp-members/bp-members-membership-requests.php src/bp-members/bp-members-membership-requests.php
    new file mode 100644
    index 000000000..2f217db7b
    - +  
     1<?php
     2/**
     3 * BuddyPress Membership Requests
     4 *
     5 * @package BuddyPress
     6 * @subpackage MembersMembershipRequest
     7 * @since 10.0.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * When a user creates a membership request,
     15 * prevent the sending of the activation email so that
     16 * the site admins can send it manually.
     17 *
     18 * @since 10.0.0
     19 *
     20 * @param bool   $send           Whether or not to send the activation key.
     21 * @param int    $user_id        User ID to send activation key to.
     22 * @param string $user_email     User email to send activation key to.
     23 * @param string $activation_key Activation key to be sent.
     24 * @param array  $usermeta       Miscellaneous metadata about the user (blog-specific
     25 *                               signup data, xprofile data, etc).
     26 * @return bool Whether or not to send the activation key.
     27 */
     28function bp_members_membership_requests_cancel_activation_email( $send, $user_id = 0, $user_email = '', $activation_key = '', $usermeta = array() ) {
     29
     30        $details = array(
     31                'user_id'        => $user_id,
     32                'user_email'     => $user_email,
     33                'activation_key' => $activation_key,
     34                'usermeta'       => $usermeta,
     35        );
     36
     37        /**
     38         * Allow some membership requests to be approved immediately.
     39         * For example, you might want to approve all requests
     40         * coming from users with certain email address domains.
     41         * If `true` is returned the activation email will be sent to the user.
     42         *
     43         * @since 10.0.0
     44         *
     45         * @param bool  $send    Whether or not this membership request should be approved
     46         *                       immediately and the activation email sent.
     47         *                       Default is `false` meaning that the request should be
     48         *                       manually approved by a site admin.
     49         * @param array $details The details of the request.
     50         */
     51        $send = apply_filters( 'bp_members_membership_requests_bypass_manual_approval', false, $details );
     52
     53        // If the registration process has been interrupted, this is a new membership request.
     54        if ( ! $send ) {
     55                $signup = bp_members_get_signup_by( 'activation_key', $activation_key );
     56
     57                /**
     58                 * Fires when a site membership request has been created and is pending.
     59                 *
     60                 * @since 10.0.0
     61                 *
     62                 * @param BP_Signup $signup  The signup object that has been created.
     63                 * @param array     $details The details of the request.
     64                 */
     65                do_action( 'bp_members_membership_request_submitted', $signup, $details );
     66        }
     67
     68        return $send;
     69}
     70add_filter( 'bp_core_signup_send_activation_key', 'bp_members_membership_requests_cancel_activation_email', 10, 5 );
     71
     72
     73/**
     74 * Notifications
     75 *********************************************************************/
     76
     77/**
     78 * Notify site admins about a new membership request.
     79 *
     80 * @since 10.0.0
     81 *
     82 * @param BP_Signup $signup  The signup object that has been created.
     83 */
     84function bp_members_membership_requests_notify_site_admins( $signup ) {
     85
     86        // Notify all site admins so the request can be handled.
     87        $admins_query = new WP_User_Query( array(
     88                'role'   => 'administrator',
     89                'fields' => 'ids'
     90        ) );
     91        $admin_ids   = $admins_query->get_results();
     92
     93        foreach ( $admin_ids as $admin_id ) {
     94                // Trigger a BuddyPress Notification.
     95                if ( bp_is_active( 'notifications' ) ) {
     96                        bp_notifications_add_notification( array(
     97                                'user_id'           => $admin_id,
     98                                'item_id'           => $signup->signup_id,
     99                                'component_name'    => buddypress()->members->id,
     100                                'component_action'  => 'membership_request_submitted',
     101                                'date_notified'     => bp_core_current_time(),
     102                                'is_new'            => 1,
     103                        ) );
     104                }
     105
     106                // Bail if member opted out of receiving this email.
     107                if ( 'no' === bp_get_user_meta( $admin_id, 'notification_members_membership_request', true ) ) {
     108                        return;
     109                }
     110
     111                $unsubscribe_args = array(
     112                        'user_id'           => $admin_id,
     113                        'notification_type' => 'members-membership-request',
     114                );
     115                $manage_url = add_query_arg( array(
     116                        'mod_req'   => 1,
     117                        'page'      => 'bp-signups',
     118                        'signup_id' => $signup->signup_id,
     119                        'action'    => 'resend',
     120                ), bp_get_admin_url( 'users.php' ) );
     121                $args  = array(
     122                        'tokens' => array(
     123                                'admin.id'                   => $admin_id,
     124                                'manage.url'                 => esc_url_raw( $manage_url ),
     125                                'requesting-user.user_login' => esc_html( $signup->user_login ),
     126                                'unsubscribe'                => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ),
     127                        ),
     128                );
     129                bp_send_email( 'members-membership-request', (int) $admin_id, $args );
     130        }
     131
     132}
     133add_action( 'bp_members_membership_request_submitted', 'bp_members_membership_requests_notify_site_admins' );
     134
     135/**
     136 * Send a message to the requesting user when his or her
     137 * site membership request has been rejected.
     138 *
     139 * @since 10.0.0
     140 *
     141 * @param array $signup_ids Array of pending IDs to delete.
     142 */
     143function bp_members_membership_requests_send_rejection_mail( $signup_ids ) {
     144        $signups = BP_Signup::get(
     145                array(
     146                        'include' => $signup_ids,
     147                )
     148        );
     149        if ( empty( $signups['signups'] ) ) {
     150                return;
     151        }
     152        foreach ( $signups['signups'] as $signup ) {
     153                if ( ! empty( $signup->user_email ) ) {
     154                        bp_send_email( 'members-membership-request-rejected', $signup->user_email );
     155                }
     156        }
     157}
     158add_action( 'bp_core_signup_before_delete', 'bp_members_membership_requests_send_rejection_mail' );
     159
     160/**
     161 * When a request is approved, activated or deleted,
     162 * delete the associated notifications.
     163 *
     164 * @since 10.0.0
     165 *
     166 * @param array $signup_ids Array of changing signup IDs.
     167 */
     168function bp_members_membership_requests_delete_notifications_on_change( $signup_ids ) {
     169        foreach ( $signup_ids as $signup_id ) {
     170                BP_Notifications_Notification::delete(
     171                        array(
     172                                'item_id'          => $signup_id,
     173                                'component_action' => 'membership_request_submitted',
     174                        )
     175                );
     176        }
     177}
     178add_action( 'bp_core_signup_after_resend',   'bp_members_membership_requests_delete_notifications_on_change' );
     179add_action( 'bp_core_signup_after_activate', 'bp_members_membership_requests_delete_notifications_on_change' );
     180add_action( 'bp_core_signup_after_delete',   'bp_members_membership_requests_delete_notifications_on_change' );
     181
     182/**
     183 * In the Nouveau template pack, when membership requests are required,
     184 * change registration form submit button label to "Submit Request".
     185 *
     186 * @since 10.0.0
     187 *
     188 * @return string $retval the HTML for the request membership link.
     189 */
     190function bp_members_membership_requests_filter_complete_signup_button( $buttons ) {
     191
     192        $buttons['register']['attributes']['value'] = __( 'Submit Request', 'buddypress' );
     193        return $buttons;
     194}
     195add_filter( 'bp_nouveau_get_submit_button', 'bp_members_membership_requests_filter_complete_signup_button' );
     196
     197
     198/**
     199 * Administration: Change certain behavior and labels
     200 * on the WP Admin > Users > Manage Signups screen.
     201 *********************************************************************/
     202
     203/**
     204 * Filter the actions available on the signups list table.
     205 *
     206 * @since 10.0.0
     207 *
     208 * @param array  $actions       Array of actions and corresponding links.
     209 * @param object $signup_object The signup data object.
     210 */
     211function bp_members_membership_requests_filter_signup_row_actions( $actions, $signup_object ) {
     212
     213        // Rename the "email" resend option when membership requests are active.
     214        $email_link = add_query_arg(
     215                array(
     216                        'page'      => 'bp-signups',
     217                        'signup_id' => $signup_object->id,
     218                        'action'    => 'resend',
     219                ),
     220                bp_get_admin_url( 'users.php' )
     221        );
     222
     223        $resend_label = ( 0 === $signup_object->count_sent ) ? __( 'Approve Request', 'buddypress' ) : __( 'Resend Approval', 'buddypress' );
     224
     225        $actions['resend'] = sprintf( '<a href="%1$s">%2$s</a>', esc_url( $email_link ), $resend_label );
     226
     227        // Add a link to view profile info when membership requests and xprofile are active.
     228        if ( bp_is_active( 'xprofile' ) ) {
     229                $profile_link = add_query_arg(
     230                        array(
     231                                'page'     => 'bp-signups#TB_inline',
     232                                'inlineId' => 'signup-info-modal-' . $signup_object->id,
     233                        ),
     234                        bp_get_admin_url( 'users.php' )
     235                );
     236
     237                $actions['profile'] = sprintf( '<a href="%1$s" class="thickbox">%2$s</a>', esc_url( $profile_link ), __( 'Profile Info', 'buddypress' ) );
     238        }
     239
     240        return $actions;
     241}
     242add_filter( 'bp_members_ms_signup_row_actions', 'bp_members_membership_requests_filter_signup_row_actions', 10, 2 );
     243
     244/**
     245 * Filter the bulk actions available on the signups list table.
     246 *
     247 * @since 10.0.0
     248 *
     249 * @param array  $actions       Array of actions and corresponding links.
     250 */
     251function bp_members_membership_requests_filter_signup_bulk_actions( $actions ) {
     252        // Rename the "email" resend option when membership requests are active.
     253        $actions['resend'] = _x( 'Approve', 'Pending signup action', 'buddypress' );
     254        return $actions;
     255}
     256add_filter( 'bp_members_ms_signup_bulk_actions', 'bp_members_membership_requests_filter_signup_bulk_actions' );
     257
     258/**
     259 * Filter the "Last Sent" column header on the pending users table.
     260 *
     261 * @since 10.0.0
     262 *
     263* @param array $value Array of columns to display.
     264 */
     265function bp_members_membership_requests_filter_signup_table_date_sent_header( $columns ) {
     266        $columns['date_sent'] = __( 'Approved', 'buddypress' );
     267        return $columns;
     268}
     269add_filter( 'bp_members_signup_columns', 'bp_members_membership_requests_filter_signup_table_date_sent_header' );
     270add_filter( 'bp_members_ms_signup_columns', 'bp_members_membership_requests_filter_signup_table_date_sent_header' );
     271
     272/**
     273 * Filter the "Last Sent" column message on the pending users table.
     274 *
     275 * @since 10.0.0
     276 *
     277 * @param string      $message "Not yet sent" message.
     278 * @param object|null $signup  Signup object instance.
     279 */
     280function bp_members_membership_requests_filter_signup_table_unsent_message( $message, $signup ) {
     281        if ( 0 === $signup->count_sent ) {
     282                $message = __( 'Not yet approved', 'buddypress' );
     283        }
     284        return $message;
     285}
     286add_filter( 'bp_members_signup_date_sent_unsent_message', 'bp_members_membership_requests_filter_signup_table_unsent_message', 10, 2 );
     287add_filter( 'bp_members_ms_signup_date_sent_unsent_message', 'bp_members_membership_requests_filter_signup_table_unsent_message', 10, 2 );
     288
     289/**
     290 * Filter/add "Request Membership" links in the following locations:
     291 * BP login widget
     292 * sidebar register link
     293 * WP Toolbar
     294 * WP login form
     295 *********************************************************************/
     296
     297/**
     298 * Add "Request Membership" link to Widget login form.
     299 *
     300 * @since 10.0.0
     301 *
     302 * @return string $retval the HTML for the request membership link.
     303 */
     304function bp_members_membership_requests_add_link_to_widget_login_form() {
     305        ?>
     306        <span class="bp-login-widget-request-membership-link"><a href="<?php echo esc_url( bp_get_signup_page() ); ?>"><?php esc_html_e( 'Request Membership', 'buddypress' ); ?></a></span>
     307        <?php
     308}
     309add_action( 'bp_login_widget_form', 'bp_members_membership_requests_add_link_to_widget_login_form' );
     310
     311/**
     312 * Filter the "Register" link from `wp_register()` as used in
     313 * `sidebar.php` and the WP Core meta widget.
     314 *
     315 * @since 10.0.0
     316 *
     317 * @param string $link The HTML code for the link to the Registration or Admin page.
     318 */
     319function bp_members_membership_requests_filter_sidebar_register_link( $link ) {
     320        // $link should be an empty string when public registration is disabled.
     321        if ( ! is_user_logged_in() && empty( $link ) ) {
     322                // @TODO: How can we know what before and after tags should be?
     323                $link = '<li><a href="' . esc_url( wp_registration_url() ) . '">' . __( 'Request Membership' ) . '</a><li>';
     324        }
     325        return $link;
     326}
     327add_filter( 'register', 'bp_members_membership_requests_filter_sidebar_register_link' );
     328
     329/**
     330 * Add a "Request Membership" link to the WP Toolbar.
     331 * Priority 21 should place it just after the "Log In" link.
     332 *
     333 * @since 10.0.0
     334 *
     335 * @param WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance, passed by reference
     336 */
     337function bp_members_membership_requests_add_toolbar_link( $wp_admin_bar ) {
     338        if ( is_user_logged_in() ) {
     339                return;
     340        }
     341
     342        $args = array(
     343                'id'    => 'bp-request-membership',
     344                'title' => __( 'Request Membership' ),
     345                'href'  => wp_registration_url(),
     346                'meta'  => array(
     347                        'class' => 'buddypress-request-membership',
     348                        'title' => __( 'Request Membership' )
     349                ),
     350        );
     351        $wp_admin_bar->add_node( $args );
     352}
     353add_action( 'admin_bar_menu', 'bp_members_membership_requests_add_toolbar_link', 21 );
     354
     355/**
     356 * Add a "Request Membership" link to the WP Login form.
     357 *
     358 * @since 10.0.0
     359 *
     360 * @param string $link HTML link to the home URL of the current site.
     361 */
     362function bp_members_membership_requests_add_link_wp_login( $link ) {
     363        return $link . '&ensp;|&ensp;' . '<a href="' . esc_url( wp_registration_url() ) . '">' . __( 'Request Membership' ) . '</a>';
     364}
     365add_action( 'login_site_html_link', 'bp_members_membership_requests_add_link_wp_login' );
  • src/bp-members/bp-members-notifications.php

    diff --git src/bp-members/bp-members-notifications.php src/bp-members/bp-members-notifications.php
    index 93cee7b89..34c2677e9 100644
    function members_format_notifications( $action, $item_id, $secondary_item_id, $t 
    6161                                }
    6262                        }
    6363                        break;
     64
     65                case 'membership_request_submitted':
     66                        // $item_id is the id of the signup, not the user ID.
     67                        $signup = new BP_Signup( $item_id );
     68
     69                        // Set up the string and the filter.
     70                        if ( (int) $total_items > 1 ) {
     71                                $link   = bp_get_notifications_permalink();
     72                                $amount = 'multiple';
     73
     74                                $text = sprintf( __( '%d people have requested site membership.', 'buddypress' ), (int) $total_items );
     75                        } else {
     76                                $link   = add_query_arg( array(
     77                                        'mod_req'   => 1,
     78                                        'page'      => 'bp-signups',
     79                                        'signup_id' => $item_id,
     80                                        'action'    => 'resend',
     81                                ), bp_get_admin_url( 'users.php' ) );
     82                                $amount = 'single';
     83
     84                                /* translators: %s: new user name */
     85                                $text = sprintf( __( '%s has requested site membership.', 'buddypress' ),  esc_html( $signup->user_login ) );
     86                        }
     87                        break;
    6488        }
    6589
    6690        // Return either an HTML link or an array, depending on the requested format.
    function bp_members_mark_read_accepted_invitation_notification() { 
    167191                        'is_new' => false,
    168192                ),
    169193                array(
    170                         'user_id' => bp_loggedin_user_id(),
    171                         'item_id' => bp_displayed_user_id(),
     194                        'user_id'           => bp_loggedin_user_id(),
     195                        'item_id'           => bp_displayed_user_id(),
     196                        'component_action'  => 'accepted_invitation',
    172197                )
    173198        );
    174199}
    175200add_action( 'bp_screens', 'bp_members_mark_read_accepted_invitation_notification' );
    176201
     202/**
     203 * Mark new membership request notifications as read when user visits Manage BP Signups screen.
     204 *
     205 * @since 10.0.0
     206 */
     207function bp_members_mark_read_submitted_membership_request_notification() {
     208        if ( ! wp_doing_ajax() && 'users_page_bp-signups' === get_current_screen()->base && ! empty( $_GET['mod_req'] ) && ! empty( $_GET['signup_id'] ) ) {
     209                // Mark all notifications about this request as read.
     210                BP_Notifications_Notification::update(
     211                        array(
     212                                'is_new' => false,
     213                        ),
     214                        array(
     215                                'item_id'          => $_GET['signup_id'],
     216                                'component_action' => 'membership_request_submitted',
     217                        )
     218                );
     219        }
     220}
     221add_action( 'admin_footer', 'bp_members_mark_read_submitted_membership_request_notification' );
     222
    177223/**
    178224 * Add Members-related settings to the Settings > Notifications page.
    179225 *
    add_action( 'bp_screens', 'bp_members_mark_read_accepted_invitation_notification 
    181227 */
    182228function members_screen_notification_settings() {
    183229
    184         // Bail early if invitations are not allowed--they are the only members notification so far.
    185         if ( ! bp_get_members_invitations_allowed () ) {
     230        // Bail early if invitations and requests are not allowed--they are the only members notification so far.
     231        if ( ! bp_get_members_invitations_allowed() && ( ! bp_get_membership_requests_required() || ! user_can( bp_displayed_user_id(), 'bp_moderate' ) ) ) {
    186232                return;
    187233        }
    188 
    189         if ( ! $allow_acceptance_emails = bp_get_user_meta( bp_displayed_user_id(), 'notification_members_invitation_accepted', true ) ) {
    190                 $allow_acceptance_emails = 'yes';
    191         }
    192234        ?>
    193235
    194236        <table class="notification-settings" id="members-notification-settings">
    function members_screen_notification_settings() { 
    202244                </thead>
    203245
    204246                <tbody>
    205                         <tr id="members-notification-settings-invitation_accepted">
    206                                 <td></td>
    207                                 <td><?php _ex( 'Someone accepts your membership invitation', 'Member settings on notification settings page', 'buddypress' ) ?></td>
    208                                 <td class="yes"><input type="radio" name="notifications[notification_members_invitation_accepted]" id="notification-members-invitation-accepted-yes" value="yes" <?php checked( $allow_acceptance_emails, 'yes', true ) ?>/><label for="notification-members-invitation-accepted-yes" class="bp-screen-reader-text"><?php
    209                                         /* translators: accessibility text */
    210                                         _e( 'Yes, send email', 'buddypress' );
    211                                 ?></label></td>
    212                                 <td class="no"><input type="radio" name="notifications[notification_members_invitation_accepted]" id="notification-members-invitation-accepted-no" value="no" <?php checked( $allow_acceptance_emails, 'no', true ) ?>/><label for="notification-members-invitation-accepted-no" class="bp-screen-reader-text"><?php
    213                                         /* translators: accessibility text */
    214                                         _e( 'No, do not send email', 'buddypress' );
    215                                 ?></label></td>
    216                         </tr>
    217247
    218248                        <?php
     249                        if ( bp_get_members_invitations_allowed() ) :
     250                                if ( ! $allow_acceptance_emails = bp_get_user_meta( bp_displayed_user_id(), 'notification_members_invitation_accepted', true ) ) {
     251                                        $allow_acceptance_emails = 'yes';
     252                                }
     253                                ?>
     254                                <tr id="members-notification-settings-invitation_accepted">
     255                                        <td></td>
     256                                        <td><?php echo esc_html_x( 'Someone accepts your membership invitation', 'Member settings on notification settings page', 'buddypress' ); ?></td>
     257                                        <td class="yes"><input type="radio" name="notifications[notification_members_invitation_accepted]" id="notification-members-invitation-accepted-yes" value="yes" <?php checked( $allow_acceptance_emails, 'yes', true ) ?>/><label for="notification-members-invitation-accepted-yes" class="bp-screen-reader-text"><?php
     258                                                /* translators: accessibility text */
     259                                                esc_html_e( 'Yes, send email', 'buddypress' );
     260                                        ?></label></td>
     261                                        <td class="no"><input type="radio" name="notifications[notification_members_invitation_accepted]" id="notification-members-invitation-accepted-no" value="no" <?php checked( $allow_acceptance_emails, 'no', true ) ?>/><label for="notification-members-invitation-accepted-no" class="bp-screen-reader-text"><?php
     262                                                /* translators: accessibility text */
     263                                                esc_html_e( 'No, do not send email', 'buddypress' );
     264                                        ?></label></td>
     265                                </tr>
     266                                <?php
     267                        endif;
     268
     269                        if ( bp_get_membership_requests_required() && user_can( bp_displayed_user_id(), 'bp_moderate' ) ) :
     270                                if ( ! $allow_request_emails = bp_get_user_meta( bp_displayed_user_id(), 'notification_members_membership_request', true ) ) {
     271                                        $allow_request_emails = 'yes';
     272                                }
     273                                ?>
     274                                <tr id="members-notification-settings-submitted_membership_request">
     275                                        <td></td>
     276                                        <td><?php echo esc_html_x( 'Someone has requested site membership', 'Member settings on notification settings page', 'buddypress' ) ?></td>
     277                                        <td class="yes"><input type="radio" name="notifications[notification_members_membership_request]" id="notification-members-submitted_membership_request-yes" value="yes" <?php checked( $allow_request_emails, 'yes', true ) ?>/><label for="notification-members-submitted_membership_request-yes" class="bp-screen-reader-text"><?php
     278                                                /* translators: accessibility text */
     279                                                esc_html_e( 'Yes, send email', 'buddypress' );
     280                                        ?></label></td>
     281                                        <td class="no"><input type="radio" name="notifications[notification_members_membership_request]" id="notification-members-submitted_membership_request-no" value="no" <?php checked( $allow_request_emails, 'no', true ) ?>/><label for="notification-members-submitted_membership_request-no" class="bp-screen-reader-text"><?php
     282                                                /* translators: accessibility text */
     283                                                esc_html_e( 'No, do not send email', 'buddypress' );
     284                                        ?></label></td>
     285                                </tr>
     286                                <?php
     287                        endif;
    219288
    220289                        /**
    221290                         * Fires after the last table row on the members notification screen.
  • src/bp-members/bp-members-template.php

    diff --git src/bp-members/bp-members-template.php src/bp-members/bp-members-template.php
    index 10e6ef071..c9616ff9c 100644
    function bp_get_members_invitations_allowed() { 
    29212921        return apply_filters( 'bp_get_members_invitations_allowed', bp_is_active( 'members', 'invitations' ) && (bool) bp_get_option( 'bp-enable-members-invitations' ) );
    29222922}
    29232923
     2924/**
     2925 * Are membership requests required for joining this site?
     2926 *
     2927 * @since 10.0.0
     2928 *
     2929 * @param bool $context "raw" to fetch value from database,
     2930 *                      "site" to take "anyone can register" setting into account.
     2931 * @return bool
     2932 */
     2933function bp_get_membership_requests_required( $context = 'site' ) {
     2934        if ( 'raw' === $context ) {
     2935                $retval = bp_is_active( 'members', 'membership_requests' ) && (bool) bp_get_option( 'bp-enable-membership-requests' );
     2936        } else {
     2937                $retval = bp_is_active( 'members', 'membership_requests' ) && ! bp_get_signup_allowed() && (bool) bp_get_option( 'bp-enable-membership-requests' );
     2938        }
     2939
     2940        /**
     2941         * Filters whether or not prospective members may submit network membership requests.
     2942         *
     2943         * @since 10.0.0
     2944         *
     2945         * @param bool $retval Whether or not membership requests are required.
     2946         * @param bool $retval Whether this is the value stored in the database ('raw')
     2947         *                     or whether the site's "anyone can register" setting is
     2948         *                     being considered ('site' or anything else).
     2949         */
     2950        return apply_filters( 'bp_get_membership_requests_required', $retval, $context );
     2951}
     2952
    29242953/**
    29252954 * Should the system create and allow access
    29262955 * to the Register and Activate pages?
    function bp_get_members_invitations_allowed() { 
    29302959 * @return bool
    29312960 */
    29322961function bp_allow_access_to_registration_pages() {
    2933         $retval = bp_get_signup_allowed() || bp_get_members_invitations_allowed();
     2962        $retval = bp_get_signup_allowed() || bp_get_members_invitations_allowed() || bp_get_membership_requests_required();
    29342963
    29352964        /**
    29362965         * Filters whether or not the system should create and allow access
  • 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 979847a18..7c352d0c1 100644
    class BP_Members_Admin { 
    514514                // Only show sign-ups where they belong.
    515515                if ( ( ! bp_is_network_activated() && ! is_network_admin() ) || ( is_network_admin() && bp_is_network_activated() ) ) {
    516516
     517                        $signups_menu_label = __( 'Manage Signups',  'buddypress' );
     518
     519                        if ( bp_get_membership_requests_required() ) {
     520                                $signups_menu_label = __( 'Manage Pending Memberships',  'buddypress' );
     521                        }
     522
    517523                        // Manage signups.
    518524                        $hooks['signups'] = $this->signups_page = add_users_page(
    519                                 __( 'Manage Signups',  'buddypress' ),
    520                                 __( 'Manage Signups',  'buddypress' ),
     525                                $signups_menu_label,
     526                                $signups_menu_label,
    521527                                $this->capability,
    522528                                'bp-signups',
    523529                                array( $this, 'signups_admin' )
    class BP_Members_Admin { 
    17091715                                '<p>' . __( 'Using the search form, you can find pending accounts more easily. The Username and Email fields will be included in the search.', 'buddypress' ) . '</p>'
    17101716                        ) );
    17111717
     1718                        $signup_help_content = '<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>';
     1719
     1720                        if ( bp_get_membership_requests_required() ) {
     1721                                $signup_help_content .= '<ul><li>' . __( '"Activate" will activate the user immediately without requiring that they validate their email.', 'buddypress' ) .'</li>' .
     1722                                        '<li>' . __( '"Approve Request"/"Resend Apprival" takes you to the confirmation screen before being able to send the activation link to the desired pending request. You can only send the activation email once per day.', 'buddypress' ) . '</li>';
     1723
     1724                                if ( bp_is_active( 'xprofile' ) ) {
     1725                                        $signup_help_content .= '<li>' . __( '"Profile Info" will display extended profile information for the request.', 'buddypress' ) . '</li>';
     1726                                }
     1727
     1728                                $signup_help_content .= '<li>' . __( '"Delete" allows you to delete a pending account from your site. You will be asked to confirm this deletion.', 'buddypress' ) . '</li></ul>';
     1729                        } else {
     1730                                $signup_help_content .= '<ul><li>' . __( '"Email" takes you to the confirmation screen before being able to send the activation link to the desired pending account. You can only send the activation email once per day.', 'buddypress' ) . '</li>' .
     1731                                        '<li>' . __( '"Delete" allows you to delete a pending account from your site. You will be asked to confirm this deletion.', 'buddypress' ) . '</li></ul>';
     1732                        }
     1733
     1734                        $signup_help_content .= '<p>' . __( 'By clicking on a Username you will be able to activate a pending account from the confirmation screen.', 'buddypress' ) . '</p>' .
     1735                                '<p>' . __( 'Bulk actions allow you to perform these 3 actions for the selected rows.', 'buddypress' ) . '</p>';
     1736
    17121737                        get_current_screen()->add_help_tab( array(
    17131738                                'id'      => 'bp-signups-actions',
    17141739                                'title'   => __( 'Actions', 'buddypress' ),
    1715                                 'content' =>
    1716                                 '<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>' .
    1717                                 '<ul><li>' . __( '"Email" takes you to the confirmation screen before being able to send the activation link to the desired pending account. You can only send the activation email once per day.', 'buddypress' ) . '</li>' .
    1718                                 '<li>' . __( '"Delete" allows you to delete a pending account from your site. You will be asked to confirm this deletion.', 'buddypress' ) . '</li></ul>' .
    1719                                 '<p>' . __( 'By clicking on a Username you will be able to activate a pending account from the confirmation screen.', 'buddypress' ) . '</p>' .
    1720                                 '<p>' . __( 'Bulk actions allow you to perform these 3 actions for the selected rows.', 'buddypress' ) . '</p>'
     1740                                'content' => $signup_help_content
    17211741                        ) );
    17221742
    17231743                        // Help panel - sidebar links.
    class BP_Members_Admin { 
    22042224                ) );
    22052225
    22062226                $signups    = $signups_query['signups'];
    2207                 $signup_ids = wp_list_pluck( $signups, 'signup_id' );
     2227                $signup_ids = wp_list_pluck( $signups, 'id' );
    22082228
    22092229                // Set up strings.
    22102230                switch ( $action ) {
    class BP_Members_Admin { 
    22272247                                break;
    22282248
    22292249                        case 'resend' :
    2230                                 $header_text = __( 'Resend Activation Emails', 'buddypress' );
    2231                                 if ( 1 == count( $signup_ids ) ) {
    2232                                         $helper_text = __( 'You are about to resend an activation email to the following account:', 'buddypress' );
     2250
     2251                                if ( bp_get_membership_requests_required() ) {
     2252                                        $header_text = __( 'Approve Membership Requests', 'buddypress' );
     2253                                        if ( 1 === count( $signup_ids ) ) {
     2254                                                $helper_text = __( 'You are about to send an approval email to the following user:', 'buddypress' );
     2255                                        } else {
     2256                                                $helper_text = __( 'You are about to send approval emails to the following users:', 'buddypress' );
     2257                                        }
    22332258                                } else {
    2234                                         $helper_text = __( 'You are about to resend an activation email to the following accounts:', 'buddypress' );
     2259                                        $header_text = __( 'Resend Activation Emails', 'buddypress' );
     2260                                        if ( 1 === count( $signup_ids ) ) {
     2261                                                $helper_text = __( 'You are about to resend an activation email to the following account:', 'buddypress' );
     2262                                        } else {
     2263                                                $helper_text = __( 'You are about to resend an activation email to the following accounts:', 'buddypress' );
     2264                                        }
    22352265                                }
    22362266                                break;
     2267
    22372268                }
    22382269
    22392270                // These arguments are added to all URLs.
    class BP_Members_Admin { 
    22622293
    22632294                // Prefetch registration field data.
    22642295                $fdata = array();
    2265                 if ( 'activate' === $action && bp_is_active( 'xprofile' ) ) {
     2296                if ( bp_is_active( 'xprofile' ) && ( 'activate' == $action || ( 'resend' == $action && bp_get_membership_requests_required() ) ) ) {
    22662297                        $field_groups = bp_xprofile_get_groups( array(
    22672298                                'exclude_fields'    => 1,
    22682299                                'update_meta_cache' => false,
    class BP_Members_Admin { 
    22862317
    22872318                        <ol class="bp-signups-list">
    22882319                        <?php foreach ( $signups as $signup ) :
    2289                                 $last_notified = mysql2date( 'Y/m/d g:i:s a', $signup->date_sent );
     2320                                if ( $signup->count_sent > 0 ) {
     2321                                        $last_notified = mysql2date( 'Y/m/d g:i:s a', $signup->date_sent );
     2322                                } else {
     2323                                        $last_notified = __( 'Not yet notified', 'buddypress' );
     2324                                }
    22902325                                $profile_field_ids = array();
    22912326
    22922327                                // Get all xprofile field IDs except field 1.
    class BP_Members_Admin { 
    22982333                                <li>
    22992334                                        <strong><?php echo esc_html( $signup->user_login ) ?></strong>
    23002335
    2301                                         <?php if ( 'activate' == $action ) : ?>
     2336                                        <?php if ( 'activate' == $action || ( 'resend' == $action && bp_get_membership_requests_required() ) ) : ?>
    23022337                                                <table class="wp-list-table widefat fixed striped">
    23032338                                                        <tbody>
    23042339                                                                <tr>
  • 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 7bca5d8bb..135fb10ca 100644
    class BP_Members_Component extends BP_Component { 
    4040                        array(
    4141                                'adminbar_myaccount_order' => 20,
    4242                                'search_query_arg'         => 'members_search',
    43                                 'features'                 => array( 'invitations' )
     43                                'features'                 => array( 'invitations', 'membership_requests' )
    4444                        )
    4545                );
    4646        }
    class BP_Members_Component extends BP_Component { 
    7474                        $includes[] = 'activity';
    7575                }
    7676
     77                if ( bp_is_active( 'members', 'membership_requests' ) && (bool) bp_get_option( 'bp-enable-membership-requests' ) ) {
     78                        $includes[] = 'membership-requests';
     79                }
     80
    7781                // Include these only if in admin.
    7882                if ( is_admin() ) {
    7983                        $includes[] = 'admin';
  • src/bp-members/classes/class-bp-members-list-table.php

    diff --git src/bp-members/classes/class-bp-members-list-table.php src/bp-members/classes/class-bp-members-list-table.php
    index 8e7733b47..d9922b1fe 100644
    class BP_Members_List_Table extends WP_Users_List_Table { 
    113113
    114114                // Reset the screen id.
    115115                $this->screen->id = $reset_screen_id;
     116
     117                // Use thickbox to display the extended profile information.
     118                if ( bp_is_active( 'xprofile' ) ) {
     119                        add_thickbox();
     120                }
    116121        }
    117122
    118123        /**
    class BP_Members_List_Table extends WP_Users_List_Table { 
    138143         */
    139144        public function get_columns() {
    140145
    141                 /**
    142                  * Filters the single site Members signup columns.
    143                  *
    144                  * @since 2.0.0
    145                  *
    146                  * @param array $value Array of columns to display.
    147                  */
    148                 return apply_filters( 'bp_members_signup_columns', array(
     146                $columns = array(
    149147                        'cb'         => '<input type="checkbox" />',
    150148                        'username'   => __( 'Username',    'buddypress' ),
    151149                        'name'       => __( 'Name',        'buddypress' ),
    class BP_Members_List_Table extends WP_Users_List_Table { 
    153151                        'registered' => __( 'Registered',  'buddypress' ),
    154152                        'date_sent'  => __( 'Last Sent',   'buddypress' ),
    155153                        'count_sent' => __( 'Emails Sent', 'buddypress' )
    156                 ) );
     154                );
     155
     156                /**
     157                 * Filters the single site Members signup columns.
     158                 *
     159                 * @since 2.0.0
     160                 *
     161                 * @param array $value Array of columns to display.
     162                 */
     163                return apply_filters( 'bp_members_signup_columns', $columns );
    157164        }
    158165
    159166        /**
    class BP_Members_List_Table extends WP_Users_List_Table { 
    171178                        $actions['delete'] = __( 'Delete', 'buddypress' );
    172179                }
    173180
    174                 return $actions;
     181                /**
     182                 * Filters the bulk actions for signups.
     183                 *
     184                 * @since 10.0.0
     185                 *
     186                 * @param array $actions Array of actions and corresponding labels.
     187                 */
     188                return apply_filters( 'bp_members_ms_signup_bulk_actions', $actions );
    175189        }
    176190
    177191        /**
    class BP_Members_List_Table extends WP_Users_List_Table { 
    183197         */
    184198        public function no_items() {
    185199
    186                 if ( bp_get_signup_allowed() ) {
     200                if ( bp_get_signup_allowed() || bp_get_membership_requests_required() ) {
    187201                        esc_html_e( 'No pending accounts found.', 'buddypress' );
    188202                } else {
    189203                        $link = false;
    class BP_Members_List_Table extends WP_Users_List_Table { 
    342356         */
    343357        public function column_name( $signup_object = null ) {
    344358                echo esc_html( $signup_object->user_name );
     359
     360                // Insert the extended profile modal content required by thickbox.
     361                if ( ! bp_is_active( 'xprofile' ) ) {
     362                        return;
     363                }
     364
     365                $profile_field_ids = array();
     366
     367                // Prefetch registration field data.
     368                $fdata = array();
     369                $field_groups = bp_xprofile_get_groups( array(
     370                        'exclude_fields'    => 1,
     371                        'update_meta_cache' => false,
     372                        'fetch_fields'      => true,
     373                ) );
     374
     375                foreach( $field_groups as $fg ) {
     376                        foreach( $fg->fields as $f ) {
     377                                $fdata[ $f->id ] = $f->name;
     378                        }
     379                }
     380
     381                // Get all xprofile field IDs except field 1.
     382                if ( ! empty( $signup_object->meta['profile_field_ids'] ) ) {
     383                        $profile_field_ids = array_flip( explode( ',', $signup_object->meta['profile_field_ids'] ) );
     384                        unset( $profile_field_ids[1] );
     385                }
     386                ?>
     387                <div id="signup-info-modal-<?php echo $signup_object->id; ?>" style="display:none;">
     388                        <h1><?php printf( esc_html__( '%1$s (%2$s)', 'buddypress' ), esc_html( $signup_object->user_name ), esc_html( $signup_object->user_email ) ); ?></h1>
     389                        <h2><?php echo esc_html__( 'Extended Profile Information', 'buddypress' ); ?></h2>
     390
     391                        <table class="signup-profile-data-drawer wp-list-table widefat fixed striped">
     392                                <?php if ( 1 <= count( $profile_field_ids ) ): foreach ( $profile_field_ids as $pid => $noop ) :
     393                                        $field_value = isset( $signup_object->meta[ "field_{$pid}" ] ) ? $signup_object->meta[ "field_{$pid}" ] : ''; ?>
     394                                        <tr>
     395                                                <td class="column-fields"><?php echo esc_html( $fdata[ $pid ] ); ?></td>
     396                                                <td><?php echo $this->format_xprofile_field_for_display( $field_value ); ?></td>
     397                                        </tr>
     398                                <?php endforeach; else:  ?>
     399                                        <tr>
     400                                                <td><?php esc_html_e( 'There is no additional information to display.', 'buddypress' ); ?></td>
     401                                        </tr>
     402                                <?php endif; ?>
     403                        </table>
     404                </div>
     405                <?php
    345406        }
    346407
    347408        /**
    class BP_Members_List_Table extends WP_Users_List_Table { 
    374435         * @param object|null $signup_object The signup data object.
    375436         */
    376437        public function column_date_sent( $signup_object = null ) {
    377                 echo mysql2date( 'Y/m/d', $signup_object->date_sent );
     438                if ( $signup_object->count_sent > 0 ) {
     439                        echo mysql2date( 'Y/m/d', $signup_object->date_sent );
     440                } else {
     441                        $message = __( 'Not yet notified', 'buddypress' );
     442
     443                        /**
     444                         * Filters the "not yet sent" message for "Last Sent"
     445                         * column in Manage Signups list table.
     446                         *
     447                         * @since 10.0.0
     448                         *
     449                         * @param string      $message       "Not yet sent" message.
     450                         * @param object|null $signup_object Signup object instance.
     451                         */
     452                        $message = apply_filters( 'bp_members_signup_date_sent_unsent_message', $message, $signup_object );
     453
     454                        echo esc_html( $message );
     455                }
    378456        }
    379457
    380458        /**
    381          * Display number of time an activation email has been sent.
     459         * Display number of times an activation email has been sent.
    382460         *
    383461         * @since 2.0.0
    384462         *
    class BP_Members_List_Table extends WP_Users_List_Table { 
    409487                 */
    410488                return apply_filters( 'bp_members_signup_custom_column', '', $column_name, $signup_object );
    411489        }
     490
     491        /**
     492         * Formats a signup's xprofile field data for display.
     493         *
     494         * Operates recursively on arrays, which are then imploded with commas.
     495         *
     496         * @since 10.0.0
     497         * @see BP_Members_Admin::format_xprofile_field_for_display()
     498         *
     499         * @param string|array $value Field value.
     500         * @return string
     501         */
     502        protected function format_xprofile_field_for_display( $value ) {
     503                if ( is_array( $value ) ) {
     504                        $value = array_map( array( $this, 'format_xprofile_field_for_display' ), $value );
     505                        $value = implode( ', ', $value );
     506                } else {
     507                        $value = stripslashes( $value );
     508                        $value = esc_html( $value );
     509                }
     510
     511                return $value;
     512        }
    412513}
  • src/bp-members/classes/class-bp-members-ms-list-table.php

    diff --git src/bp-members/classes/class-bp-members-ms-list-table.php src/bp-members/classes/class-bp-members-ms-list-table.php
    index b8e86f906..662146c78 100644
    class BP_Members_MS_List_Table extends WP_MS_Users_List_Table { 
    114114
    115115                // Reset the screen id.
    116116                $this->screen->id = $reset_screen_id;
     117
     118                // Use thickbox to display the extended profile information.
     119                if ( bp_is_active( 'xprofile' ) ) {
     120                        add_thickbox();
     121                }
    117122        }
    118123
    119124        /**
    class BP_Members_MS_List_Table extends WP_MS_Users_List_Table { 
    125130         */
    126131        public function get_columns() {
    127132
    128                 /**
    129                  * Filters the multisite Members signup columns.
    130                  *
    131                  * @since 2.0.0
    132                  *
    133                  * @param array $value Array of columns to display.
    134                  */
    135                 return apply_filters( 'bp_members_ms_signup_columns', array(
     133                $columns = array(
    136134                        'cb'         => '<input type="checkbox" />',
    137135                        'username'   => __( 'Username',    'buddypress' ),
    138136                        'name'       => __( 'Name',        'buddypress' ),
    class BP_Members_MS_List_Table extends WP_MS_Users_List_Table { 
    140138                        'registered' => __( 'Registered',  'buddypress' ),
    141139                        'date_sent'  => __( 'Last Sent',   'buddypress' ),
    142140                        'count_sent' => __( 'Emails Sent', 'buddypress' )
    143                 ) );
     141                );
     142
     143                /**
     144                 * Filters the multisite Members signup columns.
     145                 *
     146                 * @since 2.0.0
     147                 *
     148                 * @param array $value Array of columns to display.
     149                 */
     150                return apply_filters( 'bp_members_ms_signup_columns', $columns );
    144151        }
    145152
    146153        /**
    class BP_Members_MS_List_Table extends WP_MS_Users_List_Table { 
    158165                        $actions['delete'] = __( 'Delete', 'buddypress' );
    159166                }
    160167
    161                 return $actions;
     168                /**
     169                 * Filters the bulk actions for signups.
     170                 *
     171                 * @since 10.0.0
     172                 *
     173                 * @param array $actions Array of actions and corresponding labels.
     174                 */
     175                return apply_filters( 'bp_members_ms_signup_bulk_actions', $actions );
    162176        }
    163177
    164178        /**
    class BP_Members_MS_List_Table extends WP_MS_Users_List_Table { 
    169183         * @since 2.0.0
    170184         */
    171185        public function no_items() {
    172                 if ( bp_get_signup_allowed() ) {
     186                if ( bp_get_signup_allowed() || bp_get_membership_requests_required() ) {
    173187                        esc_html_e( 'No pending accounts found.', 'buddypress' );
    174188                } else {
    175189                        $link = false;
    class BP_Members_MS_List_Table extends WP_MS_Users_List_Table { 
    328342         */
    329343        public function column_name( $signup_object = null ) {
    330344                echo esc_html( $signup_object->user_name );
     345
     346                // Insert the extended profile modal content required by thickbox.
     347                if ( ! bp_is_active( 'xprofile' ) ) {
     348                        return;
     349                }
     350
     351                $profile_field_ids = array();
     352
     353                // Prefetch registration field data.
     354                $fdata = array();
     355                $field_groups = bp_xprofile_get_groups( array(
     356                        'exclude_fields'    => 1,
     357                        'update_meta_cache' => false,
     358                        'fetch_fields'      => true,
     359                ) );
     360
     361                foreach( $field_groups as $fg ) {
     362                        foreach( $fg->fields as $f ) {
     363                                $fdata[ $f->id ] = $f->name;
     364                        }
     365                }
     366
     367                // Get all xprofile field IDs except field 1.
     368                if ( ! empty( $signup_object->meta['profile_field_ids'] ) ) {
     369                        $profile_field_ids = array_flip( explode( ',', $signup_object->meta['profile_field_ids'] ) );
     370                        unset( $profile_field_ids[1] );
     371                }
     372                ?>
     373                <div id="signup-info-modal-<?php echo $signup_object->id; ?>" style="display:none;">
     374                        <h1><?php printf( esc_html__( '%1$s (%2$s)', 'buddypress' ), esc_html( $signup_object->user_name ), esc_html( $signup_object->user_email ) ); ?></h1>
     375                        <h2><?php echo esc_html__( 'Extended Profile Information', 'buddypress' ); ?></h2>
     376
     377                        <table class="signup-profile-data-drawer wp-list-table widefat fixed striped">
     378                                <?php if ( 1 <= count( $profile_field_ids ) ): foreach ( $profile_field_ids as $pid => $noop ) :
     379                                        $field_value = isset( $signup_object->meta[ "field_{$pid}" ] ) ? $signup_object->meta[ "field_{$pid}" ] : ''; ?>
     380                                        <tr>
     381                                                <td class="column-fields"><?php echo esc_html( $fdata[ $pid ] ); ?></td>
     382                                                <td><?php echo $this->format_xprofile_field_for_display( $field_value ); ?></td>
     383                                        </tr>
     384                                <?php endforeach;else:  ?>
     385                                        <tr>
     386                                                <td><?php esc_html_e( 'There is no additional information to display.', 'buddypress' ); ?></td>
     387                                        </tr>
     388                                <?php endif; ?>
     389                        </table>
     390                </div>
     391                <?php
    331392        }
    332393
    333394        /**
    class BP_Members_MS_List_Table extends WP_MS_Users_List_Table { 
    376437                        $date = 'Y/m/d \<\b\r \/\> g:i:s a';
    377438                }
    378439
    379                 echo mysql2date( $date, $signup_object->date_sent );
     440                if ( $signup_object->count_sent > 0 ) {
     441                        echo mysql2date( $date, $signup_object->date_sent );
     442                } else {
     443                        $message = __( 'Not yet notified', 'buddypress' );
     444
     445                        /**
     446                         * Filters the "not yet sent" message for "Last Sent"
     447                         * column in Manage Signups list table.
     448                         *
     449                         * @since 10.0.0
     450                         *
     451                         * @param string      $message       "Not yet sent" message.
     452                         * @param object|null $signup_object Signup object instance.
     453                         */
     454                        $message = apply_filters( 'bp_members_ms_signup_date_sent_unsent_message', $message, $signup_object );
     455
     456                        echo esc_html( $message );
     457                }
    380458        }
    381459
    382460        /**
    class BP_Members_MS_List_Table extends WP_MS_Users_List_Table { 
    411489                 */
    412490                return apply_filters( 'bp_members_ms_signup_custom_column', '', $column_name, $signup_object );
    413491        }
     492
     493        /**
     494         * Formats a signup's xprofile field data for display.
     495         *
     496         * Operates recursively on arrays, which are then imploded with commas.
     497         *
     498         * @since 10.0.0
     499         * @see BP_Members_Admin::format_xprofile_field_for_display()
     500         *
     501         * @param string|array $value Field value.
     502         * @return string
     503         */
     504        protected function format_xprofile_field_for_display( $value ) {
     505                if ( is_array( $value ) ) {
     506                        $value = array_map( array( $this, 'format_xprofile_field_for_display' ), $value );
     507                        $value = implode( ', ', $value );
     508                } else {
     509                        $value = stripslashes( $value );
     510                        $value = esc_html( $value );
     511                }
     512
     513                return $value;
     514        }
    414515}
  • src/bp-members/classes/class-bp-registration-theme-compat.php

    diff --git src/bp-members/classes/class-bp-registration-theme-compat.php src/bp-members/classes/class-bp-registration-theme-compat.php
    index 6a942a58b..f4e3e6855 100644
    class BP_Registration_Theme_Compat { 
    9797        public function dummy_post() {
    9898                // Registration page.
    9999                if ( bp_is_register_page() ) {
    100                         $title = __( 'Create an Account', 'buddypress' );
     100                        if ( bp_get_membership_requests_required() ) {
     101                                $title = __( 'Request Membership', 'buddypress' );
     102                        } else {
     103                                $title = __( 'Create an Account', 'buddypress' );
     104                        }
    101105
    102106                        if ( 'completed-confirmation' == bp_get_current_signup_step() ) {
    103                                 $title = __( 'Check Your Email To Activate Your Account!', 'buddypress' );
     107                                if ( bp_get_membership_requests_required() ) {
     108                                        $title = __( 'Your Membership Request has been submitted.', 'buddypress' );
     109                                } else {
     110                                        $title = __( 'Check Your Email To Activate Your Account!', 'buddypress' );
     111                                }
    104112                        }
    105113
    106114                // Activation page.
  • src/bp-members/classes/class-bp-signup.php

    diff --git src/bp-members/classes/class-bp-signup.php src/bp-members/classes/class-bp-signup.php
    index 9de2af9fe..76b2022d0 100644
    class BP_Signup { 
    214214                        $this->date_sent = $signup->registered;
    215215                }
    216216
     217                // How many times has the activation email been sent?
     218                if ( isset( $this->meta['count_sent'] ) ) {
     219                        $this->count_sent = absint( $this->meta['count_sent'] );
     220                } else {
     221                        /**
     222                         * Meta will not be set if this is a pre-10.0 signup.
     223                         * In this case, we assume that the count is 1.
     224                         */
     225                        $this->count_sent = 1;
     226                }
     227
    217228                /**
    218229                 * Calculate a diff between now & last time
    219230                 * an activation link has been resent.
    class BP_Signup { 
    226237                 * Set a boolean to track whether an activation link
    227238                 * was sent in the last day.
    228239                 */
    229                 $this->recently_sent = ( $diff < 1 * DAY_IN_SECONDS );
     240                $this->recently_sent = $this->count_sent && ( $diff < 1 * DAY_IN_SECONDS );
    230241
    231                 // How many times has the activation email been sent?
    232                 if ( isset( $this->meta['count_sent'] ) ) {
    233                         $this->count_sent = absint( $this->meta['count_sent'] );
    234                 } else {
    235                         $this->count_sent = 0;
    236                 }
    237242        }
    238243
    239244        /** Static Methods *******************************************************/
  • src/bp-members/screens/register.php

    diff --git src/bp-members/screens/register.php src/bp-members/screens/register.php
    index 77929c442..40dd280dc 100644
    function bp_core_screen_signup() { 
    6161                }
    6262        }
    6363
    64         if ( ! bp_get_signup_allowed() && ! $active_invite ) {
     64        $requests_enabled = bp_get_membership_requests_required();
     65
     66        if ( ! bp_get_signup_allowed() && ! $active_invite && ! $requests_enabled ) {
    6567                $bp->signup->step = 'registration-disabled';
    6668                // If the signup page is submitted, validate and save.
    6769        } elseif ( isset( $_POST['signup_submit'] ) && bp_verify_nonce_request( 'bp_new_signup' ) ) {
  • src/bp-templates/bp-legacy/buddypress/members/register.php

    diff --git src/bp-templates/bp-legacy/buddypress/members/register.php src/bp-templates/bp-legacy/buddypress/members/register.php
    index d263470f2..dd6365b45 100644
     
    351351                         *
    352352                         * @since 1.1.0
    353353                         */
    354                         do_action( 'bp_before_registration_submit_buttons' ); ?>
     354                        do_action( 'bp_before_registration_submit_buttons' );
     355
     356                        if ( bp_get_membership_requests_required() ) {
     357                                $button_text = __( 'Submit Request', 'buddypress' );
     358                        } else {
     359                                $button_text = __( 'Complete Sign Up', 'buddypress' );
     360                        }
     361                        ?>
    355362
    356363                        <div class="submit">
    357                                 <input type="submit" name="signup_submit" id="signup_submit" value="<?php esc_attr_e( 'Complete Sign Up', 'buddypress' ); ?>" />
     364                                <input type="submit" name="signup_submit" id="signup_submit" value="<?php echo esc_attr( $button_text ); ?>" />
    358365                        </div>
    359366
    360367                        <?php
     
    390397                        do_action( 'bp_before_registration_confirmed' ); ?>
    391398
    392399                        <div id="template-notices" role="alert" aria-atomic="true">
    393                                 <?php if ( bp_registration_needs_activation() ) : ?>
     400                                <?php if ( bp_get_membership_requests_required() ) : ?>
     401                                        <p><?php _e( 'You have successfully submitted your membership request! Our site moderators will review your submission and send you an activation email if your request is approved.', 'buddypress' ); ?></p>
     402                                <?php elseif ( bp_registration_needs_activation() ) : ?>
    394403                                        <p><?php _e( 'You have successfully created your account! To begin using this site you will need to activate your account via the email we have just sent to your address.', 'buddypress' ); ?></p>
    395404                                <?php else : ?>
    396405                                        <p><?php _e( 'You have successfully created your account! Please log in using the username and password you have just created.', 'buddypress' ); ?></p>
  • 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 8f36ac097..3e6bb22b1 100644
    function bp_nouveau_get_user_feedback( $feedback_id = '' ) { 
    11221122        /*
    11231123         * Adjust some messages to the context.
    11241124         */
    1125         if ( 'completed-confirmation' === $feedback_id && bp_registration_needs_activation() ) {
     1125        if ( 'completed-confirmation' === $feedback_id && bp_get_membership_requests_required() ) {
     1126                $feedback_messages['completed-confirmation']['message'] = __( 'You have successfully submitted your membership request! Our site moderators will review your submission and send you an activation email if your request is approved.', 'buddypress' );
     1127        } elseif ( 'completed-confirmation' === $feedback_id && bp_registration_needs_activation() ) {
    11261128                $feedback_messages['completed-confirmation']['message'] = __( 'You have successfully created your account! To begin using this site you will need to activate your account via the email we have just sent to your address.', 'buddypress' );
    11271129        } elseif ( 'member-notifications-none' === $feedback_id ) {
    11281130                $is_myprofile = bp_is_my_profile();
  • src/class-buddypress.php

    diff --git src/class-buddypress.php src/class-buddypress.php
    index 981ae06a1..41be07434 100644
    class BuddyPress { 
    350350                /** Versions */
    351351
    352352                $this->version    = '10.0.0-alpha';
    353                 $this->db_version = 12850;
     353                $this->db_version = 13150;
    354354
    355355                /** Loading */
    356356