Skip to content

Stop members downgrading their membership level#280

Open
dwanjuki wants to merge 5 commits into
strangerstudios:devfrom
dwanjuki:prevent-membership-level-tier-downgrade
Open

Stop members downgrading their membership level#280
dwanjuki wants to merge 5 commits into
strangerstudios:devfrom
dwanjuki:prevent-membership-level-tier-downgrade

Conversation

@dwanjuki

Copy link
Copy Markdown
Contributor

This snippet can be used to prevent members from downgrading their levels on sites with hierarchical memberships.

Originally a "make your day" snippet for a customer.

Not MMPU-compatible.

This snippet can be used to prevent members from downgrading their levels on sites with hierarchical levels.

Originally a "make your day" snippet for a customer.

Not MMPU-compatible.

@flintfromthebasement flintfromthebasement left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR: #280 — Stop members downgrading their membership level
dwanjuki → dev | 1 file, +67 -0 lines
#280

Summary
Clean, well-structured snippet with good early-returns and readable logic. One unchecked return value will cause a PHP fatal in edge cases; fix that and this is ready to merge.

Issues

  • Major stop-members-from-downgrading-level.php:39-40pmpro_getLevelAtCheckout() can return null (bare return;) when no valid level ID is found. The snippet immediately dereferences $checkout_level->id without a null check, which throws a fatal PHP error in PHP 8+ and a fatal "Call to a member function on null" in older versions — crashing checkout for any user who hits that path.

    Confirmed in core: pmpro_getLevelAtCheckout() does return; (null) if $level_id is empty or < 1 after all fallbacks exhaust.

    Fix: add a null check immediately after fetching the checkout level:

    $checkout_level = pmpro_getLevelAtCheckout();
    if ( empty( $checkout_level ) ) {
        return $okay;
    }
    $checkout_level_id = $checkout_level->id;
  • Minor stop-members-from-downgrading-level.php:10link: TBD is a placeholder. Needs a real URL before this goes live, or at minimum a tracking note that it needs updating at publish time.

  • Minor stop-members-from-downgrading-level.php:51-52array_search() is called without the $strict third argument. The $level_order array holds integers and the IDs come from ->id (also integers), so type coercion isn't currently a problem — but the false-for-not-found check on line 53 relies on strict comparison (false ===), which is inconsistent with a non-strict search. Use array_search( $checkout_level_id, $level_order, true ) to make the intent explicit and guard against any future type drift.

Looks Good

  • The false === $member_level check at line 33 and the $checkout_level_rank || $member_level_rank bail at line 53 both use strict comparison correctly — avoids the classic array_search returning 0 (falsy but not false) problem.
  • Renewal short-circuit at line 43 is correct and necessary.
  • The MMPU incompatibility is clearly documented in both the PR description and the file header.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants