This reference documents the current Content Bank implementation in BricksMembers: module boot, storage model, structure-editor integration, Bricks behavior, dynamic tags, cache invalidation, and the public helpers exposed to other runtime code.
Overview
The Content Bank is an opt-in BRM module that introduces reusable source posts and structure-specific proxy posts. A proxy is still a real WordPress post, but it stores a source reference and participates in shared-content resolution.
- Admin surface —
BricksMembers → Content BankviaContentBankPage - Editor surface — post meta box for source/proxy management via
ContentBankSystem - Structure surface — staged
Insert from Bankmodal plus proxy creation during structure commit - Bricks surface — source-first builder redirects, dynamic tags, and conditions
Module Boot Path
src/Core/ModuleRegistry.phpmapscontent_banktobrm_enable_content_bank.src/Utilities/ModuleConfig.phpexposes the module toggle in the normalized module config.src/Compatibility/InternalHookBootstrap.phpbootsContentBankSystemand registersContentBankAjaxonly when the module is active.src/Admin/Menu/AdminMenuRegistrar.phpadds the dedicated Content Bank admin page when enabled.
The implementation is intentionally module-gated so the feature adds no runtime hooks when disabled.
Canonical Storage
The Content Bank uses standard WordPress posts plus BRM meta/taxonomy keys. There is no custom Content Bank table.
_brm_bank_item— marks a source post_brm_bank_source_id— links a proxy to its source_brm_bank_blocked_fields— meta keys that should stay empty on a proxy instead of inheriting_brm_bank_title_customized,_brm_bank_content_customized,_brm_bank_excerpt_customized— stop core-field sync once a proxy divergesbrm_collectiontaxonomy — organizes source items in the library
Core field behavior is intentionally hybrid:
- Meta delegates live from source to proxy until the proxy stores a local value or blocks that key.
- Title/content/excerpt are copied to the proxy and synced from the source until the corresponding customization flag flips.
Core Service Layer
The main runtime lives in src/Modules/ContentBank/ContentBankService.php.
is_bank_item(),is_proxy(),get_source_id(),get_source_post()— identity and lookup helperscreate_proxy()— creates a real proxy post, initializes source/customization state, and applies optional levels/taxonomy argsdetach_proxy(),remove_proxy()— proxy lifecycle actionsget_delegated_meta()— central meta-resolution hook targetsync_source_core_fields()— pushes title/content/excerpt changes into still-linked proxiestrack_proxy_customization()— flips customization flags when a proxy diverges from its sourcebrowse_bank_items(),save_collection(),import_bank_data(),export_bank_data()— admin/library flows
Request Registry and Batch Loading
Content Bank keeps request-local state in the RequestRegistry and primes loop data through BatchLoader integration.
bank_proxy— resolved proxy → source IDsbank_local_meta— local meta keys present on a proxybank_blocked— blocked inherited meta keys per proxysrc/Batch/BatchBankLoader.phpprimes source lookups during batched post loads
This keeps proxy/source resolution cheap in query-loop heavy templates.
Structure Editor Integration
The structure integration deliberately uses the existing staged-edit flow instead of inventing an immediate-write side channel.
assets/admin/js/content-bank-structures.jsopens the modal, browses source items via AJAX, and stages a create payload withbank_source_id.src/Admin/StructureAdminController.phplocalizes the Content Bank strings and library URL into the structure admin runtime.src/Structures/Ajax/StructureCommitAjax.phpdetectsbank_source_idduring staged creates and callsContentBankService::create_proxy()instead ofwp_insert_post().
The result is consistent with the rest of the structure editor: proxy insertion remains part of the same staged save/commit lifecycle.
Admin Page and Request Handling
ContentBankPage renders the dedicated admin screen. ContentBankSystem handles the corresponding admin request flows:
- collection create/update/delete
- source library export
- JSON import of source items
- proxy detach flows from the post editor
The current implementation uses BRM security wrappers, nonce verification, and capability checks around those paths. Import handling accepts JSON source-library files only. Export uses a normal download response with a sanitized filename.
Bricks Integration
Bricks integration is intentionally source-first.
filter_builder_edit_link()redirects proxy builder entry points to the source builder URLmaybe_redirect_proxy_bricks_builder()handles front-end proxy builder requests and redirects to the source unless the explicit proxy-edit flag is presentrender_proxy_bricks_notice()explains whether the user is editing the shared source or localizing a proxy
Important implementation detail: BRM does not intercept Bricks saves and rewrite them back onto the source. If a proxy is edited directly in Bricks and saved, that proxy localizes its own Bricks meta and stops inheriting the shared layout for those keys.
Dynamic Tags and Conditions
Content Bank tags are registered through DynamicTagsManager and wired into Bricks rendering via InternalUtilityHookBootstrap.
{brm_bank_is_proxy}{brm_bank_source_title}{brm_bank_source_id}{brm_bank_usage_count}{brm_bank_collections}
The conditions layer is registered through InternalIntegrationHookBootstrap and evaluated by BricksConditionsRegistrar.
AJAX Endpoints
ContentBankAjax currently registers two admin AJAX handlers:
wp_ajax_brm_bank_browse— browse source items for the structure modalwp_ajax_brm_bank_get_usage— retrieve proxy usage for a given source
Both use the normal BRM AJAX nonce. Browsing validates the requested post type and restricts results to items editable by the current user.
Public Runtime Helpers
brm-public-api.php currently exposes the following Content Bank wrappers:
brm_is_bank_item( $post_id )brm_is_bank_proxy( $post_id )brm_bank_get_source_id( $post_id )brm_bank_get_usage_count( $post_id )
These helpers are safe to call from theme/plugin code because they return fallback values when the module is disabled.
Mutation Contract and Cache Invalidation
MutationContract owns the Content Bank cache invalidation rules.
bank_proxy_created()bank_proxy_removed()bank_source_updated()
These methods invalidate the brm_bank cache group and clear affected proxy/source request-runtime state.
Implementation Gotchas
- Do not treat proxies as virtual records. They are normal posts and should continue to fit normal BRM structure/access/progress flows.
- Do not reintroduce live core-field delegation for title/content/excerpt. The current model uses copied fields plus source sync for compatibility.
- Do not add an immediate-write side path for structure insertion while the staged editor exists. Proxy creation should stay in the staged commit pipeline.
- Do not assume editing a proxy in Bricks updates the source. Direct proxy saves localize that proxy.
Related Docs
- User guide:
docs/user-posts/45-content-bank-reusable-source-posts.html - Module doc:
docs/modules/content-bank.md - Plan:
docs/plans/content-bank-plan.md