I’ll build this as a practical inc/admin/system-status.php module for your RX theme: admin page, server/PHP/WordPress/theme checks, security/performance checks, copy/export tools, and safe recommendations.
Below is an advanced inc/admin/system-status.php file for your RX Theme. It creates a full System Status admin page inside WordPress with many useful checks: WordPress, PHP, server, database, theme, plugins, security, performance, REST API, uploads, memory, filesystem, debug status, caching, SSL, and export/copy report tools.
Create this file:
rx-theme/inc/admin/system-status.php
Then paste this code:
<?php
/**
* RX Theme - Advanced System Status
*
* File: inc/admin/system-status.php
*
* @package RX_Theme
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'RX_Theme_System_Status' ) ) :
final class RX_Theme_System_Status {
/**
* Menu slug.
*
* @var string
*/
const MENU_SLUG = 'rx-theme-system-status';
/**
* Minimum recommended PHP version.
*
* @var string
*/
const RECOMMENDED_PHP = '8.1';
/**
* Minimum recommended WordPress version.
*
* @var string
*/
const RECOMMENDED_WP = '6.4';
/**
* Recommended memory limit.
*
* @var int
*/
const RECOMMENDED_MEMORY_MB = 256;
/**
* Init hooks.
*/
public static function init() {
add_action( 'admin_menu', array( __CLASS__, 'register_menu' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_assets' ) );
add_action( 'admin_post_rx_system_status_download', array( __CLASS__, 'download_report' ) );
}
/**
* Register admin menu page.
*/
public static function register_menu() {
add_theme_page(
esc_html__( 'RX System Status', 'rx-theme' ),
esc_html__( 'RX System Status', 'rx-theme' ),
'manage_options',
self::MENU_SLUG,
array( __CLASS__, 'render_page' )
);
}
/**
* Admin CSS/JS.
*
* @param string $hook Current admin hook.
*/
public static function admin_assets( $hook ) {
if ( false === strpos( $hook, self::MENU_SLUG ) ) {
return;
}
wp_register_style( 'rx-system-status', false, array(), '1.0.0' );
wp_enqueue_style( 'rx-system-status' );
$css = '
.rx-status-wrap{max-width:1280px}
.rx-status-hero{background:#fff;border:1px solid #dcdcde;border-radius:12px;padding:22px;margin:18px 0;box-shadow:0 1px 2px rgba(0,0,0,.04)}
.rx-status-hero h1{margin:0 0 8px;font-size:26px}
.rx-status-hero p{font-size:14px;color:#50575e;margin:0}
.rx-status-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;margin:18px 0}
.rx-status-card{background:#fff;border:1px solid #dcdcde;border-radius:12px;padding:16px;min-height:92px}
.rx-status-card strong{display:block;font-size:24px;margin-bottom:6px}
.rx-status-card span{color:#646970}
.rx-status-section{background:#fff;border:1px solid #dcdcde;border-radius:12px;margin:18px 0;overflow:hidden}
.rx-status-section h2{margin:0;padding:14px 16px;border-bottom:1px solid #dcdcde;background:#f6f7f7;font-size:16px}
.rx-status-table{width:100%;border-collapse:collapse}
.rx-status-table th,.rx-status-table td{padding:12px 16px;border-bottom:1px solid #f0f0f1;text-align:left;vertical-align:top}
.rx-status-table th{width:280px;color:#1d2327;font-weight:600}
.rx-status-table tr:last-child th,.rx-status-table tr:last-child td{border-bottom:none}
.rx-badge{display:inline-flex;align-items:center;gap:5px;padding:4px 9px;border-radius:999px;font-size:12px;font-weight:600;line-height:1}
.rx-ok{background:#e7f7ed;color:#0a6b2b}
.rx-warn{background:#fff4d6;color:#8a5700}
.rx-bad{background:#ffe9e9;color:#b42318}
.rx-info{background:#eaf3ff;color:#135e96}
.rx-muted{color:#646970}
.rx-code{background:#f6f7f7;border:1px solid #dcdcde;border-radius:6px;padding:2px 6px;font-family:Consolas,Monaco,monospace}
.rx-actions{display:flex;gap:10px;flex-wrap:wrap;margin:18px 0}
#rx-status-report{width:100%;min-height:340px;font-family:Consolas,Monaco,monospace;font-size:12px;white-space:pre}
@media(max-width:1100px){.rx-status-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:700px){.rx-status-grid{grid-template-columns:1fr}.rx-status-table th,.rx-status-table td{display:block;width:auto}.rx-status-table th{padding-bottom:4px}.rx-status-table td{padding-top:4px}}
';
wp_add_inline_style( 'rx-system-status', $css );
wp_register_script( 'rx-system-status', false, array(), '1.0.0', true );
wp_enqueue_script( 'rx-system-status' );
$js = '
document.addEventListener("DOMContentLoaded", function(){
var btn = document.getElementById("rx-copy-status");
var area = document.getElementById("rx-status-report");
if(btn && area){
btn.addEventListener("click", function(e){
e.preventDefault();
area.select();
area.setSelectionRange(0, 999999);
try {
document.execCommand("copy");
btn.textContent = "Copied!";
setTimeout(function(){ btn.textContent = "Copy Report"; }, 1600);
} catch(err) {
alert("Copy failed. Please select and copy manually.");
}
});
}
});
';
wp_add_inline_script( 'rx-system-status', $js );
}
/**
* Render page.
*/
public static function render_page() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You do not have permission to view this page.', 'rx-theme' ) );
}
$status = self::get_status_data();
$score = self::calculate_score( $status );
$report = self::plain_text_report( $status );
?>
<div class="wrap rx-status-wrap">
<div class="rx-status-hero">
<h1><?php esc_html_e( 'RX Theme System Status', 'rx-theme' ); ?></h1>
<p>
<?php esc_html_e( 'A complete health report for WordPress, server, PHP, database, theme, security, performance, uploads, REST API, and filesystem.', 'rx-theme' ); ?>
</p>
</div>
<div class="rx-status-grid">
<?php self::summary_card( esc_html__( 'Health Score', 'rx-theme' ), $score . '%', self::score_badge( $score ) ); ?>
<?php self::summary_card( esc_html__( 'WordPress', 'rx-theme' ), $status['wordpress']['version']['value'], $status['wordpress']['version']['badge'] ); ?>
<?php self::summary_card( esc_html__( 'PHP', 'rx-theme' ), $status['server']['php_version']['value'], $status['server']['php_version']['badge'] ); ?>
<?php self::summary_card( esc_html__( 'Memory Limit', 'rx-theme' ), $status['server']['wp_memory_limit']['value'], $status['server']['wp_memory_limit']['badge'] ); ?>
</div>
<div class="rx-actions">
<a href="<?php echo esc_url( self::download_url() ); ?>" class="button button-primary">
<?php esc_html_e( 'Download Report', 'rx-theme' ); ?>
</a>
<button class="button" id="rx-copy-status">
<?php esc_html_e( 'Copy Report', 'rx-theme' ); ?>
</button>
</div>
<?php
self::render_section( esc_html__( 'WordPress Environment', 'rx-theme' ), $status['wordpress'] );
self::render_section( esc_html__( 'Server Environment', 'rx-theme' ), $status['server'] );
self::render_section( esc_html__( 'Database Status', 'rx-theme' ), $status['database'] );
self::render_section( esc_html__( 'Theme Status', 'rx-theme' ), $status['theme'] );
self::render_section( esc_html__( 'Plugin Status', 'rx-theme' ), $status['plugins'] );
self::render_section( esc_html__( 'Security Status', 'rx-theme' ), $status['security'] );
self::render_section( esc_html__( 'Performance Status', 'rx-theme' ), $status['performance'] );
self::render_section( esc_html__( 'Filesystem and Uploads', 'rx-theme' ), $status['filesystem'] );
self::render_section( esc_html__( 'WordPress REST API and Cron', 'rx-theme' ), $status['api_cron'] );
self::render_section( esc_html__( 'Recommended PHP Extensions', 'rx-theme' ), $status['extensions'] );
?>
<div class="rx-status-section">
<h2><?php esc_html_e( 'Plain Text Report', 'rx-theme' ); ?></h2>
<div style="padding:16px;">
<textarea id="rx-status-report" readonly><?php echo esc_textarea( $report ); ?></textarea>
</div>
</div>
</div>
<?php
}
/**
* Summary card.
*
* @param string $title Title.
* @param string $value Value.
* @param string $badge Badge HTML.
*/
private static function summary_card( $title, $value, $badge ) {
?>
<div class="rx-status-card">
<strong><?php echo esc_html( $value ); ?></strong>
<span><?php echo esc_html( $title ); ?></span>
<div style="margin-top:10px;"><?php echo wp_kses_post( $badge ); ?></div>
</div>
<?php
}
/**
* Render status section.
*
* @param string $title Section title.
* @param array $items Items.
*/
private static function render_section( $title, $items ) {
?>
<div class="rx-status-section">
<h2><?php echo esc_html( $title ); ?></h2>
<table class="rx-status-table">
<tbody>
<?php foreach ( $items as $label => $item ) : ?>
<tr>
<th><?php echo esc_html( $item['label'] ); ?></th>
<td>
<?php echo wp_kses_post( $item['badge'] ); ?>
<span style="margin-left:8px;"><?php echo wp_kses_post( $item['value'] ); ?></span>
<?php if ( ! empty( $item['note'] ) ) : ?>
<div class="rx-muted" style="margin-top:6px;"><?php echo wp_kses_post( $item['note'] ); ?></div>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php
}
/**
* Get all system status data.
*
* @return array
*/
private static function get_status_data() {
global $wpdb;
$theme = wp_get_theme();
$parent = $theme->parent();
$uploads = wp_upload_dir();
$wp_memory = self::size_to_mb( WP_MEMORY_LIMIT );
$php_memory = self::size_to_mb( ini_get( 'memory_limit' ) );
$max_upload = size_format( wp_max_upload_size() );
$db_version = ! empty( $wpdb->db_version() ) ? $wpdb->db_version() : 'Unknown';
$data = array();
$data['wordpress'] = array(
'home_url' => self::item(
__( 'Home URL', 'rx-theme' ),
esc_url( home_url() ),
'info'
),
'site_url' => self::item(
__( 'Site URL', 'rx-theme' ),
esc_url( site_url() ),
'info'
),
'version' => self::item(
__( 'WordPress Version', 'rx-theme' ),
get_bloginfo( 'version' ),
version_compare( get_bloginfo( 'version' ), self::RECOMMENDED_WP, '>=' ) ? 'ok' : 'warn',
sprintf(
esc_html__( 'Recommended: WordPress %s or higher.', 'rx-theme' ),
self::RECOMMENDED_WP
)
),
'multisite' => self::item(
__( 'Multisite', 'rx-theme' ),
is_multisite() ? __( 'Enabled', 'rx-theme' ) : __( 'Disabled', 'rx-theme' ),
is_multisite() ? 'info' : 'ok'
),
'language' => self::item(
__( 'Site Language', 'rx-theme' ),
get_locale(),
'info'
),
'timezone' => self::item(
__( 'Timezone', 'rx-theme' ),
wp_timezone_string() ? wp_timezone_string() : 'UTC',
'info'
),
'debug' => self::item(
__( 'WP_DEBUG', 'rx-theme' ),
defined( 'WP_DEBUG' ) && WP_DEBUG ? __( 'Enabled', 'rx-theme' ) : __( 'Disabled', 'rx-theme' ),
defined( 'WP_DEBUG' ) && WP_DEBUG ? 'warn' : 'ok',
defined( 'WP_DEBUG' ) && WP_DEBUG ? __( 'Disable debug mode on production websites.', 'rx-theme' ) : ''
),
'debug_log' => self::item(
__( 'WP_DEBUG_LOG', 'rx-theme' ),
defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ? __( 'Enabled', 'rx-theme' ) : __( 'Disabled', 'rx-theme' ),
defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ? 'warn' : 'ok'
),
'script_debug' => self::item(
__( 'SCRIPT_DEBUG', 'rx-theme' ),
defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? __( 'Enabled', 'rx-theme' ) : __( 'Disabled', 'rx-theme' ),
defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'warn' : 'ok'
),
);
$data['server'] = array(
'php_version' => self::item(
__( 'PHP Version', 'rx-theme' ),
PHP_VERSION,
version_compare( PHP_VERSION, self::RECOMMENDED_PHP, '>=' ) ? 'ok' : 'warn',
sprintf(
esc_html__( 'Recommended: PHP %s or higher.', 'rx-theme' ),
self::RECOMMENDED_PHP
)
),
'server_software' => self::item(
__( 'Server Software', 'rx-theme' ),
isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : 'Unknown',
'info'
),
'wp_memory_limit' => self::item(
__( 'WordPress Memory Limit', 'rx-theme' ),
WP_MEMORY_LIMIT,
$wp_memory >= self::RECOMMENDED_MEMORY_MB ? 'ok' : 'warn',
sprintf(
esc_html__( 'Recommended: %dMB or higher.', 'rx-theme' ),
self::RECOMMENDED_MEMORY_MB
)
),
'php_memory_limit' => self::item(
__( 'PHP Memory Limit', 'rx-theme' ),
ini_get( 'memory_limit' ),
$php_memory >= self::RECOMMENDED_MEMORY_MB || -1 === (int) ini_get( 'memory_limit' ) ? 'ok' : 'warn'
),
'max_execution_time' => self::item(
__( 'Max Execution Time', 'rx-theme' ),
ini_get( 'max_execution_time' ) . ' seconds',
(int) ini_get( 'max_execution_time' ) >= 60 || 0 === (int) ini_get( 'max_execution_time' ) ? 'ok' : 'warn',
__( 'Recommended: 60 seconds or more for large imports and updates.', 'rx-theme' )
),
'max_input_vars' => self::item(
__( 'Max Input Vars', 'rx-theme' ),
ini_get( 'max_input_vars' ),
(int) ini_get( 'max_input_vars' ) >= 3000 ? 'ok' : 'warn',
__( 'Recommended: 3000 or higher for large option panels.', 'rx-theme' )
),
'post_max_size' => self::item(
__( 'Post Max Size', 'rx-theme' ),
ini_get( 'post_max_size' ),
self::size_to_mb( ini_get( 'post_max_size' ) ) >= 64 ? 'ok' : 'warn'
),
'upload_max_filesize' => self::item(
__( 'Upload Max Filesize', 'rx-theme' ),
ini_get( 'upload_max_filesize' ),
self::size_to_mb( ini_get( 'upload_max_filesize' ) ) >= 64 ? 'ok' : 'warn'
),
'wp_max_upload_size' => self::item(
__( 'WordPress Max Upload Size', 'rx-theme' ),
$max_upload,
'ok'
),
'curl_version' => self::item(
__( 'cURL Version', 'rx-theme' ),
function_exists( 'curl_version' ) ? curl_version()['version'] : __( 'Not available', 'rx-theme' ),
function_exists( 'curl_version' ) ? 'ok' : 'bad'
),
);
$data['database'] = array(
'db_extension' => self::item(
__( 'Database Extension', 'rx-theme' ),
$wpdb->use_mysqli ? 'mysqli' : 'mysql',
$wpdb->use_mysqli ? 'ok' : 'warn'
),
'db_server' => self::item(
__( 'Database Server Version', 'rx-theme' ),
$db_version,
'info'
),
'db_charset' => self::item(
__( 'Database Charset', 'rx-theme' ),
DB_CHARSET,
'ok'
),
'db_collate' => self::item(
__( 'Database Collate', 'rx-theme' ),
defined( 'DB_COLLATE' ) && DB_COLLATE ? DB_COLLATE : __( 'Default', 'rx-theme' ),
'info'
),
'table_prefix' => self::item(
__( 'Table Prefix', 'rx-theme' ),
$wpdb->prefix,
'wp_' === $wpdb->prefix ? 'warn' : 'ok',
'wp_' === $wpdb->prefix ? __( 'For security, a custom table prefix is better than the default wp_.', 'rx-theme' ) : ''
),
);
$data['theme'] = array(
'name' => self::item(
__( 'Active Theme', 'rx-theme' ),
$theme->get( 'Name' ),
'ok'
),
'version' => self::item(
__( 'Theme Version', 'rx-theme' ),
$theme->get( 'Version' ) ? $theme->get( 'Version' ) : __( 'No version set', 'rx-theme' ),
$theme->get( 'Version' ) ? 'ok' : 'warn'
),
'author' => self::item(
__( 'Theme Author', 'rx-theme' ),
$theme->get( 'Author' ) ? wp_kses_post( $theme->get( 'Author' ) ) : __( 'Unknown', 'rx-theme' ),
'info'
),
'template' => self::item(
__( 'Template Directory', 'rx-theme' ),
get_template_directory(),
is_readable( get_template_directory() ) ? 'ok' : 'bad'
),
'stylesheet' => self::item(
__( 'Stylesheet Directory', 'rx-theme' ),
get_stylesheet_directory(),
is_readable( get_stylesheet_directory() ) ? 'ok' : 'bad'
),
'child_theme' => self::item(
__( 'Child Theme', 'rx-theme' ),
is_child_theme() ? __( 'Active', 'rx-theme' ) : __( 'Not active', 'rx-theme' ),
is_child_theme() ? 'ok' : 'info'
),
'parent_theme' => self::item(
__( 'Parent Theme', 'rx-theme' ),
$parent ? $parent->get( 'Name' ) . ' ' . $parent->get( 'Version' ) : __( 'None', 'rx-theme' ),
$parent ? 'ok' : 'info'
),
);
$active_plugins = (array) get_option( 'active_plugins', array() );
$all_plugins = self::safe_get_plugins();
$data['plugins'] = array(
'total_plugins' => self::item(
__( 'Total Plugins', 'rx-theme' ),
count( $all_plugins ),
'info'
),
'active_plugins' => self::item(
__( 'Active Plugins', 'rx-theme' ),
count( $active_plugins ),
count( $active_plugins ) <= 35 ? 'ok' : 'warn',
count( $active_plugins ) > 35 ? __( 'Too many active plugins may reduce speed and increase conflict risk.', 'rx-theme' ) : ''
),
'must_use_plugins' => self::item(
__( 'Must-Use Plugins', 'rx-theme' ),
count( self::safe_get_mu_plugins() ),
'info'
),
'dropins' => self::item(
__( 'Drop-ins', 'rx-theme' ),
count( self::safe_get_dropins() ),
'info'
),
);
$data['security'] = array(
'ssl' => self::item(
__( 'HTTPS / SSL', 'rx-theme' ),
is_ssl() ? __( 'Enabled', 'rx-theme' ) : __( 'Not detected', 'rx-theme' ),
is_ssl() ? 'ok' : 'bad',
is_ssl() ? '' : __( 'Use HTTPS for better security and SEO.', 'rx-theme' )
),
'file_edit' => self::item(
__( 'Theme/Plugin File Editor', 'rx-theme' ),
defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ? __( 'Disabled', 'rx-theme' ) : __( 'Enabled', 'rx-theme' ),
defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ? 'ok' : 'warn',
defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ? '' : __( 'Recommended: define DISALLOW_FILE_EDIT as true in wp-config.php.', 'rx-theme' )
),
'xmlrpc' => self::item(
__( 'XML-RPC', 'rx-theme' ),
apply_filters( 'xmlrpc_enabled', true ) ? __( 'Enabled', 'rx-theme' ) : __( 'Disabled', 'rx-theme' ),
apply_filters( 'xmlrpc_enabled', true ) ? 'warn' : 'ok',
apply_filters( 'xmlrpc_enabled', true ) ? __( 'If you do not use XML-RPC, consider disabling it for security.', 'rx-theme' ) : ''
),
'wp_version_visible' => self::item(
__( 'WordPress Generator Tag', 'rx-theme' ),
has_action( 'wp_head', 'wp_generator' ) ? __( 'Visible', 'rx-theme' ) : __( 'Hidden', 'rx-theme' ),
has_action( 'wp_head', 'wp_generator' ) ? 'warn' : 'ok'
),
'debug_display' => self::item(
__( 'Display Errors', 'rx-theme' ),
ini_get( 'display_errors' ) ? __( 'Enabled', 'rx-theme' ) : __( 'Disabled', 'rx-theme' ),
ini_get( 'display_errors' ) ? 'warn' : 'ok'
),
);
$data['performance'] = array(
'object_cache' => self::item(
__( 'Object Cache', 'rx-theme' ),
wp_using_ext_object_cache() ? __( 'External object cache active', 'rx-theme' ) : __( 'Default WordPress object cache', 'rx-theme' ),
wp_using_ext_object_cache() ? 'ok' : 'info'
),
'page_cache_plugin' => self::item(
__( 'Advanced Cache Drop-in', 'rx-theme' ),
defined( 'WP_CACHE' ) && WP_CACHE ? __( 'WP_CACHE enabled', 'rx-theme' ) : __( 'WP_CACHE not enabled', 'rx-theme' ),
defined( 'WP_CACHE' ) && WP_CACHE ? 'ok' : 'warn',
defined( 'WP_CACHE' ) && WP_CACHE ? '' : __( 'For production websites, use page caching or server-level caching.', 'rx-theme' )
),
'cron_disabled' => self::item(
__( 'DISABLE_WP_CRON', 'rx-theme' ),
defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ? __( 'Enabled', 'rx-theme' ) : __( 'Disabled', 'rx-theme' ),
defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ? 'info' : 'ok'
),
'concatenate_scripts' => self::item(
__( 'CONCATENATE_SCRIPTS', 'rx-theme' ),
defined( 'CONCATENATE_SCRIPTS' ) ? ( CONCATENATE_SCRIPTS ? 'true' : 'false' ) : __( 'Default', 'rx-theme' ),
'info'
),
'gzip' => self::item(
__( 'zlib.output_compression', 'rx-theme' ),
ini_get( 'zlib.output_compression' ) ? __( 'Enabled', 'rx-theme' ) : __( 'Disabled or server-managed', 'rx-theme' ),
'info'
),
);
$data['filesystem'] = array(
'filesystem_method' => self::item(
__( 'Filesystem Method', 'rx-theme' ),
self::filesystem_method(),
'ok'
),
'uploads_dir' => self::item(
__( 'Uploads Directory', 'rx-theme' ),
$uploads['basedir'],
wp_is_writable( $uploads['basedir'] ) ? 'ok' : 'bad',
wp_is_writable( $uploads['basedir'] ) ? '' : __( 'Uploads directory must be writable.', 'rx-theme' )
),
'uploads_url' => self::item(
__( 'Uploads URL', 'rx-theme' ),
esc_url( $uploads['baseurl'] ),
'info'
),
'theme_writable' => self::item(
__( 'Theme Directory Writable', 'rx-theme' ),
wp_is_writable( get_stylesheet_directory() ) ? __( 'Writable', 'rx-theme' ) : __( 'Not writable', 'rx-theme' ),
wp_is_writable( get_stylesheet_directory() ) ? 'warn' : 'ok',
wp_is_writable( get_stylesheet_directory() ) ? __( 'For security, theme folders usually should not be writable by PHP unless needed.', 'rx-theme' ) : ''
),
'log_file' => self::item(
__( 'Debug Log File', 'rx-theme' ),
file_exists( WP_CONTENT_DIR . '/debug.log' ) ? __( 'Exists', 'rx-theme' ) : __( 'Not found', 'rx-theme' ),
file_exists( WP_CONTENT_DIR . '/debug.log' ) ? 'warn' : 'ok'
),
);
$rest_status = self::check_rest_api();
$data['api_cron'] = array(
'rest_api' => self::item(
__( 'REST API', 'rx-theme' ),
$rest_status['message'],
$rest_status['status']
),
'loopback' => self::item(
__( 'Loopback Requests', 'rx-theme' ),
self::check_loopback(),
'info'
),
'cron_event_count' => self::item(
__( 'Scheduled Cron Events', 'rx-theme' ),
self::count_cron_events(),
'ok'
),
'alternate_cron' => self::item(
__( 'ALTERNATE_WP_CRON', 'rx-theme' ),
defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ? __( 'Enabled', 'rx-theme' ) : __( 'Disabled', 'rx-theme' ),
'info'
),
);
$data['extensions'] = self::php_extensions_status();
return $data;
}
/**
* Make a status item.
*
* @param string $label Label.
* @param string $value Value.
* @param string $status ok|warn|bad|info.
* @param string $note Note.
*
* @return array
*/
private static function item( $label, $value, $status = 'info', $note = '' ) {
return array(
'label' => $label,
'value' => is_scalar( $value ) ? (string) $value : wp_json_encode( $value ),
'status' => $status,
'badge' => self::badge( $status ),
'note' => $note,
);
}
/**
* Badge HTML.
*
* @param string $status Status.
*
* @return string
*/
private static function badge( $status ) {
$map = array(
'ok' => array( 'class' => 'rx-ok', 'text' => __( 'Good', 'rx-theme' ) ),
'warn' => array( 'class' => 'rx-warn', 'text' => __( 'Warning', 'rx-theme' ) ),
'bad' => array( 'class' => 'rx-bad', 'text' => __( 'Critical', 'rx-theme' ) ),
'info' => array( 'class' => 'rx-info', 'text' => __( 'Info', 'rx-theme' ) ),
);
$item = isset( $map[ $status ] ) ? $map[ $status ] : $map['info'];
return sprintf(
'<span class="rx-badge %1$s">%2$s</span>',
esc_attr( $item['class'] ),
esc_html( $item['text'] )
);
}
/**
* Score badge.
*
* @param int $score Score.
*
* @return string
*/
private static function score_badge( $score ) {
if ( $score >= 85 ) {
return self::badge( 'ok' );
}
if ( $score >= 65 ) {
return self::badge( 'warn' );
}
return self::badge( 'bad' );
}
/**
* Calculate system score.
*
* @param array $status Status data.
*
* @return int
*/
private static function calculate_score( $status ) {
$total = 0;
$good = 0;
foreach ( $status as $section ) {
foreach ( $section as $item ) {
$total++;
if ( 'ok' === $item['status'] ) {
$good++;
} elseif ( 'info' === $item['status'] ) {
$good += 0.8;
} elseif ( 'warn' === $item['status'] ) {
$good += 0.45;
}
}
}
if ( 0 === $total ) {
return 0;
}
return (int) round( ( $good / $total ) * 100 );
}
/**
* Convert memory size to MB.
*
* @param string $size Size.
*
* @return int
*/
private static function size_to_mb( $size ) {
$size = trim( (string) $size );
if ( '-1' === $size ) {
return -1;
}
$unit = strtolower( substr( $size, -1 ) );
$value = (float) $size;
switch ( $unit ) {
case 'g':
$value *= 1024;
break;
case 'k':
$value /= 1024;
break;
case 'm':
default:
break;
}
return (int) round( $value );
}
/**
* Safe get plugins.
*
* @return array
*/
private static function safe_get_plugins() {
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
return function_exists( 'get_plugins' ) ? get_plugins() : array();
}
/**
* Safe get MU plugins.
*
* @return array
*/
private static function safe_get_mu_plugins() {
if ( ! function_exists( 'get_mu_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
return function_exists( 'get_mu_plugins' ) ? get_mu_plugins() : array();
}
/**
* Safe get dropins.
*
* @return array
*/
private static function safe_get_dropins() {
if ( ! function_exists( 'get_dropins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
return function_exists( 'get_dropins' ) ? get_dropins() : array();
}
/**
* Filesystem method.
*
* @return string
*/
private static function filesystem_method() {
if ( ! function_exists( 'get_filesystem_method' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
return get_filesystem_method();
}
/**
* Check REST API.
*
* @return array
*/
private static function check_rest_api() {
$url = rest_url();
$response = wp_remote_get(
$url,
array(
'timeout' => 8,
'sslverify' => false,
)
);
if ( is_wp_error( $response ) ) {
return array(
'status' => 'bad',
'message' => $response->get_error_message(),
);
}
$code = wp_remote_retrieve_response_code( $response );
if ( $code >= 200 && $code < 300 ) {
return array(
'status' => 'ok',
'message' => sprintf( 'Working. HTTP %d', $code ),
);
}
return array(
'status' => 'warn',
'message' => sprintf( 'Unexpected response. HTTP %d', $code ),
);
}
/**
* Check loopback request.
*
* @return string
*/
private static function check_loopback() {
$response = wp_remote_get(
home_url( '/' ),
array(
'timeout' => 8,
'sslverify' => false,
)
);
if ( is_wp_error( $response ) ) {
return $response->get_error_message();
}
return 'HTTP ' . wp_remote_retrieve_response_code( $response );
}
/**
* Count cron events.
*
* @return int
*/
private static function count_cron_events() {
$cron = _get_cron_array();
$count = 0;
if ( empty( $cron ) || ! is_array( $cron ) ) {
return 0;
}
foreach ( $cron as $timestamp => $hooks ) {
foreach ( $hooks as $hook => $events ) {
$count += count( $events );
}
}
return $count;
}
/**
* PHP extension status.
*
* @return array
*/
private static function php_extensions_status() {
$extensions = array(
'curl' => __( 'cURL', 'rx-theme' ),
'dom' => __( 'DOM', 'rx-theme' ),
'exif' => __( 'EXIF', 'rx-theme' ),
'fileinfo' => __( 'Fileinfo', 'rx-theme' ),
'gd' => __( 'GD Image Library', 'rx-theme' ),
'imagick' => __( 'Imagick', 'rx-theme' ),
'intl' => __( 'Intl', 'rx-theme' ),
'json' => __( 'JSON', 'rx-theme' ),
'mbstring' => __( 'Mbstring', 'rx-theme' ),
'mysqli' => __( 'MySQLi', 'rx-theme' ),
'openssl' => __( 'OpenSSL', 'rx-theme' ),
'zip' => __( 'Zip', 'rx-theme' ),
);
$items = array();
foreach ( $extensions as $ext => $label ) {
$loaded = extension_loaded( $ext );
$items[ $ext ] = self::item(
$label,
$loaded ? __( 'Loaded', 'rx-theme' ) : __( 'Missing', 'rx-theme' ),
$loaded ? 'ok' : ( 'imagick' === $ext ? 'warn' : 'bad' ),
! $loaded ? __( 'Ask your hosting provider to enable this PHP extension if your site needs it.', 'rx-theme' ) : ''
);
}
return $items;
}
/**
* Download URL.
*
* @return string
*/
private static function download_url() {
return wp_nonce_url(
admin_url( 'admin-post.php?action=rx_system_status_download' ),
'rx_system_status_download'
);
}
/**
* Download report.
*/
public static function download_report() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Permission denied.', 'rx-theme' ) );
}
check_admin_referer( 'rx_system_status_download' );
$status = self::get_status_data();
$report = self::plain_text_report( $status );
nocache_headers();
header( 'Content-Type: text/plain; charset=utf-8' );
header( 'Content-Disposition: attachment; filename=rx-theme-system-status-' . gmdate( 'Y-m-d-H-i-s' ) . '.txt' );
echo $report; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
exit;
}
/**
* Plain text report.
*
* @param array $status Status data.
*
* @return string
*/
private static function plain_text_report( $status ) {
$lines = array();
$lines[] = 'RX THEME SYSTEM STATUS REPORT';
$lines[] = 'Generated: ' . gmdate( 'Y-m-d H:i:s' ) . ' UTC';
$lines[] = 'Site: ' . home_url();
$lines[] = str_repeat( '=', 70 );
foreach ( $status as $section_key => $section ) {
$lines[] = '';
$lines[] = strtoupper( str_replace( '_', ' ', $section_key ) );
$lines[] = str_repeat( '-', 70 );
foreach ( $section as $item ) {
$value = wp_strip_all_tags( $item['value'] );
$note = ! empty( $item['note'] ) ? ' | Note: ' . wp_strip_all_tags( $item['note'] ) : '';
$lines[] = sprintf(
'%s: %s [%s]%s',
$item['label'],
$value,
strtoupper( $item['status'] ),
$note
);
}
}
return implode( "\n", $lines );
}
}
RX_Theme_System_Status::init();
endif;
Now load it from your theme functions.php:
/**
* RX Theme Admin System Status.
*/
if ( is_admin() ) {
$rx_system_status_file = get_template_directory() . '/inc/admin/system-status.php';
if ( file_exists( $rx_system_status_file ) ) {
require_once $rx_system_status_file;
}
}
After adding it, go to:
WordPress Dashboard → Appearance → RX System Status
This page will show a complete health report for your RX theme and hosting environment.