0 Day Analytics – Table Module Developer Documentation

Table of Contents

1. Overview & Architecture

The Table Viewer Module provides a full-featured database table browser and editor within the WordPress admin. It allows administrators to inspect, search, edit, insert, and delete rows in any database table — including WordPress core tables and custom tables created by plugins or themes.

Key Capabilities

  • Browse all database tables with a searchable dropdown selector
  • View row details in a modal overlay via REST API
  • Add new rows with type-aware, auto-generated form fields
  • Edit existing rows with pre-filled values and column-type detection
  • Delete individual rows or use bulk delete
  • Full-text search across all columns using SQL LIKE matching
  • Sort by any column (ascending/descending)
  • CSV export with progress bar and cancellation support
  • Table information modal (structure, indexes, foreign keys, health)
  • Table optimization (reclaim fragmented space)
  • Truncate and drop non-core tables with confirmation
  • WordPress core table protection (truncate/drop blocked)
  • Object cache detection and warning
  • Multisite-aware table operations

Technology Stack

  • PHP 7.4+ (strict types)
  • WordPress WP_List_Table API (via Abstract_List)
  • WordPress REST API for row detail retrieval, truncate, and drop
  • wp-api-fetch for client-side REST calls
  • jQuery for modal, clipboard, and share interactions
  • Custom CSV export with batch processing via AJAX

2. File Map

advanced-analytics/
├── classes/
│   └── vendor/
│       ├── lists/
│       │   ├── class-table-list.php          — WP_List_Table for table data
│       │   ├── views/
│       │   │   └── class-table-view.php      — Page rendering, forms & action handlers
│       │   └── entity/
│       │       └── class-common-table.php    — Database operations & table utilities
│       ├── controllers/
│       │   └── class-endpoints.php           — REST API route registration
│       └── settings/
│           └── settings-options/
│               └── table-list.php            — Module settings fields
└── js/
    └── admin-export-csv.js                   — CSV export with progress & cancellation

3. Admin Screens

3.1 Table Data List

URL wp-admin/admin.php?page=advan_table
Menu Position Sub-menu under “Error Logs” (position 7)
Capability manage_options
Controller Table_View::analytics_table_page()
List Table Table_List (extends Abstract_List)

UI Components

  • “Add New” button in page header (nonce-protected)
  • Searchable table dropdown – filters tables in real time, core tables marked with WordPress icon
  • “Info” button – opens table information modal (structure, indexes, foreign keys, health)
  • “CSV Export” button – exports table data with progress bar and cancel option
  • Search box – searches across all columns using LIKE %term%
  • Sortable columns – all columns sortable, default sort by primary key DESC
  • Row actions – View (modal) | Edit | Delete
  • Bulk actions – Delete selected rows
  • View modal – full row detail with copy-to-clipboard and share
  • Object cache notice – displays warning when external object cache detected
Screen layout:

 

┌──────────────────────────────────────────────────────────────┐
│  Table: wp_options (🔵)                       [Add New]       │
│──────────────────────────────────────────────────────────────│
│  [Table Dropdown ▼] [Info]  [CSV Export]       [🔍 Search]    │
│──────────────────────────────────────────────────────────────│
│  ☐ option_id ↕ | option_name     | option_value  | autoload  │
│     bigint(20)  | varchar(191)    | longtext      | varchar  │
│  ☐ 1           | siteurl          | https://...   | yes      │
│     View | Edit | Delete                                     │
│  ☐ 2           | home             | https://...   | yes      │
│     View | Edit | Delete                                     │
│──────────────────────────────────────────────────────────────│
│  Bulk Actions [▼] [Apply]                    ‹ 1 of 50 ›     │
└──────────────────────────────────────────────────────────────┘

 

3.2 Add New Row

URL wp-admin/admin.php?page=advan_table&action=add_table_data&show_table={name}
Form Action admin_post_advan_table_insert
Handler Table_View::insert_table()
Nonce advana_table_manager (form) + add-row (URL)

Form Generation

