0 Day Analytics – WP Panel Module Developer Documentation

Table of Contents

1. Overview & Architecture

The WP Panel module provides a centralised admin page for toggling 40+ WordPress core behaviours. Unlike the plugin’s REST API endpoints (which use the 0-day/v1 namespace), the WP Panel uses a traditional WordPress form submission flow via admin_post_ actions.

Key Characteristics

  • Single static class: ADVAN\Helpers\WP_Panel
  • Settings stored in a dedicated wp_options row (separate from the main plugin settings)
  • No REST API endpoints — uses admin-post.php form POST
  • No AJAX handlers — all operations are synchronous page reloads
  • No separate JavaScript files — only inline JS for accordion toggling and conditional field display
  • Settings enforcement happens at runtime via WordPress filters and actions registered during init
  • Requires manage_options capability (Administrator role)

Technology Stack

  • PHP 7.4+ (strict types)
  • WordPress Options API for persistence
  • WordPress admin_post_ action for form handling
  • Nonce-protected form submission
  • Inline JavaScript for UI interactions

2. File Map

advanced-analytics/
├── classes/
│   ├── class-advanced-analytics.php          — Module activation check
│   └── vendor/
│       ├── helpers/
│       │   ├── class-wp-panel.php            — Main WP Panel class (~1,680 lines)
│       │   └── class-settings.php            — Plugin settings (module default + menu registration)
│       └── settings/
│           └── settings-options/
│               └── wp-panel.php              — Settings tab: "Enable WP Panel module" checkbox
└── css/
    └── admin/
        └── style.css                         — Shared admin styles (includes WP Panel CSS classes)

3. WP_Panel Class Reference

3.1 Constants

PHP
<?php
namespace ADVAN\Helpers;

class WP_Panel {
    public const PAGE_SLUG     = ADVAN_INNER_SLUG . '_page_advan_wp_panel';  // Screen base
    public const MENU_SLUG     = 'advan_wp_panel';                           // Submenu slug
    public const OPTION_NAME   = ADVAN_PREFIX . 'wp_panel_settings';         // wp_options key

    private const SAVE_ACTION   = 'advan_wp_panel_save';                     // admin_post action
    private const NONCE_ACTION  = 'advan_wp_panel_nonce';                    // Nonce action string
    private const NONCE_FIELD   = '_advan_wp_panel_nonce';                   // Nonce field name
    private const LAST_LOGIN_META = '_advan_last_login';                     // User meta key
}
Constant Visibility Value Purpose
PAGE_SLUG public ADVAN_INNER_SLUG . '_page_advan_wp_panel' WordPress screen base identifier
MENU_SLUG public 'advan_wp_panel' Submenu page slug used in URL
OPTION_NAME public ADVAN_PREFIX . 'wp_panel_settings' Database option key in wp_options
SAVE_ACTION private 'advan_wp_panel_save' Used with admin_post_ hook
NONCE_ACTION private 'advan_wp_panel_nonce' Nonce verification action
NONCE_FIELD private '_advan_wp_panel_nonce' Hidden form field name for nonce
LAST_LOGIN_META private '_advan_last_login' User meta key storing last login timestamp

3.2 Settings Methods

Method Visibility Return Description
get_defaults() public static array Returns an associative array of all 46 setting keys with their default values (all booleans default to false).
get_settings() public static array Retrieves stored settings from database and merges with defaults via wp_parse_args(). Result is cached in a static property.
store_settings(array $settings) private static void Persists the settings array to wp_options with autoload=no. Updates the static cache.

Default Values Structure

PHP
<?php
public static function get_defaults(): array {
    return array(
        // Content & editing — all boolean, default false.
        'disable_comments'              => false,
        'disable_post_revisions'        => false,
        'post_revisions_limit'          => 10,    // int, 1–100
        'disable_autosave'              => false,
        'disable_block_editor'          => false,
        'disable_file_editing'          => false,

        // Security & API — all boolean, default false.
        'disable_xmlrpc'                => false,
        'disable_rest_api_public'       => false,
        'disable_application_passwords' => false,
        // ... 7 more boolean keys ...

        // Updates — all boolean, default false.
        'disable_auto_updates_core'     => false,
        // ... 3 more keys ...

        // Front-end / performance — all boolean, default false.
        'disable_emojis'                => false,
        // ... 7 more keys ...

        // Dequeue frontend assets — all boolean, default false.
        'dequeue_wp_embed'              => false,
        // ... 8 more keys ...

        // Media — boolean.
        'disable_attachment_pages'      => false,

        // Admin — boolean.
        'disable_admin_bar_frontend'    => false,

        // Heartbeat control.
        'heartbeat_control'             => 'default', // 'default' | 'disable' | 'modify'
        'heartbeat_frequency'           => 60,        // int, 15–300
        'heartbeat_admin_disable'       => false,
        'heartbeat_editor_disable'      => false,
        'heartbeat_frontend_disable'    => false,

        // WP back-end extend.
        'enable_last_login_column'      => false,
        'enable_registration_date_column' => false,
    );
}

