Phone data pipeline phases

Summary

Per-phase reference for the four pipeline phases. Each phase is a method on MAM_Phone_Data_Pipeline that mutates the MAM_Phone_Data_Context. Sibling plugins extend the pipeline through hooks fired at well-known points; the most-used hook (mam_get_phone_data_before_send) fires at the content-phase boundary.


phase_auth

Purpose: Resolve identity, hydrate MAM_Current_Request.

Reads:

  • $_REQUEST for the auth nonce, user id, role hint
  • WP wp_get_current_user()
  • MAM_Current_Request setup

Writes to context:

  • user_id, user_role, is_cloning, is_app_request

Hooks fired: None at this phase boundary.

Default subscriber (priority 10 in the legacy filter, runs as part of this phase): mam_user_roles_manager::manage_phone_data.

After this phase the rest of the pipeline can rely on mam_current_request() being correctly populated.


phase_settings

Purpose: Load app settings, evaluate cache decisions, check the short-circuit hook.

Reads:

  • mam_app_settings_get_setting('no', $role, 'general-settings', 'tsl-setting-disable_caching') — controls cursor reset
  • mam_main_allow_cache_json_elements — global cache flag
  • mam_main_json_debug — debug enable

Writes to context:

  • bypass_caching flag
  • Settings cache, theme/branding base data

Hooks fired:

  • mam_local_app_data (short-circuit) — if any subscriber returns a non-empty array, the pipeline returns it immediately. Frozen contract.

Default subscriber: mam_app_settings::manage_phone_data (priority 1) — base theme + branding settings.


phase_content

Purpose: Build page/button/section data; let sibling plugins inject; build navigation; resolve forms.

Sub-steps (in order):

  1. Button loop — for each button in the role’s button array, resolve the content class and call get_data_for_app($category). The result is merged into the response.
  2. Per-button enrichmentapply_filters('mam_app_settings_get_buttons', ...) then per-button apply_filters('mam_tab_manager', $button) (~43 subscribers) and apply_filters('mam_final_button_settings', $button).
  3. Tab-bar dispatch — for each tab-bar setting where visible === 'on', fires mam_main_skip_tab_bar_button then mam_main_add_tab_bar_item_{slug} then the same enrichment chain.
  4. Form data — injects the cached form definitions, the nonce, and sync_user_meta.
  5. Left menumain_create_left_menu($button_array, $data_array).
  6. AJAX URL — injects the admin-ajax URL for the app to POST to.
  7. Pre-send filter — fires the legacy mam_get_phone_data_before_send filter with the assembled $data_array. ~70 subscribers.
  8. Post-pre-send checkmam_main_check_initial_form (form-state validation).

Writes to context:

  • The full $data_array shape

Hooks fired:


phase_finalize

Purpose: Inject home_cats, apply final-block overrides, output-shaping cleanup.

Sub-steps:

  1. home_cats injectionMAM_Main_Manager::manage_phone_data (priority 1000 in the legacy filter) builds the home-screen category structure. Critical contract: must run after every priority < 1000 subscriber.
  2. Final-block overrides — use-case priority-9999 subscribers run here for total replacement of sections.
  3. Output shaping:
    • clean_notifications($data_array) — trim notification payload to active items
    • mam_clean_subcategories($json_content) — strip empty subcategories
    • mam_replace_null_with_empty_string($array) — replace null with "" (older mobile parsers reject null in string fields)
    • mam_add_pn_ids() — hydrate per-user push-notification ids
    • mam_json_validate($data_array, $line) — validate JSON before send

Writes to context: Final array passed to wp_send_json($context->to_array()).

Hooks fired: Subscribers at priority 1000+ in the legacy filter run here.


Phase boundaries — for new pipeline subscribers

The pipeline also fires phase-tagged actions for new code that wants to opt into a specific phase rather than the legacy filter:

do_action( 'mam_phone_data_phase_auth',     $context );
do_action( 'mam_phone_data_phase_settings', $context );
do_action( 'mam_phone_data_phase_content',  $context );
do_action( 'mam_phone_data_phase_finalize', $context );

These pass the MAM_Phone_Data_Context object directly. New plugins should prefer phase-tagged hooks over the legacy filter; the legacy filter remains fired at the content-phase boundary indefinitely as a frozen contract.


When to hook which phase

If you want to… Hook this
Override identity for the whole pipeline phase_auth
Short-circuit and return a complete response mam_local_app_data
Inject content (the common case) mam_get_phone_data_before_send at priority 10
Run after the default cohort but before home_cats mam_get_phone_data_before_send at priority 99
Validate or clean the final structure mam_get_phone_data_before_send at priority 1001+
Modify a single button’s enrichment mam_tab_manager or mam_final_button_settings
Add a tab-bar item dynamically mam_main_add_tab_bar_item_{slug}

Gotchas

  • phase_settings short-circuit returns early. Don’t put critical setup in phase_content and rely on it always running.
  • The button loop is per-item. A list of 50 listings calls every per-button filter 50 times. Cache expensive lookups inside callbacks.
  • mam_get_phone_data_before_send is fired ONCE per pipeline run with the full $data_array, not per button. Per-button hooks are mam_tab_manager and friends.
  • Output shaping happens last. A subscriber that adds a JSON-incompatible value (a closure, a resource) won’t fail until wp_send_json() blows up.

  • Phone data pipeline overview
  • Mobile JSON shape
  • Cursor cache mechanism
  • Priority conventions for phone-data subscribers
  • Hook: mam_get_phone_data_before_send
  • Hook: mam_local_app_data
  • Hook: mam_main_check_initial_form
  • Hook: mam_tab_manager

Metadata

Field Value
Article type Plugin Overview
Plugin slug mam-main
Applies to plugin version 2.1.11+
Category Plugin Reference
Audience PHP developer
Last verified 2026-05-02
Contents

    Need Support?

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