BricksMembers uses a normalized storage model for user levels, post requirements, and direct completions, plus derived projection tables for structure and aggregate progress.
Core Runtime Model
- Canonical structure truth:
_brm_parent_level_*post meta - Derived structure projection:
brm_post_data - Canonical user levels:
brm_user_level_assignments - Canonical post requirements:
brm_post_level_requirements - Canonical direct completions:
brm_user_post_completions - Aggregate progress projection:
brm_user_progress
Drip runtime model: Global drip rules live in brm_global_drip_rules and are normalized before runtime. Rule targeting now supports structure, selected_posts, and post_type. Per-post drip behavior can be overridden via _brm_drip_override. Preserved unlock timestamps live in brm_user_unlocks, but computed drip status remains the canonical runtime access truth for conditions, filters, and frontend rendering.
Protected downloads capability model: the admin surface is gated by brm_manage_downloads, and the brm_download post type uses BRM-specific capabilities such as edit_brm_download and create_brm_downloads. Administrators receive those caps automatically so the downloads module does not mutate global WordPress capabilities.
Core API
$levels = brm_get_user_levels( $user_id );
$has_access = brm_can_user_access_content_now( $user_id, $post_id );
brm_add_user_level( $user_id, $level_id );
brm_set_post_levels( $post_id, [ 1, 2 ] );
brm_mark_content_completed( $user_id, $post_id );
$is_completed = brm_is_content_completed( $user_id, $post_id );
Developer Rules
- Use public
brm_*APIs for extension-facing reads and writes - Use canonical services directly inside plugin internals
- Do not treat
brm_user_dataas runtime truth in0.9.82+ - Do not write structure paths directly unless you are in the projection/rebuild layer
- Use request cache and batch loaders instead of ad-hoc repeated queries
- Normalize drip rules through the drip rules service instead of reading raw option arrays directly
Uninstall Ownership
uninstall.php is the single opt-in cleanup owner and exits unless WordPress defines WP_UNINSTALL_PLUGIN. Deactivation and normal plugin deletion preserve data by default. Full cleanup runs per site, including every site in a multisite network, only when that site’s brm_delete_data_on_uninstall option or its documented filter resolves true.
The cleanup uses the centrally maintained BRM table catalog, deletes current and future options/transients in the brm_* namespaces, removes brm_* and _brm_* user/post/term metadata with prepared escaped-prefix queries, and explicitly removes the legacy webhook_field_mappings option and required_level term meta. Content-structure posts are deleted only when brm_delete_structure_posts_on_uninstall is separately enabled. New storage owners must update the uninstall catalog and its architecture contract without widening cleanup into unrelated WordPress data.
Optional Modules
Progress, drip, downloads, quizzes and assessments, groups and team licenses, and submissions all build on the same core access and structure model. Check module activation before calling module-specific helpers.
Progress target reads such as {brm_progress:completed_item:last} belong to CompletedItemTargetReadService, with SQL delegated to ProgressTrackingReadService. The dynamic tag renderer is only the Bricks adapter; it does not own completion storage or structure scoping.