The form is dynamically generated by iterating over Common_Table::get_columns_info(). Auto-increment columns are automatically skipped. Each column’s MySQL type is inspected via regex to render the appropriate HTML input type.

3.3 Edit Row

URL wp-admin/admin.php?page=advan_table&action=edit_table_data&id={id}&show_table={name}
Form Action admin_post_advan_table_update
Handler Table_View::update_table()
Nonce advana_table_manager (form) + edit-row (URL)

Uses the same form field generation as Add New. Pre-fills values from Common_Table::load_row_data(). Displays a serialization warning notice before the form.

3.4 Module Settings

URL wp-admin/admin.php?page=advan_logs_settings
Settings File classes/vendor/settings/settings-options/table-list.php

Available Settings

Setting ID Type Description
Enable tables module tables_module_enabled checkbox Enables/disables the Table Viewer module. When disabled, the sub-menu is hidden and no table operations are accessible.

4. Core Classes

4.1 ADVAN\Lists\Table_List

Extends Abstract_List (which extends WP_List_Table). Handles the table data admin list rendering, column management, sorting, searching, pagination, bulk operations, CSV export, and table information modals.

Constants

PHP
<?php
public const PAGE_SLUG            = '{ADVAN_INNER_SLUG}_page_advan_table';
public const SWITCH_ACTION        = 'switch_advan_table';
public const SCREEN_OPTIONS_SLUG  = 'advanced_analytics_table_list';
public const SEARCH_INPUT         = 's';
public const TABLE_MENU_SLUG      = 'advan_table';
public const UPDATE_ACTION        = 'advan_table_update';
public const INSERT_ACTION        = 'advan_table_insert';
public const NONCE_NAME           = 'advana_table_manager';

Constructor

PHP
<?php
public function __construct( string $table_name )

Accepts a table name, initializes Common_Table with it, and calls the parent constructor with plural/singular labels set to the table name.

Key Methods

Method Description
hooks_init() Registers admin_post handlers for switch, update, and insert actions
menu_add() Registers the “Table viewer” submenu page under Error Logs (position 7)
process_actions_load() Runs on load-{hook} phase to handle bulk delete before output
prepare_items() Queries the database, populates rows, sets pagination; validates and allowlists orderby/order
fetch_table_data(array $args) Builds and executes SQL with search, sort, and pagination; counts total rows
get_columns() Returns columns from Common_Table::manage_columns()
get_sortable_columns() Makes all columns sortable (derived from column info)
column_default($item, $column_name) Renders cell — primary key column includes row actions; other columns truncate at 100 chars
column_cb($item) Renders checkbox for bulk selection
handle_table_actions() Processes bulk delete with nonce verification and redirect
extra_tablenav($which) Renders table dropdown, Info button, CSV Export button, and table info modal HTML

Column Rendering

  • Primary key column: Shows raw value + row actions (View, Edit, Delete)
  • Other columns: Values wrapped in <code> tags, truncated to 100 characters with […] indicator

4.2 ADVAN\Lists\Views\Table_View

Handles page rendering for all table screens (list, add, edit) and processes form submissions. All methods are static.

Public Static Methods

Method Description
analytics_table_page() Main page router — renders list, add form, or edit form based on action parameter. Enforces manage_options capability. Enqueues ThickBox, media-views, and wp-api-fetch.
switch_action() Handles table switching via the dropdown. Validates nonce (switch_advan_table), verifies table exists, and redirects.
page_load() Removes _wp_http_referer from URL on page load to keep URLs clean.
update_table() Processes row update form submission. Enforces manage_options, validates nonce, collects form data, calls Common_Table::insert_row_record() with $where for update, then redirects.
insert_table() Processes row insert form submission. Enforces manage_options, validates nonce, collects form data (skipping auto-increment), calls Common_Table::insert_row_record() without $where for insert, then redirects.
add_help_content_table() Returns help text for the Help tab in Screen Options.
add_config_content_table() Returns config panel with table metadata (engine, version, row format, row count, sizes, etc.) and Truncate/Drop buttons.

