Hook: mam_app_settings_get_setting

Purpose

The settings-cascade read filter. Every setting read in mam-main flows through this filter. Sibling plugins register handlers per-key to extend reads without touching the app-settings subsystem.

⚠️ Hot path. Runs 100+ times per phone-data build. Subscribers must be cheap.


Signature

$value = apply_filters(
    'mam_app_settings_get_setting',
    $default,        // value to return if no stored value exists
    $role,           // role slug ('subscriber', 'admin', 'mam-all', etc.)
    $button_id,      // button-id namespace ('general-settings', 'login', a real button id, ...)
    $key             // the setting key ('tsl-setting-disable_caching', etc.)
);

Registered by the data manager at priority 10, 4 (four args).

Parameter Type Description
$default mixed Fallback if no stored value exists
$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 The setting key

Returns: mixed — the resolved value.


The cascade

For a given $button_id + $key, the data manager runs a single query against
wp_mam_app_settings_options that resolves the fallback in one shot. First hit wins.

1. Role-specific row          (role = $role)
2. Global row                 (role = 'mam-all')
3. Default                    ($default arg, returned when neither row exists)

The fallback is a single ORDER BY inside app-settings-data-manager.php‘s get_setting(),
not chained filter subscribers. Subscribers shouldn’t try to re-implement it.


Example: simple read

$radius = apply_filters(
    'mam_app_settings_get_setting',
    25,                                      // default
    mam_current_request()->user_role(),
    'general-settings',
    'tsl-setting-geofilter_radius'
);

Example: subscriber that overrides one key

add_filter( 'mam_app_settings_get_setting', function ( $value, $role, $button_id, $key ) {

    // Only handle my plugin's special key.
    if ( $key !== 'my_plugin_special_value' ) {
        return $value;
    }

    // Cheap: read from my plugin's own option.
    return get_option( 'my_plugin_special_value', $value );

}, 10, 4 );

⚠️ Notice the early return — subscribers that don’t apply to this key must short-circuit immediately. Doing work for every key is the most common cause of slow phone-data responses.


Example: cached subscriber

add_filter( 'mam_app_settings_get_setting', function ( $value, $role, $button_id, $key ) {

    if ( $button_id !== 'my_plugin' ) {
        return $value;
    }

    static $cache = null;
    if ( $cache === null ) {
        $cache = wp_cache_get( 'my_plugin_settings', 'mam' ) ?: array();
    }

    return $cache[ $key ] ?? $value;

}, 10, 4 );

For non-trivial lookups, use wp_cache_get / wp_cache_set — multiplied by hundreds of calls, the savings are large.


Hot-path anti-patterns

  • ❌ Make HTTP calls
  • ❌ Run unbatched DB queries (get_post_meta per row)
  • ❌ Allocate large objects per call
  • apply_filters recursion
  • ❌ Iterate every key looking for a match (early-return based on $key)
  • ✅ Early return when the key doesn’t match
  • ✅ Use wp_cache_get / wp_cache_set
  • ✅ Use static for per-request caching

Gotchas

  • Hot path. A 50ms subscriber adds 5+ seconds to every phone-data build (100+ invocations).
  • The cascade is in the data manager. Don’t try to re-implement fallback by chaining subscribers.
  • Frozen contract. ~20 direct apply_filters call sites across the suite, but 100+ invocations per phone-data build (settings are read inside per-button / per-role loops).
  • Cloning admins read settings for the role they’re cloning, not their actual admin role.
  • An empty $role falls back to 'mam-all' (the global row). Pass '' or 'mam-all'; don’t invent a 'global' string.
  • The $button_id namespace is '<plugin-slug>' (or a real button id) for sibling plugins. Don’t reuse a core sentinel like 'general-settings' for your own keys.

  • Settings cascade overview
  • Per-button and per-role settings
  • Hook: mam_app_settings_set_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 — ~20 call sites, 100+ invocations per build
Last verified 2026-05-02
Was this article helpful?
Contents

    Need Support?

    Can't find the answer you're looking for? Don't worry we're here to help!