BricksMembers provides a comprehensive event-based extensibility system. Extensions react to events but cannot override core access decisions. This preserves system integrity while enabling powerful integrations.
Core Principle: React, Don’t Decide
Extensions can respond to access changes but cannot bypass core access logic. This means:
- Send email on
access_granted - Sync CRM on
access_revoked - Add bonus access on
payment_completed(via separate API call) - Queue background jobs on
access_scheduled
Available Events
Each event carries an \BaselMedia\BricksMembers\Core\Event object with:
- User ID – The affected user
- Resource Type – ‘level’ or ‘post’
- Resource ID – Level or post ID
- Reason – Why this happened (e.g., ‘scheduled_expiration’)
- Trigger – What caused it (admin, webhook, woocommerce, cron, api)
- Timestamp – When it occurred
- Correlation ID – UUID for tracing related events
- Context – Additional data specific to the event
Event Types
| Event | Description |
|---|---|
access_granted | User gained access to a level or post |
access_revoked | User lost access to a level or post |
access_scheduled | Access change scheduled for the future (e.g., expiration) |
access_expired | Scheduled access expired (fires before revocation) |
access_rebuilt | Access state was recalculated (progress rebuild, cache sync) |
progress_completed | User completed a lesson/post |
progress_incompleted | User marked content incomplete |
content_unlocked | Drip content became available |
Subscribe to Events (Recommended)
Use \BaselMedia\BricksMembers\Utilities\ExtensionRegistry::subscribe() to listen for specific event types. Add these use statements at the top of your file:
use BaselMedia\BricksMembers\Utilities\ExtensionRegistry;
use BaselMedia\BricksMembers\Core\Event;
// Subscribe to access_granted events
ExtensionRegistry::subscribe(
Event::ACCESS_GRANTED,
function( Event $event ): void {
// Send welcome email when level access is granted
if ( $event->get_resource_type() === 'level' ) {
$user_id = $event->get_user_id();
$level_id = $event->get_resource_id();
$reason = $event->get_reason();
$trigger = $event->get_trigger();
// Log with correlation ID for tracing
error_log( sprintf(
'[%s] User %d granted level %d via %s: %s',
$event->get_correlation_id(),
$user_id,
$level_id,
$trigger,
$reason
) );
send_welcome_email( $user_id, $level_id );
}
}
);
// Subscribe to access_expired events
// Note: access_expired fires BEFORE the actual revocation.
// The sequence is: access_expired -> access_revoked (brm_event_access_revoked)
ExtensionRegistry::subscribe(
Event::ACCESS_EXPIRED,
function( Event $event ): void {
// Send expiration-specific notification
notify_user_access_expired(
$event->get_user_id(),
$event->get_resource_id()
);
}
);
// Subscribe to ALL events for logging/auditing
ExtensionRegistry::subscribe_all(
function( Event $event ): void {
log_to_audit_system( $event->to_array() );
}
);
Event Context Management
When triggering access changes from your code, set the event context:
use BaselMedia\BricksMembers\Core\Event;
// Option 1: Set context manually
brm_set_event_context( Event::TRIGGER_WEBHOOK, 'payment_received' );
brm_add_user_level( $user_id, $level_id );
brm_clear_event_context();
// Option 2: Use the helper wrapper
brm_with_event_context(
Event::TRIGGER_API,
'external_system_sync',
function() use ( $user_id, $level_id ) {
brm_add_user_level( $user_id, $level_id );
}
);
Register Settings Sections
Extensions can register settings sections to add admin UI:
use BaselMedia\BricksMembers\Utilities\ExtensionRegistry;
ExtensionRegistry::register_settings_section(
'my_extension',
array(
'title' => __( 'My Extension', 'brm' ),
'description' => __( 'Additional settings for My Extension.', 'brm' ),
'callback' => 'my_extension_render_settings',
)
);
Extension Guidelines
- React, don’t decide – Extensions cannot override core access logic.
- Use services for mutations; avoid direct DB writes.
- Use
\BaselMedia\BricksMembers\Services\CoreDataServicefor read-only access. - Set event context when triggering access changes from external sources.
- Use correlation IDs to trace related events across systems.
- Route cache invalidation through
\BaselMedia\BricksMembers\Core\MutationContract.
See docs/api/actions.md for the full actions reference.