diff --git a/.github/workflows/label-sync.yml b/.github/workflows/label-sync.yml new file mode 100644 index 0000000..67cfbaf --- /dev/null +++ b/.github/workflows/label-sync.yml @@ -0,0 +1,23 @@ +name: Sync labels +on: + # You can run this with every type of event, but it's better to run it only when you actually need it. + workflow_dispatch: + +jobs: + labels: + runs-on: ubuntu-latest + + steps: + - uses: strangerstudios/label-sync@v2 + with: + # If you want to use a source repo, you can put is name here (only the owner/repo format is accepted) + source-repo: strangerstudios/paid-memberships-pro + + # If you want to delete any additional label, set this to true + delete-other-labels: true + + #If you want the action just to show you the preview of the changes, without actually editing the labels, set this to tru + dry-run: false + + # You can change the token used to change the labels, this is the default one + token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/adminpages/approvals.php b/adminpages/approvals.php index 4f66aae..e05636d 100644 --- a/adminpages/approvals.php +++ b/adminpages/approvals.php @@ -34,17 +34,23 @@ //Approve, deny or reset member back to pending if ( ! empty( $_REQUEST['approve'] ) ) { check_admin_referer( 'pmpro_approvals', 'pmpro_approvals_nonce' ); - if ( ! PMPro_Approvals::isApproved( intval( $_REQUEST['approve'] ) ) ) { + if ( ! PMPro_Approvals::isApproved( intval( $_REQUEST['approve'] ), $l ) ) { PMPro_Approvals::approveMember( intval( $_REQUEST['approve'] ), $l ); + $l = false; + $status = 'pending'; } } elseif ( ! empty( $_REQUEST['deny'] ) ) { check_admin_referer( 'pmpro_approvals', 'pmpro_approvals_nonce' ); - if ( ! PMPro_Approvals::isDenied( intval( $_REQUEST['deny'] ) ) ) { + if ( ! PMPro_Approvals::isDenied( intval( $_REQUEST['deny'] ), $l ) ) { PMPro_Approvals::denyMember( intval( $_REQUEST['deny'] ), $l ); + $l = false; + $status = 'pending'; } } elseif ( ! empty( $_REQUEST['unapprove'] ) ) { check_admin_referer( 'pmpro_approvals', 'pmpro_approvals_nonce' ); PMPro_Approvals::resetMember( intval( $_REQUEST['unapprove'] ), $l ); + $l = false; + $status = 'pending'; } require_once PMPRO_DIR . '/adminpages/admin_header.php'; @@ -137,16 +143,17 @@ $limit = 15; } - $theusers = PMPro_Approvals::getApprovals( $l, $s, $status, $sortby, $sortorder, $pn, $limit ); + $approval_users = PMPro_Approvals::getApprovals( $l, $s, $status, $sortby, $sortorder, $pn, $limit ); $totalrows = $wpdb->get_var( 'SELECT FOUND_ROWS() as found_rows' ); - if ( $theusers ) { + if ( $approval_users ) { ?>

- - . + + . +

