Signature
apply_filters( 'mam_special_offers_skip_tab_bar_button', array $tabbar_button, array $data_array );
| Parameter | Type | Description |
|---|---|---|
$tabbar_button |
array | The fully constructed Edit Deals button. Has at least icon ('black_gift'), action ('open_form_array'), and source (an array of one form entry per existing offer plus an Add Offer entry when the cap allows). |
$data_array |
array | The listing context the button is being built for. Keys include at least id (the parent listing post ID). |
Returns: array — the final tab bar button. Return an empty array to skip rendering. You must return an array.
Purpose
Provides the last-word override on the in-app Edit Deals button. The plugin builds the entire button — icon, action, and a source array of form entries — and then runs it through this filter just before returning it to the tab bar pipeline. Subscribers can:
- Skip the button by returning
array(). Useful for ownership gating, where only the listing’s owner should see the management UI. - Modify the source list by trimming
$tabbar_button['source'], reordering it, or replacing form entries. - Change the icon or label to match the app’s design system.
There’s an earlier escape hatch — Hook: mam_special_offers_hard_skip_tab_bar_button — that fires before the button is built. Prefer the hard skip if you can decide based on $data_array alone, because it avoids the (potentially expensive) database query for the listing’s existing offers. Use this filter when your decision depends on inspecting what the button is going to contain.
When it runs
Once per Edit Deals tab bar build, at the very end of mam_special_offers_tab_bar_manager::mam_app_settings_tab_bar_button_edit_deals() (includes/mam_special_offers_tab_bar_manager.php):
// ... build $forms by walking existing offers, gated by mam_special_offers_deals_allowed ...
if ( empty( $forms ) ) {
return array();
}
$tabbar_button['icon'] = 'black_gift';
$tabbar_button['action'] = 'open_form_array';
$tabbar_button['source'] = $forms;
return apply_filters( 'mam_special_offers_skip_tab_bar_button', $tabbar_button, $data_array );
By the time your callback runs:
- The Gravity Form lookup has resolved successfully (otherwise an empty array was returned earlier and your filter does not fire).
- The hard-skip filter returned
false(otherwise an empty array was returned earlier and your filter does not fire). - The offers query has run and the source list is fully built.
- The deals-allowed cap has been applied to the Add Offer row.
Default behavior
The plugin doesn’t subscribe to this filter itself. With no callback registered, the button is returned exactly as built.
Examples
Gate by listing ownership
add_filter( 'mam_special_offers_skip_tab_bar_button', 'my_app_owner_only_deals', 10, 2 );
function my_app_owner_only_deals( $button, $data_array ) {
$listing_author = (int) get_post_field( 'post_author', $data_array['id'] );
if ( $listing_author !== mam_user_id() ) {
return array();
}
return $button;
}
This is the canonical pairing for Recipe: Let venue owners manage offers from the app — without it, every authenticated app user sees the button on every listing they visit.
Hide the Add Offer row but keep existing-offer editing
add_filter( 'mam_special_offers_skip_tab_bar_button', 'my_app_no_new_offers' );
function my_app_no_new_offers( $button ) {
if ( empty( $button['source'] ) ) {
return $button;
}
$button['source'] = array_values( array_filter(
$button['source'],
static fn ( $entry ) => 'Add Offer' !== ( $entry['custom_form_name'] ?? '' )
) );
if ( empty( $button['source'] ) ) {
return array();
}
return $button;
}
A subtler version of the deals-allowed cap — keep editing of existing offers, but block adding new ones during a freeze period.
Change the icon for a specific app brand
add_filter( 'mam_special_offers_skip_tab_bar_button', static function ( $button ) {
if ( empty( $button ) ) {
return $button;
}
$button['icon'] = 'black_star';
return $button;
} );
Gotchas
- Always return an array. Returning
nullorfalsewill break the tab bar build downstream. To skip, returnarray()explicitly. - Doesn’t run when the button has already short-circuited. If the Gravity Form ID hasn’t been generated yet, or the hard-skip filter returned
true, your callback never sees the button. Don’t rely on this filter as the only place an “is the button visible?” decision is made. $data_array['id']is the listing’s post ID, not the offer’s. The button operates at listing scope. To inspect offers, walk$button['source']— each entry’scustom_form_values['postid']is the offer ID it edits.- The Add Offer entry has
postid => ''. Filter logic distinguishing “edit existing” from “create new” should check for an empty string, not just an integer. - Returning a button without a
sourceis invalid. The mobile client expects an array there. If you trim every entry, returnarray()instead of leaving an emptysource.
Verification
This article was last verified against:
- Plugin:
mam-special-offersv2.1 - Source:
mam-special-offers/includes/mam_special_offers_tab_bar_manager.php
Re-verify whenever the button structure (icon, action, source) changes, the early-return logic in mam_app_settings_tab_bar_button_edit_deals() is reordered, the mam_special_offers_hard_skip_tab_bar_button companion is renamed, or the Add Offer entry’s identifying field (custom_form_name) changes.
Related articles
- Plugin: mam-special-offers
- Recipe: Let venue owners manage offers from the app
- Hook: mam_special_offers_deals_allowed — earlier in the same builder
- Hook: mam_specials_get_post_radius
- Hook: mam_specials_get_post_lat
Metadata
| Field | Value |
|---|---|
| Article type | Hook Reference |
| Plugin slug | mam-special-offers |
| Applies to plugin version | 2.1+ |
| Category | Extending MAM Suite |
| Hook type | filter |
| Audience | PHP developer |
| Last verified | 2026-05-01 |