The View action triggers a REST API call via wp.apiFetch() to retrieve full row data. The response HTML is injected into the modal overlay. The modal also supports:

  • Copy to clipboard — copies raw HTML of row data via navigator.clipboard
  • Share — uses the navigator.share Web Share API (falls back gracefully)

4.3 ADVAN\Entities_Global\Common_Table

Central utility class for all database table operations. Handles table inspection, CRUD, schema analysis, health monitoring, and type-aware data normalization. All methods are static.

Constants

PHP
<?php
public const INT_TYPES = array(
    'TINYINT'   => 'TINYINT',
    'SMALLINT'  => 'SMALLINT',
    'MEDIUMINT' => 'MEDIUMINT',
    'INT'       => 'INT',
    'BIGINT'    => 'BIGINT',
    'BIT'       => 'BIT',
);

public const FLOAT_TYPES = array(
    'DECIMAL' => 'DECIMAL',
    'FLOAT'   => 'FLOAT',
    'DOUBLE'  => 'DOUBLE',
);

Properties

Property Type Description
$table_name string Currently active table name
$columns_info array Cached column metadata from DESC
$tables array Cached list of all database tables
$core_tables array Cached list of WordPress core tables
$real_id string Primary key column name (auto-detected)
$table_size int Cached table size in bytes
$table_stat array Cached SHOW TABLE STATUS result

Initialization & Table Discovery

Method Return Description
init(string $table_name) void Set the active table name for all subsequent operations
get_name() string Returns the current table name
check_table_exists(string $table_name, $connection) bool Verifies a table exists using SHOW TABLES
get_tables($connection) array Lists all tables in the database (cached)
get_wp_core_tables() array Returns WordPress core tables via $wpdb->tables('all')
get_default_table() string Returns {prefix}options as the default table
validate_table_name(string $name) bool Validates table name (alphanumeric + underscore only)

Column & Schema Inspection

Method Return Description
get_columns_info() array Returns column metadata via DESC {table} (cached)
get_column_names() array Returns column name list (Field values)
get_column_names_admin() array Returns column headers for admin list (Field + Type)
get_real_id_name() string Auto-detects primary key via SHOW KEYS, falls back to first index, then first column
check_column(...) bool Verifies column existence and optional type/null/key/default/extra match
manage_columns($columns) array Builds column array for WP_List_Table with cb checkbox prepended

CRUD Operations

Method Return Description
load_row_data($id) array|WP_Error Fetch single row by primary key value
delete_by_id(int $id) int|bool Delete row by ID using $wpdb->delete()
delete_data(array $data) int|bool Delete with arbitrary WHERE conditions
update_data(array $data) int|bool Update row using $wpdb->update()
insert_data(array $data) int|bool Insert row using $wpdb->insert()
find(array $data) array Query with WHERE conditions (uses cloned wpdb for process_fields())
insert_row_record($table_name, array $data, ?array $where) int|bool|WP_Error Smart insert/update with full column-type normalization (see Type Detection section)

Table Management

Method Return Description
drop_table($request, $table_name, $connection) WP_REST_Response|WP_Error Drop table (non-core only). Works via REST or direct call.
truncate_table($request, $table_name, $connection) WP_REST_Response|WP_Error Truncate table (non-core only). Works via REST or direct call.
optimize_table(string $table_name, $connection) array|WP_Error Runs OPTIMIZE TABLE to defragment. Returns status and message.
backup_table() void|WP_Error Creates a timestamped copy of the current table (CREATE TABLE ... LIKE)

Table Health & Information

Method Return Description
get_table_size() int Table size in bytes from information_schema (cached)
get_table_status() array Full SHOW TABLE STATUS result (cached)
get_table_info(string $table_name, $connection) array|WP_Error Comprehensive info: structure, indexes, foreign keys, health metrics

REST API Handlers

Method Return Description
extract_row_data(WP_REST_Request) WP_REST_Response|WP_Error Retrieves single row as formatted HTML table for the view modal