- + ID ); - $theuser->membership_level = pmpro_getMembershipLevelForUser( $theuser->ID ); + $user_data = get_userdata( $approval_user->ID ); ?> class="alternate"> - ID; ?> + ID; ?> - ID, 32 ); ?> + ID, 32 ); ?> - user_login; ?> + user_login; ?> - user_login; ?> + user_login; ?>
> } ?> - first_name . ' ' . $theuser->last_name ); ?> - user_email; ?> - + first_name . ' ' . $user_data->last_name ); ?> + user_email; ?> + membership; + echo $approval_user->membership; ?> ID ) || PMPro_Approvals::isDenied( $theuser->ID ) ) { + if ( PMPro_Approvals::isApproved( $user_data->ID, $approval_user->membership_id) || PMPro_Approvals::isDenied( $user_data->ID, $approval_user->membership_id ) ) { - if ( ! PMPro_Approvals::getEmailConfirmation( $theuser->ID ) ) { + if ( ! PMPro_Approvals::getEmailConfirmation( $user_data->ID ) ) { _e( 'Email Confirmation Required.', 'pmpro-approvals' ); } else { - echo PMPro_Approvals::getUserApprovalStatus( $theuser->ID, $theuser->membership_level->id, false ); + echo PMPro_Approvals::getUserApprovalStatus( $user_data->ID, $approval_user->membership_id, false ); //link to unapprove ?> - [X] + [X] - | - + | + - user_registered ) ); ?> + user_registered ) ); ?>

diff --git a/adminpages/userinfo.php b/adminpages/userinfo.php index 3d6108c..d57e383 100644 --- a/adminpages/userinfo.php +++ b/adminpages/userinfo.php @@ -9,7 +9,13 @@ if ( isset( $_REQUEST['l'] ) ) { $l = intval( $_REQUEST['l'] ); } else { - $l = false; + // Default to a random level that the user has. Hopefully we never actually do this. + $levels = pmpro_getMembershipLevelsForUser( $current_user->ID ); + if ( ! empty( $levels ) ) { + $l = $levels[0]->id; + } else { + $l = 0; + } } if ( ! empty( $_REQUEST['approve'] ) ) { @@ -59,7 +65,7 @@ ID ); + $level_details = pmpro_getSpecificMembershipLevelForUser( $user->ID, $l ); echo esc_html( $level_details->name ); @@ -71,20 +77,20 @@ ID ) || PMPro_Approvals::isDenied( $user->ID ) ) { + if ( PMPro_Approvals::isApproved( $user->ID, $l ) || PMPro_Approvals::isDenied( $user->ID, $l ) ) { if ( ! PMPro_Approvals::getEmailConfirmation( $user->ID ) ) { _e( 'Email Confirmation Required.', 'pmpro-approvals' ); } else { - echo PMPro_Approvals::getUserApprovalStatus( $user->ID, null, false ); + echo PMPro_Approvals::getUserApprovalStatus( $user->ID, $l, false ); ?> - [X] + [X] - Approve | - Deny + | + diff --git a/classes/class.approvalemails.php b/classes/class.approvalemails.php index 485c927..c5ab8e3 100644 --- a/classes/class.approvalemails.php +++ b/classes/class.approvalemails.php @@ -20,8 +20,9 @@ public static function get_instance() { * Send user's an email that their account has been approved. * * @param $member. The member's ID or object. + * @param int $level_id */ - public function sendMemberApproved( $member ) { + public function sendMemberApproved( $member, $level_id = null ) { if ( empty( $member ) ) { return; @@ -29,7 +30,12 @@ public function sendMemberApproved( $member ) { $member = get_user_by( 'ID', $member ); } - $level = pmpro_getMembershipLevelForUser( $member->ID ); + if ( empty( $level_id ) ) { + $level = pmpro_getMembershipLevelForUser( $member->ID ); + } else { + $level = pmpro_getSpecificMembershipLevelForUser( $member->ID, $level_id ); + } + $this->email = $member->user_email; $this->subject = sprintf( __( 'Your membership at %s has been approved.', 'pmpro-approvals' ), get_bloginfo( 'name' ) ); @@ -58,8 +64,9 @@ public function sendMemberApproved( $member ) { * Send user's an email that their account has been denied. * * @param $member. The member's ID or object. + * @param int $level_id */ - public function sendMemberDenied( $member ) { + public function sendMemberDenied( $member, $level_id = null ) { if ( empty( $member ) ) { return; @@ -67,7 +74,11 @@ public function sendMemberDenied( $member ) { $member = get_user_by( 'ID', $member ); } - $level = pmpro_getMembershipLevelForUser( $member->ID ); + if ( empty( $level_id ) ) { + $level = pmpro_getMembershipLevelForUser( $member->ID ); + } else { + $level = pmpro_getSpecificMembershipLevelForUser( $member->ID, $level_id ); + } $this->email = $member->user_email; $this->subject = sprintf( __( 'Your membership at %s has been denied.', 'pmpro-approvals' ), get_bloginfo( 'name' ) ); @@ -98,8 +109,9 @@ public function sendMemberDenied( $member ) { * * @param $member The member object/ID/email. * @param $admin The admin object/ID. Default $current_user object. + * @param int $level_id */ - public function sendAdminPending( $member = null, $admin = null ) { + public function sendAdminPending( $member = null, $admin = null, $level_id = null ) { if ( empty( $admin ) ) { $admin = get_user_by( 'email', get_option( 'admin_email' ) ); @@ -130,13 +142,17 @@ public function sendAdminPending( $member = null, $admin = null ) { $member = get_user_by( 'email', $member ); } - $level = pmpro_getMembershipLevelForUser( $member->ID ); + if ( empty( $level_id ) ) { + $level = pmpro_getMembershipLevelForUser( $member->ID ); + } else { + $level = pmpro_getSpecificMembershipLevelForUser( $member->ID, $level_id ); + } $this->data['member_name'] = $member->display_name; $this->data['member_email'] = $member->user_email; $this->data['membership_id'] = $level->id; $this->data['membership_level_name'] = $level->name; - $this->data['view_profile'] = admin_url( 'admin.php?page=pmpro-approvals&user_id=' . $member->ID ); + $this->data['view_profile'] = admin_url( 'admin.php?page=pmpro-approvals&user_id=' . $member->ID . '&l=' . $level->id ); $this->data['approve_link'] = $this->data['view_profile'] . '&approve=' . $member->ID; $this->data['deny_link'] = $this->data['view_profile'] . '&deny=' . $member->ID; } @@ -151,8 +167,9 @@ public function sendAdminPending( $member = null, $admin = null ) { * * @param $member The member object/ID/email. * @param $admin The admin object/ID. Default $current_user object. + * @param int $level_id */ - public function sendAdminApproval( $member = null, $admin = null ) { + public function sendAdminApproval( $member = null, $admin = null, $level_id = null ) { if ( empty( $admin ) ) { $admin = get_user_by( 'email', get_option( 'admin_email' ) ); @@ -184,13 +201,17 @@ public function sendAdminApproval( $member = null, $admin = null ) { $member = get_user_by( 'email', $member ); } - $level = pmpro_getMembershipLevelForUser( $member->ID ); + if ( empty( $level_id ) ) { + $level = pmpro_getMembershipLevelForUser( $member->ID ); + } else { + $level = pmpro_getSpecificMembershipLevelForUser( $member->ID, $level_id ); + } $this->data['membership_id'] = $level->id; $this->data['membership_level_name'] = $level->name; $this->data['member_email'] = $member->user_email; $this->data['member_name'] = $member->display_name; - $this->data['view_profile'] = admin_url( 'admin.php?page=pmpro-approvals&user_id=' . $member->ID ); + $this->data['view_profile'] = admin_url( 'admin.php?page=pmpro-approvals&user_id=' . $member->ID . '&l=' . $level->id ); } $this->data = apply_filters( 'pmpro_approvals_admin_approved_email_data', $this->data, $member, $admin ); @@ -203,8 +224,9 @@ public function sendAdminApproval( $member = null, $admin = null ) { * * @param $member The member object/ID/email. * @param $admin The admin object/ID. Default $current_user object. + * @param int $level_id */ - public function sendAdminDenied( $member = null, $admin = null ) { + public function sendAdminDenied( $member = null, $admin = null, $level_id = null ) { if ( empty( $admin ) ) { $admin = get_user_by( 'email', get_option( 'admin_email' ) ); @@ -236,13 +258,17 @@ public function sendAdminDenied( $member = null, $admin = null ) { $member = get_user_by( 'email', $member ); } - $level = pmpro_getMembershipLevelForUser( $member->ID ); + if ( empty( $level_id ) ) { + $level = pmpro_getMembershipLevelForUser( $member->ID ); + } else { + $level = pmpro_getSpecificMembershipLevelForUser( $member->ID, $level_id ); + } $this->data['membership_id'] = $level->id; $this->data['membership_level_name'] = $level->name; $this->data['member_email'] = $member->user_email; $this->data['member_name'] = $member->display_name; - $this->data['view_profile'] = admin_url( 'admin.php?page=pmpro-approvals&user_id=' . $member->ID ); + $this->data['view_profile'] = admin_url( 'admin.php?page=pmpro-approvals&user_id=' . $member->ID . '&l=' . $level->id ); } $this->data = apply_filters( 'pmpro_approvals_admin_denied_email_data', $this->data, $member, $admin ); diff --git a/pmpro-approvals.php b/pmpro-approvals.php index a1ecc6d..c78872e 100644 --- a/pmpro-approvals.php +++ b/pmpro-approvals.php @@ -3,7 +3,7 @@ Plugin Name: Paid Memberships Pro - Approvals Add On Plugin URI: https://www.paidmembershipspro.com/add-ons/approval-process-membership/ Description: Grants administrators the ability to approve/deny memberships after signup. -Version: 1.4.3 +Version: 1.5 Author: Stranger Studios Author URI: https://www.paidmembershipspro.com Text Domain: pmpro-approvals @@ -42,6 +42,9 @@ private function __construct() { //add support for PMPro Email Templates Add-on add_filter( 'pmproet_templates', array( 'PMPro_Approvals', 'pmproet_templates' ) ); add_filter( 'pmpro_email_filter', array( 'PMPro_Approvals', 'pmpro_email_filter' ) ); + + //add support for PMPro BuddyPress Add On + add_filter( 'pmpro_bp_directory_sql_parts', array( 'PMPro_Approvals', 'buddypress_sql' ), 10, 2 ); } /** @@ -72,7 +75,7 @@ public static function init() { add_action( 'admin_init', array( 'PMPro_Approvals', 'admin_init' ) ); //add user actions to the approvals page - add_filter( 'pmpro_approvals_user_row_actions', array( 'PMPro_Approvals', 'pmpro_approvals_user_row_actions' ), 10, 2 ); + add_filter( 'pmpro_approvals_user_row_actions', array( 'PMPro_Approvals', 'pmpro_approvals_user_row_actions' ), 10, 3 ); //add approval section to edit user page $membership_level_capability = apply_filters( 'pmpro_edit_member_capability', 'manage_options' ); @@ -116,7 +119,6 @@ public static function init() { //Integrate with Member Directory. add_filter( 'pmpro_member_directory_sql_parts', array( 'PMPro_Approvals', 'pmpro_member_directory_sql_parts'), 10, 9 ); - add_filter( 'gettext', array( 'PMPro_Approvals', 'change_your_level_text' ), 10, 3 ); //Integrate with Pay By Check Add On add_action( 'pmpro_approvals_after_approve_member', array( 'PMPro_Approvals', 'pmpro_pay_by_check_approve' ), 10, 2 ); @@ -664,6 +666,7 @@ public static function getUserApproval( $user_id = null, $level_id = null ) { if ( ! empty( $user_id ) ) { //default to the user's current level if ( empty( $level_id ) ) { + _doing_it_wrong( __FUNCTION__, __( 'You should pass a level ID to getUserApproval.', 'pmpro-approvals' ), '1.5' ); $level = pmpro_getMembershipLevelForUser( $user_id ); if ( ! empty( $level ) ) { $level_id = $level->id; @@ -701,6 +704,7 @@ public static function getUserApprovalStatus( $user_id = null, $level_id = null, //get the PMPro level for the user if ( empty( $level_id ) ) { + _doing_it_wrong( __FUNCTION__, __( 'You should pass a level ID to getUserApprovalStatus.', 'pmpro-approvals' ), '1.5' ); $level = pmpro_getMembershipLevelForUser( $user_id ); if ( ! empty( $level ) ) { @@ -799,14 +803,12 @@ public static function isApproved( $user_id = null, $level_id = null ) { //get approval for this user/level $user_approval = self::getUserApproval( $user_id, $level_id ); - //if no array, check if they already have the level if ( empty( $user_approval ) || ! is_array( $user_approval ) ) { - $level = pmpro_getMembershipLevelForUser( $user_id ); - - if ( empty( $level ) || ( ! empty( $level_id ) && $level->id != $level_id ) ) { - $user_approval = array( 'status' => 'pending' ); - } else { + // Check if the user had this level before it was set to require approval. + if ( ! empty( $level_id ) && self::hasMembershipLevelSansApproval( $level_id, $user_id ) ) { $user_approval = array( 'status' => 'approved' ); + } else { + $user_approval = array( 'status' => 'pending' ); } } @@ -863,9 +865,8 @@ public static function isPending( $user_id = null, $level_id = null ) { //if no array, check if they already had the level if ( empty( $user_approval ) || ! is_array( $user_approval ) ) { - $level = pmpro_getMembershipLevelForUser( $user_id ); - - if ( empty( $level ) || ( ! empty( $level_id ) && $level->id != $level_id ) ) { + // Check if the user had this level before it was set to require approval. + if ( ! empty( $level_id ) && self::hasMembershipLevelSansApproval( $level_id, $user_id ) ) { return true; } else { return false; @@ -1002,6 +1003,26 @@ public static function getApprovals( $l = false, $s = '', $status = 'pending', $ return $theusers; } + /** + * Hooks into the BuddyPress member directory. + * Hide the user if they are pending/denied. + * + * @since 1.5 + */ + public static function buddypress_sql( $sql_parts, $levels_included ) { + + global $wpdb; + + $sql_parts['JOIN'] .= " LEFT JOIN {$wpdb->usermeta} umm + ON umm.meta_key = CONCAT('pmpro_approval_', m.membership_id) + AND umm.meta_key != 'pmpro_approval_log' + AND m.user_id = umm.user_id "; + + $sql_parts['WHERE'] .= " AND ( umm.meta_value LIKE '%approved%' OR umm.meta_value IS NULL ) "; + + return $sql_parts; + } + /** * Approve a member. * @@ -1022,6 +1043,7 @@ public static function approveMember( $user_id, $level_id = null, $force = false // get user's current level if none given. if ( empty( $level_id ) ) { + _doing_it_wrong( __FUNCTION__, __( 'No level ID given. Please pass a level ID to approveMember().', 'pmpro-approvals' ), '1.5' ); $user_level = pmpro_getMembershipLevelForUser( $user_id ); $level_id = $user_level->id; } @@ -1062,8 +1084,8 @@ public static function approveMember( $user_id, $level_id = null, $force = false if ( $send_emails ) { // send email to user and admin. $approval_email = new PMPro_Approvals_Email(); - $approval_email->sendMemberApproved( $user_id ); - $approval_email->sendAdminApproval( $user_id ); + $approval_email->sendMemberApproved( $user_id, $level_id ); + $approval_email->sendAdminApproval( $user_id, null, $level_id ); } self::updateUserLog( $user_id, $level_id ); @@ -1089,6 +1111,7 @@ public static function denyMember( $user_id, $level_id ) { //get user's current level if none given if ( empty( $level_id ) ) { + _doing_it_wrong( __FUNCTION__, __( 'No level ID given. Please pass a level ID to denyMember().', 'pmpro-approvals' ), '1.5' ); $user_level = pmpro_getMembershipLevelForUser( $user_id ); $level_id = $user_level->id; } @@ -1114,8 +1137,8 @@ public static function denyMember( $user_id, $level_id ) { // Send email to member and admin. $denied_email = new PMPro_Approvals_Email(); - $denied_email->sendMemberDenied( $user_id ); - $denied_email->sendAdminDenied( $user_id ); + $denied_email->sendMemberDenied( $user_id, $level_id ); + $denied_email->sendAdminDenied( $user_id, null, $level_id ); self::updateUserLog( $user_id, $level_id ); @@ -1141,6 +1164,7 @@ public static function resetMember( $user_id, $level_id ) { //get user's current level if none given if ( empty( $level_id ) ) { + _doing_it_wrong( __FUNCTION__, __( 'No level ID given. Please pass a level ID to resetMember().', 'pmpro-approvals' ), '1.5' ); $user_level = pmpro_getMembershipLevelForUser( $user_id ); $level_id = $user_level->id; } @@ -1176,9 +1200,9 @@ public static function resetMember( $user_id, $level_id ) { public static function pmpro_before_change_membership_level( $level_id, $user_id, $old_levels, $cancel_level ) { // First see if the user is cancelling. If so, try to clean up approval data if they are pending. - if ( $level_id == 0 ) { - if ( self::isPending( $user_id, $old_levels[0]->ID ) ) { - self::clearApprovalData( $user_id, $old_levels[0]->ID, apply_filters( 'pmpro_approvals_delete_log_on_cancel', false ) ); + if ( ! empty( $cancel_level ) ) { + if ( self::isPending( $user_id, $cancel_level ) ) { + self::clearApprovalData( $user_id, $cancel_level, apply_filters( 'pmpro_approvals_delete_log_on_cancel', false ) ); } } @@ -1233,7 +1257,7 @@ public static function pmpro_after_change_membership_level( $level_id, $user_id //send email to admin that a new member requires approval. $email = new PMPro_Approvals_Email(); - $email->sendAdminPending( $user_id ); + $email->sendAdminPending( $user_id, null, $level_id ); } /** @@ -1247,13 +1271,18 @@ public static function pmpro_non_member_text_filter( $text ) { if ( ! pmpro_hasMembershipLevel() ) { return $text; } else { - //get current user's level ID - $users_level = pmpro_getMembershipLevelForUser( $current_user->ID ); - $level_id = $users_level->ID; - if ( self::requiresApproval( $level_id ) && self::isPending() ) { - $text = __( 'Your membership requires approval before you are able to view this content.', 'pmpro-approvals' ); - } elseif ( self::requiresApproval( $level_id ) && self::isDenied() ) { - $text = __( 'Your membership application has been denied. Contact the site owners if you believe this is an error.', 'pmpro-approvals' ); + // Loop through all user levels and check if any are pending approval or denied. + $user_levels = pmpro_getMembershipLevelsForUser( $current_user->ID ); + foreach ( $user_levels as $user_level ) { + if ( ! self::requiresApproval( $user_level->id ) ) { + continue; + } + + if ( self::isPending( $current_user->ID, $user_level->id ) ) { + return esc_html__( 'Your membership requires approval before you are able to view this content.', 'pmpro-approvals' ); + } elseif ( self::isDenied( $current_user->ID, $user_level->id ) ) { + return esc_html__( 'Your membership application has been denied. Contact the site owners if you believe this is an error.', 'pmpro-approvals' ); + } } } @@ -1263,7 +1292,12 @@ public static function pmpro_non_member_text_filter( $text ) { /** * Set user action links for approvals page */ - public static function pmpro_approvals_user_row_actions( $actions, $user ) { + public static function pmpro_approvals_user_row_actions( $actions, $user, $approval_user = null ) { + if ( empty( $approval_user ) ) { + // Doing it wrong. Approval user should now be passed. + _doing_it_wrong( __FUNCTION__, 'The $approval_user parameter is required.', '1.5' ); + } + $cap = apply_filters( 'pmpro_approvals_cap', 'pmpro_approvals' ); if ( current_user_can( 'edit_users' ) && ! empty( $user->ID ) ) { @@ -1271,7 +1305,11 @@ public static function pmpro_approvals_user_row_actions( $actions, $user ) { } if ( current_user_can( $cap ) && ! empty( $user->ID ) ) { - $actions[] = 'View'; + if ( empty( $approval_user ) ) { + $actions[] = 'View'; + } else { + $actions[] = 'View'; + } } return $actions; @@ -1281,19 +1319,23 @@ public static function pmpro_approvals_user_row_actions( $actions, $user ) { * Add Approvals status to Account Page. */ public static function pmpro_account_bullets_top() { - $approval_status = ucfirst( self::getUserApprovalStatus() ); + // Get all of the user's approval statuses. + $approval_statuses = self::getUserApprovalStatuses(); - $user_level = pmpro_getMembershipLevelForUser(); - if ( empty( $user_level ) ) { - return; - } - - $level_approval = self::requiresApproval( $user_level->ID ); + // Get all levels that require approval. + $approval_levels = self::getApprovalLevels(); - // Only show this if the user has an approval status. - if ( $level_approval ) { - printf( '
  • ' . __( 'Status', 'pmpro-approvals' ) . ':' . ' %s
  • ', $approval_status ); + // Display approval status for each level that requires approval. + foreach ( $approval_levels as $approval_level_id ) { + // Check if we have an approval status. + if ( ! empty( $approval_statuses[ $approval_level_id ] ) ) { + // Check that the user has this level. + if ( self::hasMembershipLevelSansApproval( $approval_level_id ) ) { + $level = pmpro_getLevel( $approval_level_id ); + printf( '
  • ' . esc_html( 'Approval Status for %s', 'pmpro-approvals' ) . ':' . ' %s
  • ', $level->name, $approval_statuses[ $approval_level_id ] ); + } } + } } /** @@ -1310,9 +1352,13 @@ public static function pmpro_members_list_user( $user ) { return $user; } - // Show user status if the user is pending. - if ( current_user_can( 'pmpro_approvals' ) && self::isPending( $user->ID, $user->membership_id ) && ! in_array( $level_type, $status_in ) ) { - $user->membership .= ' (' . __( 'Pending', 'pmpro-approvals' ) . ')'; + // Check if the user is pending for any of their levels. + $approval_levels = self::getApprovalLevels(); + foreach ( $approval_levels as $approval_level_id ) { + if ( self::isPending( $user->ID, $approval_level_id ) ) { + $user->membership .= ' (' . __( 'Pending', 'pmpro-approvals' ) . ')'; + break; + } } return $user; @@ -1343,25 +1389,34 @@ public static function pmpro_confirmation_message( $confirmation_message, $pmpro global $current_user; - $approval_status = self::getUserApprovalStatus(); + // Try to get the membership ID for the confirmation. + if ( ! empty( $pmpro_invoice ) ) { + $membership_id = $pmpro_invoice->membership_id; + } elseif ( empty( $pmpro_invoice ) && ! empty( $_REQUEST['level' ] ) ) { + $membership_id = (int) $_REQUEST['level']; + } else { + $membership_id = $current_user->membership_level->ID; + } - $users_level = pmpro_getMembershipLevelForUser( $current_user->ID ); - $level_id = $users_level->ID; + $approval_status = self::getUserApprovalStatus( $current_user->ID, $membership_id ); //if current level does not require approval keep confirmation message the same. - if ( ! self::requiresApproval( $level_id ) ) { + if ( ! self::requiresApproval( $membership_id ) ) { return $confirmation_message; } + // Get the specific membership level object for this confirmation. + $membership = pmpro_getSpecificMembershipLevelForUser( $current_user->ID, $membership_id ); + $email_confirmation = self::getEmailConfirmation( $current_user->ID ); if ( ! $email_confirmation ) { $approval_status = __( 'pending', 'pmpro-approvals' ); } - $confirmation_message = '

    ' . sprintf( __( 'Thank you for your membership to %1$s. Your %2$s membership status is: %3$s.', 'pmpro-approvals' ), get_bloginfo( 'name' ), $current_user->membership_level->name, $approval_status ) . '

    '; + $confirmation_message = '

    ' . sprintf( __( 'Thank you for your membership to %1$s. Your %2$s membership status is: %3$s.', 'pmpro-approvals' ), get_bloginfo( 'name' ), $membership->name, $approval_status ) . '

    '; - // Check instructions + // Check instructions. $pmpro_invoice should not be empty when reaching here. if ( ! empty( $pmpro_invoice ) && $pmpro_invoice->gateway == "check" && ! pmpro_isLevelFree( $pmpro_invoice->membership_level ) ) { $confirmation_message .= '
    ' . wpautop( wp_unslash( pmpro_getOption("instructions") ) ) . '
    '; } @@ -1435,58 +1490,19 @@ public static function pmpro_email_filter( $email ) { //Approve members from edit profile in WordPress. public static function show_user_profile_status( $user ) { - - //get some info about the user's level - if ( isset( $_REQUEST['membership_level'] ) ) { - $level_id = intval( $_REQUEST['membership_level'] ); - $level = pmpro_getLevel( $level_id ); - } else { - $level = pmpro_getMembershipLevelForUser( $user->ID ); - if ( ! empty( $level ) ) { - $level_id = $level->id; - } else { - $level_id = null; - } - } - - //process any approve/deny/reset click - if ( current_user_can( 'pmpro_approvals' ) ) { - if ( ! empty( $_REQUEST['approve'] ) ) { - self::approveMember( intval( $_REQUEST['approve'] ), $level_id ); - } elseif ( ! empty( $_REQUEST['deny'] ) ) { - self::denyMember( intval( $_REQUEST['deny'] ), $level_id ); - } elseif ( ! empty( $_REQUEST['unapprove'] ) ) { - self::resetMember( intval( $_REQUEST['unapprove'] ), $level_id ); - } - } - //show info ?> - - +
    - - ID, null, false ); ?> - - - ID, $level_id ) ) { -?> -style="display: none;"> - [X] - - ID, $level_id ) ) { -?> -style="display: none;"> - Approve | - Deny - - + // Link to the approvals admin page for this user. + $approvals_admin_url = admin_url( 'admin.php?page=pmpro-approvals&s=' . $user->display_name . '&status=all' ); + ?> +

    + +

    - id; } @@ -1686,10 +1651,13 @@ public static function getApprovalCount( $approval_status = null ) { // If we don't have this value yet, get all users with 'pending' status. if ( ! isset( $number_of_users[$approval_status] ) ) { + + $approval_levels = self::get_all_approval_level_ids(); // Get level ID's that require approvals only and search against those. + $sql_parts = array(); $sql_parts['SELECT'] = "SELECT COUNT(mu.user_id) as count FROM $wpdb->pmpro_memberships_users mu "; $sql_parts['JOIN'] = "LEFT JOIN $wpdb->usermeta um ON um.user_id = mu.user_id AND um.meta_key LIKE CONCAT('pmpro_approval_', mu.membership_id) "; - $sql_parts['WHERE'] = "WHERE mu.status = 'active' AND mu.membership_id > 0 AND um.meta_value LIKE '%" . esc_sql( $approval_status ) . "%' "; + $sql_parts['WHERE'] = "WHERE mu.status = 'active' AND mu.membership_id IN (" . implode( ',', $approval_levels ) . ") AND um.meta_value LIKE '%" . esc_sql( $approval_status ) . "%'"; $sql_parts['GROUP'] = ""; $sql_parts['ORDER'] = ""; $sql_parts['LIMIT'] = ""; @@ -1726,6 +1694,11 @@ public static function getApprovalCount( $approval_status = null ) { ); $results = $wpdb->get_results( $sqlQuery ); + + if ( ! $results ) { + $number_of_users[$approval_status] = 0; + } + $number_of_users[$approval_status] = (int) $results[0]->count; set_transient( 'pmpro_approvals_approval_count', $number_of_users, 3600*24 ); @@ -1822,6 +1795,27 @@ public static function pmpro_pay_by_check_approve( $user_id, $level_id, $order_i } } + /** + * Get level ID's that require approval. + * + * @return array $level_ids An array of level_ids that requires approval. + * @since 1.5 + */ + public static function get_all_approval_level_ids() { + $all_levels = pmpro_getAllLevels( true, true ); + + $approval_levels = array(); + foreach( $all_levels as $level_id => $data) { + if ( self::requiresApproval( $level_id ) ) { + $approval_levels[] = $level_id; + } + + } + + return $approval_levels; + + } + /** * Add links to the plugin row meta @@ -1847,35 +1841,6 @@ public static function text_domain() { load_plugin_textdomain( 'pmpro-approvals', false, basename( dirname( __FILE__ ) ) . '/languages' ); } - /** - * Change "Your Level" to "Awaiting Approval" in these instances for pending users. - * @since 1.3 - */ - public static function change_your_level_text( $translated_text, $text, $domain ) { - global $current_user; - - $approved = self::isApproved( $current_user->ID ); - - // Bail if the user is approved. - if ( $approved ) { - return $translated_text; - } - - $approval = self::getUserApproval( $current_user->ID ); - - if ( $domain == 'paid-memberships-pro' ) { - if ( $translated_text == 'Your Level' ) { - if ( $approval['status'] == 'pending' ){ - $translated_text = __( 'Pending Approval', 'pmpro-approvals' ); - } else { - $translated_text = __( 'Membership Denied', 'pmpro-approvals' ); - } - } - } - return $translated_text; - } - - } // end class PMPro_Approvals::get_instance(); diff --git a/readme.txt b/readme.txt index 72b5c7e..712ba84 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: strangerstudios, andrewza Tags: paid memberships pro, pmpro, approval, approvals, workflow Requires at least: 5.0 Tested up to: 6.0 -Stable tag: 1.4.3 +Stable tag: 1.5 Grants administrators the ability to approve/deny memberships after signup. @@ -36,6 +36,12 @@ Members pending approval will not have access to view members-only content until View full documentation at: https://www.paidmembershipspro.com/add-ons/approval-process-membership/ == Changelog == += 1.5 - 2022-10-06 = +* ENHANCEMENT: Added support for Multiple Memberships Per User, allowing individual approval for each level ID a user may hold. +* ENHANCEMENT: Improved logic for the Approval Counter to increase accuracy. +* ENHANCEMENT: Added support for member directory filtering within the PMPro BuddyPress & BuddyBoss Add On. +* BUG FIX: Fixed an issue where free checkouts would cause a warning that level ID's are missing on the confirmation page. + = 1.4.3 - 2022-07-19 = * ENHANCEMENT: Added Approval level template and support for PMPro v2.9+ settings UI.