Purpose
The settings-cascade write filter. Mirror of mam_app_settings_get_setting. Persists a value to the appropriate scope.
Signature
$status = apply_filters(
'mam_app_settings_set_setting',
$status, // pass-through status value (returned unchanged)
$role, // role scope ('mam-all' for global)
$button_id, // button-id namespace for the setting
$key, // setting key
$value // value to persist
);
Registered by the data manager at priority 10, 5 (five args).
| Parameter | Type | Description |
|---|---|---|
$status |
mixed | Pass-through status — returned unchanged (this filter’s “value” slot is not the written value) |
$role |
string | Role scope. Empty falls back to 'mam-all' (global). |
$button_id |
string | Button-id namespace the setting is stored under (a real button id, or a namespace sentinel like 'general-settings') |
$key |
string | Setting key |
$value |
mixed | The value to persist (the last argument, not the first) |
Returns: mixed — $status echoed back unchanged. The write is a side effect; the return value is not the persisted value.
Per-scope persistence
$role value |
Persisted to |
|---|---|
'' (empty) → 'mam-all' |
Global row (role mam-all) in the wp_mam_app_settings_options table |
'subscriber', 'admin', etc. |
Per-role row (role column = the role) |
The $button_id argument selects the button-id namespace column; every row is keyed by (button_id, role, setting_key, acct_code).
Example: write a per-role value
apply_filters(
'mam_app_settings_set_setting',
'', // status (pass-through)
'subscriber', // role
'general-settings', // button-id namespace
'tsl-setting-geofilter_radius', // key
'new value' // value (last arg)
);
Example: subscriber-side write hook
add_filter( 'mam_app_settings_set_setting', function ( $status, $role, $button_id, $key, $value ) {
if ( $key !== 'my_plugin_special_value' ) {
return $status;
}
// Persist to my plugin's own store.
update_option( 'my_plugin_special_value_' . $role, $value );
// Also invalidate a cache.
wp_cache_delete( 'my_plugin_settings', 'mam' );
return $status;
}, 10, 5 );
Cache invalidation responsibility
If the setting being written affects what the mobile app sees, you may need to invalidate the cursor cache:
JSON_Cursor_Manager::reset_cursor();
Or, more surgically, bump a section-specific timestamp:
update_option( 'my_plugin_data_changed_at', time() );
For form-affecting settings, also invalidate the form cache:
mam_form_manager_cache_manager::invalidate( $form_id );
Gotchas
- Cache invalidation is your responsibility. A subscriber that persists a setting affecting mobile output must invalidate the appropriate cache.
- Per-button writes need a button context. The data manager looks up the active button id from the request; if no button context is set, the write goes per-role or global.
- Frozen contract. Many call sites assume the existing signature.
- Don’t bypass with direct
update_option. The filter runs the data manager’s validation + side-effect chain.
Related articles
- Settings cascade overview
- Per-button and per-role settings
- Cursor cache mechanism
- Hook: mam_app_settings_get_setting
- 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 |
| Frozen contract | yes |
| Last verified | 2026-05-02 |
