Content Bank API

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 surfaceBricksMembers → Content Bank via ContentBankPage
  • Editor surface — post meta box for source/proxy management via ContentBankRuntime
  • Structure surface — staged Insert from Bank modal plus proxy creation during structure commit
  • Bricks surface — source-first builder redirects, dynamic tags, and Bricks conditions

Module Boot Path

  • src/Core/ModuleRegistry.php maps content_bank to brm_enable_content_bank.
  • src/Utilities/ModuleConfig.php exposes the module toggle in the normalized module config.
  • src/Bootstrap/BootstrapCoordinator.php boots ContentBankRuntime and conditionally registers ContentBankAjax during AJAX requests when the module is active.
  • src/Admin/Menu/AdminMenuRegistrar.php adds 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 — legacy cleanup/protection key from the previous copied-field model
  • _brm_bank_content_customized, _brm_bank_excerpt_customized — legacy compatibility markers for explicit body/excerpt overrides on older proxies
  • brm_collection taxonomy — organizes source items in the library

Core field behavior is intentionally hybrid:

  • Title and slug stay local on the proxy and are not resynced from the source after proxy creation.
  • Body and excerpt delegate live from source to proxy when the proxy value is empty; adding a local value makes that field local, and clearing it returns the field to source fallback.
  • Meta, including featured image and custom fields, delegates live from source to proxy until the proxy stores a non-empty local value or blocks that key. Empty local meta values are treated as missing.
  • Content Fields scalar values are native postmeta and therefore follow the same source/proxy fallback path. Definition ownership, sanitization, and required-field validation remain in the Content Fields module.
  • Source saves invalidate Content Bank runtime caches through MutationContract::bank_source_updated() but do not write shared content into proxy post rows.

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 helpers
  • create_proxy() — creates a real proxy post, stores its source link, and applies optional local levels/taxonomy args
  • detach_proxy(), remove_proxy() — proxy lifecycle actions
  • get_delegated_meta() — central meta-resolution hook target
  • get_delegated_core_field(), handle_source_saved(), handle_proxy_saved() — resolve empty proxy body/excerpt fields from the source, invalidate runtime caches after source saves without mutating proxy rows, and remember explicit body/excerpt overrides when the proxy itself is edited
  • browse_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 IDs
  • bank_local_meta — local meta keys with non-empty content on a proxy
  • bank_blocked — blocked inherited meta keys per proxy
  • src/Batch/BatchBankLoader.php primes 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.js opens the modal, browses source items via AJAX, and stages a create payload with bank_source_id.
  • src/Admin/StructureAdminController.php localizes the Content Bank strings and library URL into the structure admin runtime.
  • src/Structures/Ajax/StructureCommitAjax.php detects bank_source_id during staged creates and calls ContentBankService::create_proxy() instead of wp_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. ContentBankRuntime 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 URL
  • maybe_redirect_proxy_bricks_builder() handles front-end proxy builder requests and redirects to the source unless the explicit proxy-edit flag is present
  • render_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 BricksDynamicTagListComposer and wired into Bricks rendering through UtilityBootstrap and the dynamic tag integration path.

  • {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 the Bricks condition registrar path and evaluated by BricksConditionsRegistrar.

AJAX Endpoints

ContentBankAjax currently registers two admin AJAX handlers:

  • wp_ajax_brm_bank_browse — browse source items for the structure modal
  • wp_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 source-save writes into proxy rows. Proxies should read shared body, excerpt, and meta values dynamically when their local value is empty.
  • Do not treat empty proxy meta as a local override. Empty local values are intentionally equivalent to missing values.
  • 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.
Get BricksMembers

Start Building Your Membership Site Today

Create, sell, and manage your content without limits. BricksMembers gives you everything you need to build membership and LMS sites with Bricks Builder.

Lifetime updates & bug fixes • Premium support • 0% transaction fees • 60-day money-back guarantee