Utility Methods

Method Return Description
execute_query(string $query, $connection, ?array $args) array Execute raw SQL; optionally prepares with args
format_value_for_html($value) string Formats values for display: decodes JSON, unserializes PHP, pretty-prints arrays
prepare_full_where(array $where_clause, ...) array Builds parameterized WHERE clause from field data

5. Column Type Detection & Form Generation

Both the Add and Edit forms use regex-based column type detection to generate appropriate HTML input elements. The detection is performed inline in Table_View::analytics_table_page().

Type-to-Input Mapping

Regex Pattern Matches HTML Input
/int|decimal|float|double|real|bit|bool/i All numeric types <input type="number" step="any">
/char|varchar/i CHAR, VARCHAR <input type="text" maxlength="255">
/text|tinytext|mediumtext|longtext/i All text types <textarea rows="10">
/date$/i DATE <input type="date">
/datetime|timestamp/i DATETIME, TIMESTAMP <input type="datetime-local">
/time$/i TIME <input type="time">
/year/i YEAR <input type="number" min="1900" max="2100">
/enum\((.+)\)/i ENUM <select> with extracted options
/set\((.+)\)/i SET Multiple <input type="checkbox">
/json/i JSON <textarea> with JSON placeholder

insert_row_record() Type Normalization

The insert_row_record() method performs comprehensive type normalization when writing data. It inspects each column’s type and converts values accordingly:

  • Integer types — Cast to int, handle booleans as 0/1, use %d format
  • Float types — Cast to float, use %f format
  • Date/time types — Accept DateTime objects, Unix timestamps, or string dates; format to MySQL standard
  • JSON — Encode arrays/objects to JSON string
  • ENUM/SET — Validate against allowed values, reject invalid entries
  • BINARY/BLOB — Store binary data as-is; encode complex structures to base64
  • VARCHAR(n) — Enforce max length via mb_strcut() (UTF-8 safe)
  • Text/default — Cast to string; arrays/objects JSON-encoded
Insert vs Update: When $where is provided, insert_row_record() performs an UPDATE using $wpdb->update(). Without $where, it performs a REPLACE using $wpdb->replace().

6. REST API Endpoints

All endpoints are registered under the 0-day/v1 namespace. Every endpoint requires manage_options capability.

View Row Data GET

Route /0-day/v1/get_table_record/{table_name}/{id}/
Method GET
Handler Common_Table::extract_row_data()
Parameters
  • table_name (string, required) — target table
  • id (string, required) — primary key value
Response { success: true, mail_body: "<html>...", table_name: "wp_options" }

Truncate Table DELETE

Route /0-day/v1/truncate_table/{table_name}/
Method DELETE
Handler Common_Table::truncate_table()
Parameters table_name (string, required)
Response { success: true }
Errors 400 if core table, 403 if insufficient permissions

Drop Table DELETE

Route /0-day/v1/drop_table/{table_name}/
Method DELETE
Handler Common_Table::drop_table()
Parameters table_name (string, required)
Response { success: true }
Errors 400 if core table, 403 if insufficient permissions

7. Hooks & Actions

Admin Post Actions ACTION

Action Handler Description
admin_post_switch_advan_table Table_View::switch_action Switch to a different database table
admin_post_advan_table_update Table_View::update_table Update an existing row
admin_post_advan_table_insert Table_View::insert_table Insert a new row

WordPress Hooks Used ACTION

Hook Priority Description
load-{page_slug} 5 Processes bulk actions and table action redirects before output
load-{page_slug} default Removes _wp_http_referer from URL, adds common help tabs

8. Settings Reference

Settings are on the Tables Options tab within the main settings page.

PHP
<?php
// Check if the Table Viewer module is enabled
$enabled = Settings::get_option( 'tables_module_enabled' );

Settings Builder Usage

PHP
<?php
// How the settings are defined in table-list.php
Settings::build_option(
    array(
        'title' => esc_html__( 'Tables Options', '0-day-analytics' ),
        'id'    => 'options-settings-tab',
        'type'  => 'tab-title',
    )
);

Settings::build_option(
    array(
        'title' => esc_html__( 'Tables list options', '0-day-analytics' ),
        'id'    => 'table-settings-options',
        'type'  => 'header',
    )
);

Settings::build_option(
    array(
        'name'    => esc_html__( 'Enable tables module', '0-day-analytics' ),
        'id'      => 'tables_module_enabled',
        'type'    => 'checkbox',
        'hint'    => esc_html__( 'If you disable this, the entire plugin tables module will be disabled...', '0-day-analytics' ),
        'default' => Settings::get_option( 'tables_module_enabled' ),
    )
);

9. List Table Columns & Sorting

Columns

Columns are dynamically generated from the database schema of the selected table via Common_Table::get_column_names_admin(). Each column header displays the column name and its MySQL data type.

Key Header Sortable Description
cb No Bulk selection checkbox
Dynamic column_name + type Yes All columns from the table are shown and sortable

The search box filters across all columns using LIKE %term% for each column (OR logic). Query parameter: s

Default Sort

By primary key column in DESC order. The primary key is auto-detected via SHOW KEYS WHERE Key_name = 'PRIMARY', falling back to any index, then the first column.

Pagination

Default items per page: 20. Configurable via Screen Options. Uses LIMIT/OFFSET SQL pagination.

10. Bulk & Row Actions

Row Actions

Action Method Description
View REST API (AJAX modal) Opens modal showing full row data via wp.apiFetch()
Edit Page redirect Opens the Edit Row form with pre-filled values
Delete Page redirect Deletes the row after JavaScript confirm() dialog

Bulk Actions

Action Description
Delete Permanently delete all selected rows

Destructive Table Actions (Config Help Tab)

Action Method Core Tables Description
Truncate Table REST API (DELETE) Blocked Removes all rows, keeps structure. JavaScript confirm required.
Drop Table REST API (DELETE) Hidden Permanently removes table and data. JavaScript confirm required.
Optimize Table Info modal button Allowed Reclaims fragmented space via OPTIMIZE TABLE

11. Security Model

Capability Checks

  • manage_options enforced on: page rendering, row edit/delete/insert, table dropdown switch, bulk operations, REST API endpoints
  • Menu visibility optionally restricted by menu_admins_only setting

Nonce Verification

Context Nonce Action
Table switch switch_advan_table
Add row (URL) add-row
Edit row (URL) edit-row
Add/Edit form advana_table_manager
Bulk delete bulk-{table_name} (WP_List_Table auto-generated)

Input Validation

  • Table names — validated with /^[A-Za-z0-9_]+$/ regex to prevent cross-database references and SQL injection via dots/backticks
  • Order/orderby — allowlisted against actual column names; order restricted to ASC/DESC
  • Search terms — escaped via $wpdb->esc_like() and parameterized with %s
  • WHERE operators — restricted to allowlisted set: =, !=, >, <, LIKE, etc.
  • Form data — all values processed through wp_unslash() and type-normalized by insert_row_record()

Core Table Protections

  • WordPress core tables (via $wpdb->tables('all')) cannot be truncated or dropped
  • The “Drop Table” button is hidden for core tables in the Config help tab
  • REST API endpoints return WP_Error with 400 status for core table truncate/drop attempts

12. Code Examples

Example 1: Check If a Table Exists

PHP
<?php
use ADVAN\Entities_Global\Common_Table;

$table_name = 'wp_custom_logs';

if ( Common_Table::check_table_exists( $table_name ) ) {
    echo 'Table exists!';
} else {
    echo 'Table does not exist.';
}

Example 2: Get All Database Tables

PHP
<?php
use ADVAN\Entities_Global\Common_Table;

$all_tables  = Common_Table::get_tables();
$core_tables = Common_Table::get_wp_core_tables();

foreach ( $all_tables as $table ) {
    $is_core = in_array( $table, $core_tables, true ) ? '(core)' : '(custom)';
    echo $table . ' ' . $is_core . "\n";
}