3.3 Runtime Enforcement (apply_settings())

Called during init(), this method reads the stored settings and attaches the appropriate WordPress filters and actions. Each setting key maps to a specific set of hooks.

Enforcement Techniques Used

Technique Settings That Use It
Return false via filter disable_xmlrpc, disable_block_editor, disable_application_passwords, disable_rest_jsonp, disable_admin_bar_frontend, auto-update toggles
Define PHP constant disable_post_revisions (WP_POST_REVISIONS), disable_file_editing (DISALLOW_FILE_EDIT)
remove_action() / remove_filter() Emoji, embed, feed, generator, WLW manifest, RSD link, shortlink, REST link head/header, adjacent posts
wp_deregister_script() disable_autosave, heartbeat_control (disable), per-location heartbeat
wp_dequeue_script/style() All dequeue_* settings
Custom callback with wp_die() disable_rss_feeds
301 redirect disable_attachment_pages
HTTP headers enable_security_headers, remove_x_pingback_header
REST authentication error disable_rest_api_public
User meta tracking + list table columns enable_last_login_column, enable_registration_date_column
Important: Settings that define PHP constants (WP_POST_REVISIONS, DISALLOW_FILE_EDIT) will not take effect if those constants are already defined elsewhere (e.g., in wp-config.php).

3.4 Save Handler (handle_save())

Processes the form POST submitted from the WP Panel admin page.

Security Checks

  1. current_user_can('manage_options') — capability check
  2. wp_verify_nonce() — nonce verification using NONCE_FIELD and NONCE_ACTION

Sanitisation Logic

Setting Key Sanitisation Clamping
post_revisions_limit absint() Min 1, Max 100
heartbeat_control sanitize_text_field() + whitelist check Must be default, disable, or modify
heartbeat_frequency absint() Min 15, Max 300
All other keys filter_var(FILTER_VALIDATE_BOOLEAN) Absent = false

Post-save Redirect

PHP
<?php
\wp_safe_redirect(
    \add_query_arg(
        array(
            'page'    => self::MENU_SLUG,
            'updated' => '1',
        ),
        \admin_url( 'admin.php' )
    )
);
exit;

3.5 Rendering Methods

Method Visibility Description
render_admin_page() public static Renders the full admin page HTML: header, success notice, form with 8 collapsible sections, save button, and inline JS.
render_card_toggle(string $key, string $label, string $description, array $settings) private static Outputs a single card with a label, description paragraph, and a toggle switch checkbox.

Card Toggle HTML Structure

XML
<div class="advan-wp-panel-card">
    <div class="advan-wp-panel-card-main">
        <div class="advan-wp-panel-card-text">
            <h3>Setting Label</h3>
            Setting description text.

        </div>
        <div class="advan-wp-panel-card-control">
            <label class="advan-wp-panel-switch" for="setting_key">
                <input type="checkbox" id="setting_key" name="setting_key" value="1" />
                <span class="advan-wp-panel-slider"></span>
            </label>
        </div>
    </div>
</div>

CSS Classes Used

Class Element Purpose
.advan-wp-panel-wrap Container Main wrapper for the page
.advan-wp-panel-header Header Page title and subtitle area
.advan-wp-panel-grid Grid Layout container for sections
.advan-wp-panel-section Section Collapsible section wrapper; has data-section attribute
.advan-wp-panel-section-header Section header Clickable header with icon, title, chevron
.advan-wp-panel-section-body Section body Contains the toggle cards
.advan-wp-panel-card Card Individual setting card
.advan-wp-panel-switch Label Toggle switch wrapper
.advan-wp-panel-slider Span Visual slider for toggle
.advan-wp-panel-select Select Dropdown control (heartbeat mode)
.advan-wp-panel-number Input Numeric input control
.advan-wp-panel-card-group Div Groups related cards (heartbeat locations)
.is-collapsed Section Added when section is collapsed

