Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save dwanjuki/dd28014c9320a54226ad11767f3ca064 to your computer and use it in GitHub Desktop.

Select an option

Save dwanjuki/dd28014c9320a54226ad11767f3ca064 to your computer and use it in GitHub Desktop.
<?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