Last active
July 7, 2026 08:29
-
-
Save dwanjuki/dd28014c9320a54226ad11767f3ca064 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * This recipe requires members to apply and be approved for the "application" level | |
| * again before rejoining a "main" level after their main membership has ended. | |
| * | |
| * For this recipe to work, you must be using the Approvals Add On and your main | |
| * levels must be set to "Yes. User must have an approved membership for a different | |
| * level." or "Yes. User must have an approved membership for a different level AND | |
| * admin must approve new members for this level." under the Approval Settings when | |
| * editing the membership level. Other approval and non-approval levels will not | |
| * be affected. | |
| * | |
| * 1. When a member's main membership ends (expires, is cancelled, or is removed), | |
| * their application level membership is removed and its approval is cleared. | |
| * They must sign up for the application level and be approved again before | |
| * rejoining. | |
| * 2. The Approvals Add On will then block checkout for the main level until the | |
| * member has been approved for the application level again. | |
| * 3. Members who still hold an active main membership can renew it without being | |
| * approved again. | |
| * | |
| * You can add this recipe to your site by creating a custom plugin | |
| * or using the Code Snippets plugin available for free in the WordPress repository. | |
| * Read this companion article for step-by-step directions on either method. | |
| * https://www.paidmembershipspro.com/create-a-plugin-for-pmpro-customizations/ | |
| */ | |
| /** | |
| * Build an array of main level ID => required application level ID pairs | |
| * from the Approvals Add On level settings. | |
| * | |
| * @return array Main level IDs as keys, required application level IDs as values. | |
| */ | |
| function my_pmproap_get_main_to_application_levels() { | |
| $map = array(); | |
| if ( ! class_exists( 'PMPro_Approvals' ) ) { | |
| return $map; | |
| } | |
| $options = PMPro_Approvals::getOptions(); | |
| foreach ( $options as $level_id => $level_options ) { | |
| if ( ! empty( $level_options['restrict_checkout'] ) ) { | |
| $map[ (int) $level_id ] = (int) $level_options['restrict_checkout']; | |
| } | |
| } | |
| return $map; | |
| } | |
| /** | |
| * When a member loses a main level (expiration, cancellation, or admin change), | |
| * remove their application level membership and clear its approval so they must | |
| * apply and be approved again before rejoining the main level. | |
| * | |
| * @param array $old_user_levels Array of user_id => array of old level objects. | |
| */ | |
| function my_pmproap_reset_approval_when_main_level_ends( $old_user_levels ) { | |
| $main_to_application = my_pmproap_get_main_to_application_levels(); | |
| if ( empty( $main_to_application ) ) { | |
| return; | |
| } | |
| // Track whether we cancel a level so we can re-run the level change action. | |
| $cancelled_membership = false; | |
| foreach ( $old_user_levels as $user_id => $old_levels ) { | |
| $old_level_ids = wp_list_pluck( $old_levels, 'id' ); | |
| $current_levels = pmpro_getMembershipLevelsForUser( $user_id ); | |
| $current_level_ids = wp_list_pluck( $current_levels, 'id' ); | |
| foreach ( $main_to_application as $main_level_id => $application_level_id ) { | |
| // Only act when the user just lost this main level. | |
| if ( ! in_array( $main_level_id, $old_level_ids ) || in_array( $main_level_id, $current_level_ids ) ) { | |
| continue; | |
| } | |
| // Skip if the application level does not require approval. | |
| if ( ! PMPro_Approvals::requiresApproval( $application_level_id ) ) { | |
| continue; | |
| } | |
| // Leave denied members denied. | |
| if ( PMPro_Approvals::isDenied( $user_id, $application_level_id ) ) { | |
| continue; | |
| } | |
| // If the member still holds the application level, cancel it so they | |
| // have to sign up for it again rather than just being re-approved. | |
| if ( PMPro_Approvals::hasMembershipLevelSansApproval( $application_level_id, $user_id ) ) { | |
| pmpro_cancelMembershipLevel( $application_level_id, $user_id ); | |
| $cancelled_membership = true; | |
| } | |
| // Remove the old approval entirely so they must apply again. This is | |
| // required even after cancelling, since the Approvals Add On surfaces | |
| // the recorded decision regardless of whether the level is held. | |
| delete_user_meta( $user_id, 'pmpro_approval_' . $application_level_id ); | |
| delete_transient( 'pmpro_approvals_approval_count' ); | |
| } | |
| } | |
| // If we cancelled any application levels above, re-run the level change | |
| // action so other integrations process those cancellations. Our own guard | |
| // only acts on lost main levels, so this will not recurse. | |
| if ( $cancelled_membership ) { | |
| pmpro_do_action_after_all_membership_level_changes(); | |
| } | |
| } | |
| add_action( 'pmpro_after_all_membership_level_changes', 'my_pmproap_reset_approval_when_main_level_ends', 20 ); | |
| /** | |
| * Let members with an active main membership renew that level without being | |
| * approved for the application level again. | |
| * | |
| * @param int $restrict_checkout The level ID the member must be approved for, or 0 for none. | |
| * @param int $level_id The level ID being checked out for. | |
| * @return int The filtered restrict checkout level ID. | |
| */ | |
| function my_pmproap_skip_approval_for_renewals( $restrict_checkout, $level_id ) { | |
| // Nothing to do if this level doesn't require approval for another level. | |
| if ( empty( $restrict_checkout ) ) { | |
| return $restrict_checkout; | |
| } | |
| if ( is_admin() || ! is_user_logged_in() || ! class_exists( 'PMPro_Approvals' ) ) { | |
| return $restrict_checkout; | |
| } | |
| // Active members of this level can renew without being approved again. | |
| if ( PMPro_Approvals::hasMembershipLevelSansApproval( $level_id, get_current_user_id() ) ) { | |
| return 0; | |
| } | |
| return $restrict_checkout; | |
| } | |
| add_filter( 'pmpro_approvals_level_restrict_checkout', 'my_pmproap_skip_approval_for_renewals', 10, 2 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment