Stop members downgrading their membership level#280
Conversation
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
left a comment
There was a problem hiding this comment.
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-40—pmpro_getLevelAtCheckout()can returnnull(barereturn;) when no valid level ID is found. The snippet immediately dereferences$checkout_level->idwithout 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()doesreturn;(null) if$level_idis 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:10—link: TBDis 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-52—array_search()is called without the$strictthird argument. The$level_orderarray 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. Usearray_search( $checkout_level_id, $level_order, true )to make the intent explicit and guard against any future type drift.
Looks Good
- The
false === $member_levelcheck at line 33 and the$checkout_level_rank || $member_level_rankbail at line 53 both use strict comparison correctly — avoids the classicarray_searchreturning0(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.
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.