Hook: mam_geodirectory_admin_settings_tab_content_{tab}

Signature

apply_filters( "mam_geodirectory_admin_settings_tab_content_{$tab}", string $html_line, string $tab );
Parameter Type Description
$html_line string HTML accumulated so far for the page. Includes the page header and the tab nav.
$tab string The currently active tab key (sanitized via sanitize_key).

Returns: string — the full HTML for the page. You must return it.


Purpose

Renders the body of a custom admin tab. The hook name is dynamic — it includes the active tab key — so a callback only fires for its own tab. Pair this with Hook: mam_geodirectory_admin_settings_tabs to register the tab key in the first place.

When this filter has any subscribers for the active tab, the page skips its built-in tab rendering for that tab. So you take complete responsibility for the tab body, including any forms, tables, or settings UI.


When it runs

Inside mam_geodirectory_admin_settings::create_admin_page():

$tab = sanitize_key( $_REQUEST['tab'] ?? 'gd-settings' );
$html_line = '<div class="local-app-main-content-area">';
$html_line .= mam_admin_settings::headline( __( 'GeoDirectory Settings', 'mam-suite' ) );
$html_line .= '<h4>...</h4>';
$html_line .= $this->add_page_tabs();

if ( has_filter( 'mam_geodirectory_admin_settings_tab_content_' . $tab ) ) {
    $html_line = apply_filters( 'mam_geodirectory_admin_settings_tab_content_' . $tab, $html_line, $tab );
} elseif ( 'gd-claim-listings' === $tab ) {
    /* render the built-in claim listings UI */
} else {
    /* render the built-in settings UI */
}

The check is has_filter(), so the first subscriber wins — built-in rendering is skipped if anyone has subscribed for that key.


Example

add_filter( 'mam_geodirectory_admin_settings_tabs', function( $tabs ) {
    $tabs['my-app-stats'] = 'Stats';
    return $tabs;
} );

add_filter( 'mam_geodirectory_admin_settings_tab_content_my-app-stats', 'my_app_stats_body', 10, 2 );

function my_app_stats_body( $html_line, $tab ) {
    $listings = wp_count_posts( 'gd_place' );
    $html_line .= '<div class="tsl-admin-settings-holder">';
    $html_line .= '<h3>Listing counts</h3>';
    $html_line .= '<ul>';
    $html_line .= '<li>Published: ' . (int) $listings->publish . '</li>';
    $html_line .= '<li>Pending: '   . (int) $listings->pending . '</li>';
    $html_line .= '<li>Draft: '     . (int) $listings->draft . '</li>';
    $html_line .= '</ul>';
    $html_line .= '</div>';
    return $html_line;
}

Gotchas

  • Built-in rendering is skipped entirely. If you subscribe and forget to render the body, the user sees an empty page.
  • $html_line already includes the page header and nav. Append, don’t replace.
  • Escape user-controlled data. The page renders the result raw via echo $html_line — use esc_html, esc_attr, and the WordPress nonce/cap helpers as you would on any admin page.
  • Capability check is upstream. create_admin_page() already verifies current_user_can('manage_options'). You can rely on that at the page level but add per-action checks (e.g., on form processing) yourself.
  • Forms within your tab need their own nonce. The plugin’s nonce mam_geodirectory_settings_save only validates the global Settings tab’s form. For your own forms, use a distinct nonce.

Verification

This article was last verified against:

  • Plugin: mam-geodirectory v2.1.5
  • Source: includes/mam_geodirectory_admin_settings.phpcreate_admin_page()

Re-verify whenever the page rendering structure changes (e.g., the conditional elseif chain), the has_filter() gating is replaced, or sanitize_key() is replaced as the tab-key sanitiser.


  • Plugin: mam-geodirectory
  • Recipe: Configure the GeoDirectory settings page
  • Hook: mam_geodirectory_admin_settings_tabs
  • Hook: mam_geodirectory_admin_settings

Metadata

Field Value
Article type Hook Reference
Plugin slug mam-geodirectory
Applies to plugin version 2.1.5+
Category Extending MAM Suite
Hook type filter
Audience PHP developer
Last verified 2026-05-01
Contents

    Need Support?

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