3.6 User List Column Helpers

When enabled, the module adds sortable columns to the wp-admin/users.php list table.

Last Login Column

Method Hook Description
add_last_login_column(array $columns) manage_users_columns Adds advan_last_login column
render_last_login_column($output, $column_name, $user_id) manage_users_custom_column Renders formatted date or “Never”
sortable_last_login_column(array $columns) manage_users_sortable_columns Registers as sortable
sort_by_last_login($query) pre_get_users Sets meta_key for sorting

Login timestamps are stored as Unix timestamps in user meta (_advan_last_login) via the wp_login action.

Registration Date Column

Method Hook Description
add_registration_date_column(array $columns) manage_users_columns Adds advan_registered column
render_registration_date_column($output, $column_name, $user_id) manage_users_custom_column Renders user_registered date
sortable_registration_date_column(array $columns) manage_users_sortable_columns Registers as sortable
sort_by_registration_date($query) pre_get_users Sets orderby to registered

3.7 Asset Helpers

Method Hook Description
dequeue_wp_assets() wp_enqueue_scripts (priority 100000) Conditionally dequeues/deregisters front-end scripts and styles based on dequeue_* settings
strip_version_query($src) style_loader_src, script_loader_src (priority 9999) Removes ?ver= from asset URLs when remove_version_query_strings is enabled

4. Data Model & Storage

All WP Panel settings are stored in a single row in the wp_options table.

Property Value
Table wp_options
Option Name {ADVAN_PREFIX}wp_panel_settings
Autoload no
Format Serialised PHP array
Size 46 keys (boolean, integer, and string values)

Reading Settings Programmatically

PHP
<?php
// Get all WP Panel settings (merged with defaults).
$settings = \ADVAN\Helpers\WP_Panel::get_settings();

// Check a specific setting.
if ( ! empty( $settings['disable_comments'] ) ) {
    // Comments are disabled.
}

// Get raw stored value (without defaults).
$raw = get_option( \ADVAN\Helpers\WP_Panel::OPTION_NAME, array() );

5. Settings Key Reference

Key Type Default Section
disable_comments bool false Content & Editing
disable_post_revisions bool false Content & Editing
post_revisions_limit int 10 Content & Editing
disable_autosave bool false Content & Editing
disable_block_editor bool false Content & Editing
disable_file_editing bool false Content & Editing
disable_xmlrpc bool false Security & API
disable_rest_api_public bool false Security & API
disable_application_passwords bool false Security & API
disable_rest_output_link_wp_head bool false Security & API
disable_adjacent_posts_rel_link bool false Security & API
disable_rest_jsonp bool false Security & API
disable_rest_output_link_header bool false Security & API
remove_version_query_strings bool false Security & API
remove_x_pingback_header bool false Security & API
enable_security_headers bool false Security & API
disable_auto_updates_core bool false Updates
disable_auto_updates_plugins bool false Updates
disable_auto_updates_themes bool false Updates
disable_update_notifications bool false Updates
disable_emojis bool false Front-end & Performance
disable_embeds bool false Front-end & Performance
disable_rss_feeds bool false Front-end & Performance
disable_self_pingbacks bool false Front-end & Performance
disable_wp_generator bool false Front-end & Performance
disable_wlw_manifest bool false Front-end & Performance
disable_rsd_link bool false Front-end & Performance
disable_shortlink bool false Front-end & Performance
dequeue_wp_embed bool false Dequeue Frontend Assets
dequeue_wp_block_library bool false Dequeue Frontend Assets
dequeue_wp_block_library_theme bool false Dequeue Frontend Assets
dequeue_wc_block_style bool false Dequeue Frontend Assets
dequeue_jquery bool false Dequeue Frontend Assets
dequeue_jquery_migrate bool false Dequeue Frontend Assets
dequeue_global_styles bool false Dequeue Frontend Assets
dequeue_classic_styles bool false Dequeue Frontend Assets
dequeue_core_block_supports bool false Dequeue Frontend Assets
disable_attachment_pages bool false Media
disable_admin_bar_frontend bool false Admin
heartbeat_control string 'default' Heartbeat Control
heartbeat_frequency int 60 Heartbeat Control
heartbeat_admin_disable bool false Heartbeat Control
heartbeat_editor_disable bool false Heartbeat Control
heartbeat_frontend_disable bool false Heartbeat Control
enable_last_login_column bool false WP Back-end Extend
enable_registration_date_column bool false WP Back-end Extend