Example 3: Inspect Table Column Schema

PHP
<?php
use ADVAN\Entities_Global\Common_Table;

Common_Table::init( 'wp_options' );

$columns = Common_Table::get_columns_info();

foreach ( $columns as $col ) {
    printf(
        "Column: %s | Type: %s | Null: %s | Key: %s | Default: %s | Extra: %s\n",
        $col['Field'],
        $col['Type'],
        $col['Null'],
        $col['Key'],
        $col['Default'] ?? 'NULL',
        $col['Extra']
    );
}

Example 4: Load a Single Row

PHP
<?php
use ADVAN\Entities_Global\Common_Table;

Common_Table::init( 'wp_options' );

$row = Common_Table::load_row_data( 1 );

if ( ! is_wp_error( $row ) ) {
    echo 'Option name: ' . $row['option_name'];
    echo 'Option value: ' . $row['option_value'];
}

Example 5: Insert a Row with Type Normalization

PHP
<?php
use ADVAN\Entities_Global\Common_Table;

$result = Common_Table::insert_row_record(
    'wp_options',
    array(
        'option_name'  => 'my_custom_option',
        'option_value' => 'hello world',
        'autoload'     => 'yes',
    )
);

if ( is_wp_error( $result ) ) {
    echo 'Error: ' . $result->get_error_message();
} elseif ( is_int( $result ) ) {
    echo 'Inserted row with ID: ' . $result;
}

Example 6: Update a Row

PHP
<?php
use ADVAN\Entities_Global\Common_Table;

$result = Common_Table::insert_row_record(
    'wp_options',
    array(
        'option_value' => 'updated value',
    ),
    array(
        'option_id' => 42,  // WHERE clause
    )
);

if ( true === $result ) {
    echo 'Row updated successfully.';
}

Example 7: Delete a Row

PHP
<?php
use ADVAN\Entities_Global\Common_Table;

Common_Table::init( 'wp_custom_logs' );

$deleted = Common_Table::delete_by_id( 123 );

if ( $deleted ) {
    echo 'Row deleted.';
}

Example 8: Get Table Health Information

PHP
<?php
use ADVAN\Entities_Global\Common_Table;

$info = Common_Table::get_table_info( 'wp_posts' );

if ( ! is_wp_error( $info ) ) {
    echo 'Row count: ' . $info['health']['row_count'];
    echo 'Data size: ' . size_format( $info['health']['data_size'] );
    echo 'Index size: ' . size_format( $info['health']['index_size'] );
    echo 'Needs optimization: ' . ( $info['health']['needs_optimization'] ? 'Yes' : 'No' );

    echo "\nColumns:\n";
    foreach ( $info['structure'] as $col ) {
        echo '  ' . $col['Field'] . ' — ' . $col['Type'] . "\n";
    }

    echo "\nIndexes:\n";
    foreach ( $info['indexes'] as $idx ) {
        echo '  ' . $idx['Key_name'] . ' on ' . $idx['Column_name'] . "\n";
    }
}

Example 9: Optimize a Table

PHP
<?php
use ADVAN\Entities_Global\Common_Table;

$result = Common_Table::optimize_table( 'wp_postmeta' );

if ( is_wp_error( $result ) ) {
    echo 'Optimization failed: ' . $result->get_error_message();
} else {
    echo 'Status: ' . $result['status'];
    echo 'Message: ' . $result['message'];
}

Example 10: Back Up a Table Before Modifications

PHP
<?php
use ADVAN\Entities_Global\Common_Table;

Common_Table::init( 'wp_custom_data' );

// Creates a copy named wp_custom_data{YmdHis}
Common_Table::backup_table();

// Now safe to perform destructive operations
Common_Table::truncate_table( null, 'wp_custom_data' );
Need User Guide documentation?
See Table Module User Guide for more details about configuration, practical usage and information.
← Table Module — User Guide WordPress Zero-Day Vulnerabilities: How to Detect and Monitor Threats with 0 Day Analytics →
Share this page
Back to top