Purpose
Per-plugin licensing check. Returns the entitlement record for a specific MAM Suite plugin slug for the current customer site. Sibling plugins query this to decide whether to bootstrap.
Backed by mam_entitlement_manager (includes/plugin-update-manager/) and the WPMAM software-manager API. The entitlement record can include flags like blocked, expired, or trial.
Signature
$entitlement = apply_filters(
'mam_plugin_entitlement',
$default,
string $plugin_slug
);
| Parameter | Type | Description |
|---|---|---|
$default |
mixed | Fallback (typically false or an empty array) |
$plugin_slug |
string | The plugin slug to check (e.g., mam-geodirectory) |
Returns: mixed — entitlement record (typically array) or the default.
Example: gate a sibling plugin’s bootstrap
add_action( 'plugins_loaded', function () {
$entitlement = apply_filters( 'mam_plugin_entitlement', false, 'mam-my-plugin' );
$state = is_array( $entitlement ) ? ( $entitlement['state'] ?? '' ) : '';
if ( 'blocked' === $state ) {
// Don't bootstrap — customer isn't entitled or has been blocked.
return;
}
if ( 'expired' === $state ) {
// Show an admin notice; don't bootstrap functional code.
add_action( 'admin_notices', 'my_plugin_expired_notice' );
return;
}
// Normal bootstrap.
new MAM_My_Plugin_Manager();
} );
This is the pattern mam-geodirectory and other sibling plugins use to decide whether to register their hooks.
Entitlement record shape
The record is always an array with a state key (the filter normalizes the raw WPMAM response into this shape). Keys:
| Key | Meaning |
|---|---|
state |
One of entitled, blocked, grace, expired — the primary gate |
reason |
Why this state was assigned (purchased, source_server, cache_miss, not_purchased, grace, subscription_expired) |
plugin_slug |
The plugin slug that was checked |
expires_at |
Timestamp — present for expired and grace states |
grace_until |
Grace-period end timestamp (source-side; surfaced as expires_at for the grace state) |
Gate on state: entitled (and, in practice, grace) mean bootstrap; blocked and expired mean don’t. Note the fail-open behavior — a cold cache or a plugin missing from the API response returns state = entitled with reason = cache_miss.
How it resolves
mam_plugin_entitlement filter is applied
│
▼
mam_entitlement_manager checks the cached entitlement map
│ (cache is per-account-code, refreshed periodically)
▼
Cache miss → WPMAM software-manager API call
│ POSTs account code, receives entitlement map
▼
Persist + return the per-plugin record
Related: mam_check_required_version
Sibling plugins also commonly check that mam-main is at a sufficient version. The filter takes ($requires, $plugin) — the required version and a plugin name used in the admin alert it raises — and returns the installed mam-main version string (it does not return a boolean), so compare it yourself:
$installed = apply_filters( 'mam_check_required_version', '1.9.1', 'My Plugin' );
$ok = version_compare( $installed, '1.9.1', '>=' );
Gotchas
- Cache is per-account-code. Switching account codes (rare — should never happen on a live site) requires a cache flush.
- Network failures produce stale entitlement reads. The graceful-degradation hook (see
MAM_Account_Code_Managerpatterns) applies — defaults often assume “still entitled” during planned outages. - Don’t gate every request by re-firing this filter at request-time; bootstrap-time check is enough. Fire it once on
plugins_loadedand cache the decision. - Customer-side blocking is admin/support territory. Don’t try to “auto-recover” from a blocked entitlement.
- The
$defaultargument is effectively ignored. The bundled subscriber always returns a normalizedstatearray (fail-open toentitled/cache_misswhen it has no data), so don’t rely on your default being returned — gate onstateinstead.
Related articles
- Integration: Account code and enrollment server
- Recipe: Customer enrollment and account code
- Frozen public contracts reference
Metadata
| Field | Value |
|---|---|
| Article type | Hook Reference |
| Plugin slug | mam-main |
| Applies to plugin version | 2.1.11+ |
| Hook type | filter |
| Audience | PHP developer |
| Last verified | 2026-05-02 |