6. Module Activation Flow

The WP Panel module is conditionally loaded based on a plugin-level setting.

PHP
<?php
// 1. Settings tab (wp-panel.php) registers checkbox:
//    Option ID: 'wp_panel_module_enabled'
//    Default:   true (enabled)

// 2. Main plugin class checks this setting:
// In class-advanced-analytics.php:
if ( Settings::get_option( 'wp_panel_module_enabled' ) ) {
    WP_Panel::init();
}

// 3. Menu registration (in class-settings.php):
if ( get_option( 'wp_panel_module_enabled' ) ) {
    WP_Panel::menu_add();
}

Initialisation Sequence

  1. WP_Panel::init() is called from the main plugin class
  2. init() registers the admin_post_advan_wp_panel_save handler
  3. init() calls apply_settings() which reads settings and hooks into WordPress
  4. Separately, WP_Panel::menu_add() registers the admin submenu page under Error Logs

7. Admin Form Submission Flow

TEXT
User clicks "Save Changes"
    │
    ▼
POST to wp-admin/admin-post.php
    action = advan_wp_panel_save
    _advan_wp_panel_nonce = {nonce}
    {setting_key} = {value} (for each enabled toggle)
    │
    ▼
WordPress dispatches admin_post_advan_wp_panel_save
    │
    ▼
WP_Panel::handle_save()
    ├── Check: current_user_can('manage_options')
    ├── Check: wp_verify_nonce()
    ├── Loop through get_defaults() keys:
    │   ├── post_revisions_limit → absint() + clamp 1–100
    │   ├── heartbeat_control   → whitelist (default/disable/modify)
    │   ├── heartbeat_frequency → absint() + clamp 15–300
    │   └── all others          → filter_var(FILTER_VALIDATE_BOOLEAN)
    ├── store_settings($sanitised)
    └── wp_safe_redirect(admin.php?page=advan_wp_panel&updated=1)

8. WordPress Hooks & Filters Used

The following is a comprehensive list of WordPress hooks and filters that WP Panel interacts with.

Filters (return value modifications)

Filter Triggered By Return
comments_open disable_comments false
pings_open disable_comments false
comments_array disable_comments array()
use_block_editor_for_post disable_block_editor false
use_block_editor_for_post_type disable_block_editor false
xmlrpc_enabled disable_xmlrpc false
rest_authentication_errors disable_rest_api_public WP_Error for unauthenticated
wp_is_application_passwords_available disable_application_passwords false
rest_jsonp_enabled disable_rest_jsonp false
wp_headers disable_xmlrpc, remove_x_pingback_header Unsets X-Pingback
style_loader_src remove_version_query_strings URL without ?ver=
script_loader_src remove_version_query_strings URL without ?ver=
auto_update_core disable_auto_updates_core false
allow_major_auto_core_updates disable_auto_updates_core false
allow_minor_auto_core_updates disable_auto_updates_core false
auto_update_plugin disable_auto_updates_plugins false
auto_update_theme disable_auto_updates_themes false
tiny_mce_plugins disable_emojis, disable_embeds Removes wpemoji/wpembed
wp_resource_hints disable_emojis, disable_embeds Filters DNS prefetch URLs
embed_oembed_discover disable_embeds false
the_generator disable_wp_generator Empty string
show_admin_bar disable_admin_bar_frontend false
heartbeat_settings heartbeat_control (modify) Modified interval
manage_users_columns Login/registration columns Adds column
manage_users_custom_column Login/registration columns Column HTML
manage_users_sortable_columns Login/registration columns Adds sortable entry

Actions (side effects)

Action Triggered By Effect
admin_post_advan_wp_panel_save Form submission Processes and saves settings
init disable_comments Removes post type support for comments/trackbacks
admin_menu disable_comments Removes Comments menu page
wp_before_admin_bar_render disable_comments Removes comments admin bar item
admin_enqueue_scripts disable_autosave, heartbeat per-location Deregisters scripts
admin_head disable_update_notifications Removes update nag
send_headers enable_security_headers Sends security HTTP headers
do_feed (and variants) disable_rss_feeds wp_die() with 404
pre_ping disable_self_pingbacks Removes self-referencing links
template_redirect disable_attachment_pages 301 redirect
wp_enqueue_scripts Dequeue settings, heartbeat front-end Dequeues assets
wp_login enable_last_login_column Stores login timestamp in user meta
pre_get_users Column sorting Modifies user query orderby

