Purpose
The settings-cascade write filter. Mirror of mam_app_settings_get_setting. Persists a value to the appropriate scope.
Signature
$persisted = apply_filters(
'mam_app_settings_set_setting',
$value, // new value
$role, // role scope (or empty for global)
$category, // settings category
$key // setting key
);
| Parameter | Type | Description |
|---|---|---|
$value |
mixed | The value to persist |
$role |
string | Role scope. Empty = global. |
$category |
string | Settings category |
$key |
string | Setting key |
Returns: mixed — the persisted value (typically $value echoed back).
Per-scope persistence
$role value |
Persisted to |
|---|---|
'' (empty) |
Global option (canonical key) |
'subscriber', 'admin', etc. |
Per-role option (canonical key + role suffix) |
| With a button context | Per-button blob inside local-app-button-array* |
Example: write a per-role value
apply_filters(
'mam_app_settings_set_setting',
'new value',
'subscriber',
'general-settings',
'tsl-setting-geofilter_radius'
);
Example: subscriber-side write hook
add_filter( 'mam_app_settings_set_setting', function ( $value, $role, $category, $key ) {
if ( $key !== 'my_plugin_special_value' ) {
return $value;
}
// 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 $value;
}, 10, 4 );
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 |