9. Extending the Module

Reading Settings From Other Code

PHP
<?php
// Check if a specific WP Panel setting is active.
$settings = \ADVAN\Helpers\WP_Panel::get_settings();

if ( ! empty( $settings['disable_comments'] ) ) {
    // Comments are disabled via WP Panel.
}

Checking If the Module Is Active

PHP
<?php
// Check if the WP Panel module is enabled.
$module_enabled = \ADVAN\Helpers\Settings::get_option( 'wp_panel_module_enabled' );

if ( $module_enabled ) {
    // WP Panel is active and enforcing settings.
}

Overriding Settings Programmatically

PHP
<?php
// Override WP Panel settings via wp_options directly.
// Warning: This bypasses the module's sanitisation.
$settings = get_option( \ADVAN\Helpers\WP_Panel::OPTION_NAME, array() );
$settings['disable_emojis'] = true;
update_option( \ADVAN\Helpers\WP_Panel::OPTION_NAME, $settings );
Warning: Direct option updates bypass the module’s sanitisation and clamping logic. Use this approach only in custom migration scripts or CLI tools where you fully control the values.

10. Code Examples

Check if Comments Are Disabled Before Rendering

PHP
<?php
/**
 * Conditionally render a comment form only if WP Panel hasn't disabled comments.
 */
function my_theme_maybe_show_comments() {
    if ( class_exists( '\ADVAN\Helpers\WP_Panel' ) ) {
        $settings = \ADVAN\Helpers\WP_Panel::get_settings();
        if ( ! empty( $settings['disable_comments'] ) ) {
            return; // WP Panel has disabled comments.
        }
    }

    comments_template();
}

Check if REST API Is Restricted

PHP
<?php
/**
 * Check if the REST API is restricted to logged-in users.
 */
function is_rest_api_restricted(): bool {
    if ( ! class_exists( '\ADVAN\Helpers\WP_Panel' ) ) {
        return false;
    }

    $settings = \ADVAN\Helpers\WP_Panel::get_settings();

    return ! empty( $settings['disable_rest_api_public'] );
}

Log When WP Panel Settings Are Saved

PHP
<?php
/**
 * Hook into WordPress option update to log WP Panel setting changes.
 */
\add_action( 'update_option_' . \ADVAN\Helpers\WP_Panel::OPTION_NAME, function ( $old, $new ) {
    $changes = array_diff_assoc( $new, $old );
    if ( ! empty( $changes ) ) {
        error_log( 'WP Panel settings changed: ' . \wp_json_encode( $changes ) );
    }
}, 10, 2 );

Export WP Panel Settings via WP-CLI

Shell
# Export current WP Panel settings to a JSON file.
wp option get advan_wp_panel_settings --format=json > wp-panel-settings.json

# Import WP Panel settings from a JSON file.
wp option update advan_wp_panel_settings --format=json < wp-panel-settings.json

Conditionally Load Assets Based on WP Panel Dequeue Settings

PHP
<?php
/**
 * Only enqueue jQuery in your theme if WP Panel hasn't dequeued it.
 */
add_action( 'wp_enqueue_scripts', function () {
    if ( class_exists( '\ADVAN\Helpers\WP_Panel' ) ) {
        $settings = \ADVAN\Helpers\WP_Panel::get_settings();
        if ( ! empty( $settings['dequeue_jquery'] ) ) {
            // WP Panel has dequeued jQuery; use a vanilla JS alternative.
            wp_enqueue_script( 'my-theme-vanilla', get_template_directory_uri() . '/js/vanilla.js', array(), '1.0', true );
            return;
        }
    }

    wp_enqueue_script( 'my-theme-scripts', get_template_directory_uri() . '/js/scripts.js', array( 'jquery' ), '1.0', true );
}, 20 );

Need User Guide documentation?
See WP Panel Module User Guide for more details about configuration, practical usage and information.

← WP Panel Module – User Guide Transients Module — User Guide →
Share this page
Back to top