dashboard-widgets.php

I’ll build this as a full theme admin dashboard widgets module: site overview, theme status, performance hints, security checks, quick links, system info, recent content, and optional admin notices.

Below is a large advanced inc/admin/dashboard-widgets.php file for your RX Theme. It adds many useful WordPress admin dashboard widgets: theme status, site overview, performance, security, SEO, recent content, system info, quick actions, cleanup links, and developer notes.

Create this file:

rx-theme/inc/admin/dashboard-widgets.php

Then paste this full code:

<?php
/**
 * RX Theme - Advanced Admin Dashboard Widgets
 *
 * File: inc/admin/dashboard-widgets.php
 *
 * Adds professional custom dashboard widgets for the RX Theme:
 * - RX Theme Overview
 * - Site Health Summary
 * - SEO Status
 * - Performance Checks
 * - Security Checks
 * - Recent Content
 * - Quick Admin Actions
 * - Server/System Info
 * - Developer Notes
 *
 * @package RX_Theme
 */

defined( 'ABSPATH' ) || exit;

if ( ! class_exists( 'RX_Theme_Dashboard_Widgets' ) ) :

final class RX_Theme_Dashboard_Widgets {

	/**
	 * Capability required to view RX dashboard widgets.
	 *
	 * @var string
	 */
	private static $capability = 'manage_options';

	/**
	 * Initialize hooks.
	 */
	public static function init() {
		add_action( 'wp_dashboard_setup', array( __CLASS__, 'register_dashboard_widgets' ) );
		add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_admin_assets' ) );
		add_action( 'admin_init', array( __CLASS__, 'handle_quick_actions' ) );
		add_action( 'wp_ajax_rx_theme_clear_dashboard_cache', array( __CLASS__, 'ajax_clear_dashboard_cache' ) );

		add_filter( 'dashboard_glance_items', array( __CLASS__, 'add_glance_items' ) );
	}

	/**
	 * Register all dashboard widgets.
	 */
	public static function register_dashboard_widgets() {
		if ( ! current_user_can( self::$capability ) ) {
			return;
		}

		wp_add_dashboard_widget(
			'rx_theme_overview_widget',
			esc_html__( 'RX Theme Overview', 'rx-theme' ),
			array( __CLASS__, 'render_theme_overview_widget' )
		);

		wp_add_dashboard_widget(
			'rx_site_health_widget',
			esc_html__( 'RX Site Health Summary', 'rx-theme' ),
			array( __CLASS__, 'render_site_health_widget' )
		);

		wp_add_dashboard_widget(
			'rx_seo_status_widget',
			esc_html__( 'RX SEO Status', 'rx-theme' ),
			array( __CLASS__, 'render_seo_status_widget' )
		);

		wp_add_dashboard_widget(
			'rx_performance_widget',
			esc_html__( 'RX Performance Checks', 'rx-theme' ),
			array( __CLASS__, 'render_performance_widget' )
		);

		wp_add_dashboard_widget(
			'rx_security_widget',
			esc_html__( 'RX Security Checks', 'rx-theme' ),
			array( __CLASS__, 'render_security_widget' )
		);

		wp_add_dashboard_widget(
			'rx_recent_content_widget',
			esc_html__( 'RX Recent Content', 'rx-theme' ),
			array( __CLASS__, 'render_recent_content_widget' )
		);

		wp_add_dashboard_widget(
			'rx_quick_actions_widget',
			esc_html__( 'RX Quick Actions', 'rx-theme' ),
			array( __CLASS__, 'render_quick_actions_widget' )
		);

		wp_add_dashboard_widget(
			'rx_system_info_widget',
			esc_html__( 'RX System Information', 'rx-theme' ),
			array( __CLASS__, 'render_system_info_widget' )
		);

		wp_add_dashboard_widget(
			'rx_developer_notes_widget',
			esc_html__( 'RX Developer Notes', 'rx-theme' ),
			array( __CLASS__, 'render_developer_notes_widget' )
		);
	}

	/**
	 * Admin CSS and JavaScript.
	 */
	public static function enqueue_admin_assets( $hook ) {
		if ( 'index.php' !== $hook ) {
			return;
		}

		$css = '
			.rx-dashboard-wrap {
				font-size: 13px;
				line-height: 1.6;
			}
			.rx-dashboard-grid {
				display: grid;
				grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
				gap: 10px;
				margin-top: 10px;
			}
			.rx-dashboard-card {
				background: #fff;
				border: 1px solid #dcdcde;
				border-radius: 8px;
				padding: 12px;
			}
			.rx-dashboard-card h4 {
				margin: 0 0 6px;
				font-size: 13px;
			}
			.rx-dashboard-value {
				font-size: 22px;
				font-weight: 700;
				margin: 3px 0;
			}
			.rx-status {
				display: inline-flex;
				align-items: center;
				gap: 6px;
				padding: 3px 8px;
				border-radius: 999px;
				font-size: 12px;
				font-weight: 600;
			}
			.rx-status-good {
				background: #edfaef;
				color: #0a6b22;
			}
			.rx-status-warning {
				background: #fff8e5;
				color: #8a5a00;
			}
			.rx-status-danger {
				background: #fdecec;
				color: #9d1c1c;
			}
			.rx-status-info {
				background: #eef6ff;
				color: #005a9e;
			}
			.rx-dashboard-list {
				margin: 10px 0 0;
			}
			.rx-dashboard-list li {
				display: flex;
				justify-content: space-between;
				gap: 10px;
				border-bottom: 1px solid #f0f0f1;
				padding: 7px 0;
				margin: 0;
			}
			.rx-dashboard-list li:last-child {
				border-bottom: 0;
			}
			.rx-dashboard-actions {
				display: flex;
				flex-wrap: wrap;
				gap: 8px;
				margin-top: 10px;
			}
			.rx-dashboard-actions .button {
				margin: 0;
			}
			.rx-muted {
				color: #646970;
			}
			.rx-small {
				font-size: 12px;
			}
			.rx-code {
				font-family: Consolas, Monaco, monospace;
				background: #f6f7f7;
				border: 1px solid #dcdcde;
				padding: 2px 5px;
				border-radius: 4px;
			}
			.rx-progress {
				height: 8px;
				background: #f0f0f1;
				border-radius: 20px;
				overflow: hidden;
				margin-top: 6px;
			}
			.rx-progress span {
				display: block;
				height: 100%;
				background: #2271b1;
			}
		';

		wp_register_style( 'rx-dashboard-widgets', false, array(), self::theme_version() );
		wp_enqueue_style( 'rx-dashboard-widgets' );
		wp_add_inline_style( 'rx-dashboard-widgets', $css );

		$js = '
			(function($){
				$(document).on("click", ".rx-clear-dashboard-cache", function(e){
					e.preventDefault();

					var $button = $(this);
					var oldText = $button.text();

					$button.text("Clearing...").prop("disabled", true);

					$.post(ajaxurl, {
						action: "rx_theme_clear_dashboard_cache",
						nonce: $button.data("nonce")
					}).done(function(response){
						if (response && response.success) {
							$button.text("Cache Cleared");
							setTimeout(function(){ location.reload(); }, 700);
						} else {
							$button.text("Failed");
						}
					}).fail(function(){
						$button.text("Failed");
					}).always(function(){
						setTimeout(function(){
							$button.text(oldText).prop("disabled", false);
						}, 1500);
					});
				});
			})(jQuery);
		';

		wp_register_script( 'rx-dashboard-widgets', false, array( 'jquery' ), self::theme_version(), true );
		wp_enqueue_script( 'rx-dashboard-widgets' );
		wp_add_inline_script( 'rx-dashboard-widgets', $js );
	}

	/**
	 * RX Theme Overview Widget.
	 */
	public static function render_theme_overview_widget() {
		$theme        = wp_get_theme();
		$child_theme  = is_child_theme();
		$theme_name   = $theme->get( 'Name' );
		$theme_ver    = $theme->get( 'Version' );
		$theme_author = $theme->get( 'Author' );

		?>
		<div class="rx-dashboard-wrap">
			<p>
				<strong><?php echo esc_html( $theme_name ); ?></strong>
				<span class="rx-muted">v<?php echo esc_html( $theme_ver ? $theme_ver : '1.0.0' ); ?></span>
			</p>

			<div class="rx-dashboard-grid">
				<div class="rx-dashboard-card">
					<h4><?php esc_html_e( 'Theme Mode', 'rx-theme' ); ?></h4>
					<div class="rx-dashboard-value"><?php echo $child_theme ? esc_html__( 'Child', 'rx-theme' ) : esc_html__( 'Parent', 'rx-theme' ); ?></div>
				</div>

				<div class="rx-dashboard-card">
					<h4><?php esc_html_e( 'WordPress', 'rx-theme' ); ?></h4>
					<div class="rx-dashboard-value"><?php echo esc_html( get_bloginfo( 'version' ) ); ?></div>
				</div>

				<div class="rx-dashboard-card">
					<h4><?php esc_html_e( 'PHP', 'rx-theme' ); ?></h4>
					<div class="rx-dashboard-value"><?php echo esc_html( PHP_VERSION ); ?></div>
				</div>

				<div class="rx-dashboard-card">
					<h4><?php esc_html_e( 'Environment', 'rx-theme' ); ?></h4>
					<div class="rx-dashboard-value"><?php echo esc_html( wp_get_environment_type() ); ?></div>
				</div>
			</div>

			<ul class="rx-dashboard-list">
				<li>
					<span><?php esc_html_e( 'Theme Author', 'rx-theme' ); ?></span>
					<strong><?php echo wp_kses_post( $theme_author ? $theme_author : 'RX Theme' ); ?></strong>
				</li>
				<li>
					<span><?php esc_html_e( 'Stylesheet Directory', 'rx-theme' ); ?></span>
					<span class="rx-code"><?php echo esc_html( basename( get_stylesheet_directory() ) ); ?></span>
				</li>
				<li>
					<span><?php esc_html_e( 'Template Directory', 'rx-theme' ); ?></span>
					<span class="rx-code"><?php echo esc_html( basename( get_template_directory() ) ); ?></span>
				</li>
			</ul>

			<div class="rx-dashboard-actions">
				<a class="button button-primary" href="<?php echo esc_url( admin_url( 'customize.php' ) ); ?>">
					<?php esc_html_e( 'Customize Theme', 'rx-theme' ); ?>
				</a>
				<a class="button" href="<?php echo esc_url( admin_url( 'themes.php' ) ); ?>">
					<?php esc_html_e( 'Manage Themes', 'rx-theme' ); ?>
				</a>
				<a class="button" href="<?php echo esc_url( admin_url( 'nav-menus.php' ) ); ?>">
					<?php esc_html_e( 'Menus', 'rx-theme' ); ?>
				</a>
			</div>
		</div>
		<?php
	}

	/**
	 * Site Health Summary Widget.
	 */
	public static function render_site_health_widget() {
		$post_count      = wp_count_posts( 'post' );
		$page_count      = wp_count_posts( 'page' );
		$comment_count   = wp_count_comments();
		$plugin_count    = self::get_plugin_count();
		$active_theme    = wp_get_theme();
		$public_site     = (int) get_option( 'blog_public', 1 );
		$timezone        = wp_timezone_string();
		$permalink       = get_option( 'permalink_structure' );

		?>
		<div class="rx-dashboard-wrap">
			<div class="rx-dashboard-grid">
				<div class="rx-dashboard-card">
					<h4><?php esc_html_e( 'Published Posts', 'rx-theme' ); ?></h4>
					<div class="rx-dashboard-value"><?php echo esc_html( number_format_i18n( (int) $post_count->publish ) ); ?></div>
				</div>

				<div class="rx-dashboard-card">
					<h4><?php esc_html_e( 'Published Pages', 'rx-theme' ); ?></h4>
					<div class="rx-dashboard-value"><?php echo esc_html( number_format_i18n( (int) $page_count->publish ) ); ?></div>
				</div>

				<div class="rx-dashboard-card">
					<h4><?php esc_html_e( 'Approved Comments', 'rx-theme' ); ?></h4>
					<div class="rx-dashboard-value"><?php echo esc_html( number_format_i18n( (int) $comment_count->approved ) ); ?></div>
				</div>

				<div class="rx-dashboard-card">
					<h4><?php esc_html_e( 'Active Plugins', 'rx-theme' ); ?></h4>
					<div class="rx-dashboard-value"><?php echo esc_html( number_format_i18n( $plugin_count['active'] ) ); ?></div>
				</div>
			</div>

			<ul class="rx-dashboard-list">
				<li>
					<span><?php esc_html_e( 'Search Engine Visibility', 'rx-theme' ); ?></span>
					<?php echo $public_site ? self::status_badge( 'good', __( 'Visible', 'rx-theme' ) ) : self::status_badge( 'danger', __( 'Discouraged', 'rx-theme' ) ); ?>
				</li>
				<li>
					<span><?php esc_html_e( 'Permalink Structure', 'rx-theme' ); ?></span>
					<?php echo $permalink ? self::status_badge( 'good', __( 'Enabled', 'rx-theme' ) ) : self::status_badge( 'warning', __( 'Plain', 'rx-theme' ) ); ?>
				</li>
				<li>
					<span><?php esc_html_e( 'Timezone', 'rx-theme' ); ?></span>
					<strong><?php echo esc_html( $timezone ? $timezone : 'UTC' ); ?></strong>
				</li>
				<li>
					<span><?php esc_html_e( 'Current Theme', 'rx-theme' ); ?></span>
					<strong><?php echo esc_html( $active_theme->get( 'Name' ) ); ?></strong>
				</li>
			</ul>

			<div class="rx-dashboard-actions">
				<a class="button" href="<?php echo esc_url( admin_url( 'site-health.php' ) ); ?>">
					<?php esc_html_e( 'Open Site Health', 'rx-theme' ); ?>
				</a>
				<a class="button" href="<?php echo esc_url( admin_url( 'options-permalink.php' ) ); ?>">
					<?php esc_html_e( 'Permalinks', 'rx-theme' ); ?>
				</a>
				<a class="button" href="<?php echo esc_url( admin_url( 'options-reading.php' ) ); ?>">
					<?php esc_html_e( 'Reading Settings', 'rx-theme' ); ?>
				</a>
			</div>
		</div>
		<?php
	}

	/**
	 * SEO Status Widget.
	 */
	public static function render_seo_status_widget() {
		$blog_public      = (int) get_option( 'blog_public', 1 );
		$site_title       = get_bloginfo( 'name' );
		$tagline          = get_bloginfo( 'description' );
		$permalink        = get_option( 'permalink_structure' );
		$front_page_id    = (int) get_option( 'page_on_front' );
		$show_on_front    = get_option( 'show_on_front' );
		$robots_file      = ABSPATH . 'robots.txt';
		$sitemap_enabled  = function_exists( 'wp_sitemaps_get_server' );

		?>
		<div class="rx-dashboard-wrap">
			<ul class="rx-dashboard-list">
				<li>
					<span><?php esc_html_e( 'Search Engine Indexing', 'rx-theme' ); ?></span>
					<?php echo $blog_public ? self::status_badge( 'good', __( 'Allowed', 'rx-theme' ) ) : self::status_badge( 'danger', __( 'Blocked', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'Site Title', 'rx-theme' ); ?></span>
					<?php echo ! empty( $site_title ) ? self::status_badge( 'good', __( 'Set', 'rx-theme' ) ) : self::status_badge( 'warning', __( 'Missing', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'Tagline', 'rx-theme' ); ?></span>
					<?php echo ! empty( $tagline ) ? self::status_badge( 'good', __( 'Set', 'rx-theme' ) ) : self::status_badge( 'warning', __( 'Missing', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'SEO-Friendly Permalinks', 'rx-theme' ); ?></span>
					<?php echo ! empty( $permalink ) ? self::status_badge( 'good', __( 'Enabled', 'rx-theme' ) ) : self::status_badge( 'warning', __( 'Plain URL', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'Static Homepage', 'rx-theme' ); ?></span>
					<?php echo ( 'page' === $show_on_front && $front_page_id ) ? self::status_badge( 'good', __( 'Configured', 'rx-theme' ) ) : self::status_badge( 'info', __( 'Blog Feed', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'WordPress Sitemap', 'rx-theme' ); ?></span>
					<?php echo $sitemap_enabled ? self::status_badge( 'good', __( 'Available', 'rx-theme' ) ) : self::status_badge( 'warning', __( 'Unavailable', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'Robots.txt File', 'rx-theme' ); ?></span>
					<?php echo file_exists( $robots_file ) ? self::status_badge( 'good', __( 'Physical File', 'rx-theme' ) ) : self::status_badge( 'info', __( 'Virtual Default', 'rx-theme' ) ); ?>
				</li>
			</ul>

			<div class="rx-dashboard-actions">
				<a class="button" href="<?php echo esc_url( home_url( '/wp-sitemap.xml' ) ); ?>" target="_blank" rel="noopener">
					<?php esc_html_e( 'View Sitemap', 'rx-theme' ); ?>
				</a>
				<a class="button" href="<?php echo esc_url( home_url( '/robots.txt' ) ); ?>" target="_blank" rel="noopener">
					<?php esc_html_e( 'View Robots.txt', 'rx-theme' ); ?>
				</a>
				<a class="button" href="<?php echo esc_url( admin_url( 'options-general.php' ) ); ?>">
					<?php esc_html_e( 'General Settings', 'rx-theme' ); ?>
				</a>
			</div>
		</div>
		<?php
	}

	/**
	 * Performance Widget.
	 */
	public static function render_performance_widget() {
		$memory_limit       = wp_convert_hr_to_bytes( WP_MEMORY_LIMIT );
		$memory_limit_mb    = $memory_limit ? round( $memory_limit / MB_IN_BYTES ) : 0;
		$memory_usage       = function_exists( 'memory_get_usage' ) ? memory_get_usage( true ) : 0;
		$memory_usage_mb    = $memory_usage ? round( $memory_usage / MB_IN_BYTES ) : 0;
		$memory_percent     = ( $memory_limit > 0 && $memory_usage > 0 ) ? min( 100, round( ( $memory_usage / $memory_limit ) * 100 ) ) : 0;
		$object_cache       = wp_using_ext_object_cache();
		$gzip_possible      = extension_loaded( 'zlib' );
		$opcache_enabled    = function_exists( 'opcache_get_status' ) ? (bool) opcache_get_status( false ) : false;
		$uploads            = wp_upload_dir();
		$uploads_writable   = ! empty( $uploads['basedir'] ) && wp_is_writable( $uploads['basedir'] );

		?>
		<div class="rx-dashboard-wrap">
			<div class="rx-dashboard-card">
				<h4><?php esc_html_e( 'PHP Memory Usage', 'rx-theme' ); ?></h4>
				<strong>
					<?php
					echo esc_html(
						sprintf(
							/* translators: 1: usage, 2: limit */
							__( '%1$s MB of %2$s MB', 'rx-theme' ),
							$memory_usage_mb,
							$memory_limit_mb
						)
					);
					?>
				</strong>
				<div class="rx-progress">
					<span style="width: <?php echo esc_attr( $memory_percent ); ?>%;"></span>
				</div>
				<p class="rx-muted rx-small">
					<?php esc_html_e( 'Lower memory usage usually means faster admin loading.', 'rx-theme' ); ?>
				</p>
			</div>

			<ul class="rx-dashboard-list">
				<li>
					<span><?php esc_html_e( 'External Object Cache', 'rx-theme' ); ?></span>
					<?php echo $object_cache ? self::status_badge( 'good', __( 'Enabled', 'rx-theme' ) ) : self::status_badge( 'info', __( 'Not Detected', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'GZIP/Zlib Extension', 'rx-theme' ); ?></span>
					<?php echo $gzip_possible ? self::status_badge( 'good', __( 'Available', 'rx-theme' ) ) : self::status_badge( 'warning', __( 'Missing', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'OPcache', 'rx-theme' ); ?></span>
					<?php echo $opcache_enabled ? self::status_badge( 'good', __( 'Enabled', 'rx-theme' ) ) : self::status_badge( 'info', __( 'Not Detected', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'Uploads Folder Writable', 'rx-theme' ); ?></span>
					<?php echo $uploads_writable ? self::status_badge( 'good', __( 'Writable', 'rx-theme' ) ) : self::status_badge( 'danger', __( 'Not Writable', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'Script Debug Mode', 'rx-theme' ); ?></span>
					<?php echo ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? self::status_badge( 'warning', __( 'Enabled', 'rx-theme' ) ) : self::status_badge( 'good', __( 'Disabled', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'WP Debug Mode', 'rx-theme' ); ?></span>
					<?php echo ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ? self::status_badge( 'warning', __( 'Enabled', 'rx-theme' ) ) : self::status_badge( 'good', __( 'Disabled', 'rx-theme' ) ); ?>
				</li>
			</ul>

			<div class="rx-dashboard-actions">
				<a href="#" class="button rx-clear-dashboard-cache" data-nonce="<?php echo esc_attr( wp_create_nonce( 'rx_clear_dashboard_cache' ) ); ?>">
					<?php esc_html_e( 'Clear RX Cache', 'rx-theme' ); ?>
				</a>
				<a class="button" href="<?php echo esc_url( admin_url( 'site-health.php?tab=debug' ) ); ?>">
					<?php esc_html_e( 'Debug Info', 'rx-theme' ); ?>
				</a>
			</div>
		</div>
		<?php
	}

	/**
	 * Security Widget.
	 */
	public static function render_security_widget() {
		$ssl                 = is_ssl();
		$file_edit_disabled  = defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT;
		$wp_debug            = defined( 'WP_DEBUG' ) && WP_DEBUG;
		$admin_user_exists   = username_exists( 'admin' );
		$xmlrpc_file         = ABSPATH . 'xmlrpc.php';
		$xmlrpc_exists       = file_exists( $xmlrpc_file );
		$uploads             = wp_upload_dir();
		$uploads_index       = trailingslashit( $uploads['basedir'] ) . 'index.php';
		$uploads_index_exists = file_exists( $uploads_index );

		?>
		<div class="rx-dashboard-wrap">
			<ul class="rx-dashboard-list">
				<li>
					<span><?php esc_html_e( 'HTTPS / SSL', 'rx-theme' ); ?></span>
					<?php echo $ssl ? self::status_badge( 'good', __( 'Active', 'rx-theme' ) ) : self::status_badge( 'danger', __( 'Not Active', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'Theme/Plugin File Editor', 'rx-theme' ); ?></span>
					<?php echo $file_edit_disabled ? self::status_badge( 'good', __( 'Disabled', 'rx-theme' ) ) : self::status_badge( 'warning', __( 'Enabled', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'WP Debug on Live Site', 'rx-theme' ); ?></span>
					<?php echo $wp_debug ? self::status_badge( 'warning', __( 'Enabled', 'rx-theme' ) ) : self::status_badge( 'good', __( 'Disabled', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'Default Admin Username', 'rx-theme' ); ?></span>
					<?php echo $admin_user_exists ? self::status_badge( 'warning', __( 'Exists', 'rx-theme' ) ) : self::status_badge( 'good', __( 'Not Found', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'XML-RPC File', 'rx-theme' ); ?></span>
					<?php echo $xmlrpc_exists ? self::status_badge( 'info', __( 'Present', 'rx-theme' ) ) : self::status_badge( 'good', __( 'Removed', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'Uploads Index Protection', 'rx-theme' ); ?></span>
					<?php echo $uploads_index_exists ? self::status_badge( 'good', __( 'Index Exists', 'rx-theme' ) ) : self::status_badge( 'info', __( 'Missing', 'rx-theme' ) ); ?>
				</li>
			</ul>

			<p class="rx-muted rx-small">
				<?php esc_html_e( 'Security status is a helpful checklist only. Use a dedicated security plugin or server firewall for deeper protection.', 'rx-theme' ); ?>
			</p>

			<div class="rx-dashboard-actions">
				<a class="button" href="<?php echo esc_url( admin_url( 'users.php' ) ); ?>">
					<?php esc_html_e( 'Manage Users', 'rx-theme' ); ?>
				</a>
				<a class="button" href="<?php echo esc_url( admin_url( 'update-core.php' ) ); ?>">
					<?php esc_html_e( 'Updates', 'rx-theme' ); ?>
				</a>
			</div>
		</div>
		<?php
	}

	/**
	 * Recent Content Widget.
	 */
	public static function render_recent_content_widget() {
		$recent_posts = get_posts(
			array(
				'post_type'      => array( 'post', 'page' ),
				'post_status'    => array( 'publish', 'draft', 'pending', 'future' ),
				'posts_per_page' => 8,
				'orderby'        => 'modified',
				'order'          => 'DESC',
				'no_found_rows'  => true,
			)
		);

		?>
		<div class="rx-dashboard-wrap">
			<?php if ( ! empty( $recent_posts ) ) : ?>
				<ul class="rx-dashboard-list">
					<?php foreach ( $recent_posts as $post ) : ?>
						<li>
							<span>
								<a href="<?php echo esc_url( get_edit_post_link( $post->ID ) ); ?>">
									<?php echo esc_html( get_the_title( $post->ID ) ? get_the_title( $post->ID ) : __( '(No title)', 'rx-theme' ) ); ?>
								</a>
								<br>
								<span class="rx-muted rx-small">
									<?php echo esc_html( ucfirst( $post->post_type ) ); ?> ·
									<?php echo esc_html( ucfirst( $post->post_status ) ); ?> ·
									<?php echo esc_html( human_time_diff( get_post_modified_time( 'U', true, $post ), current_time( 'timestamp', true ) ) . ' ago' ); ?>
								</span>
							</span>

							<span>
								<a class="button button-small" href="<?php echo esc_url( get_permalink( $post->ID ) ); ?>" target="_blank" rel="noopener">
									<?php esc_html_e( 'View', 'rx-theme' ); ?>
								</a>
							</span>
						</li>
					<?php endforeach; ?>
				</ul>
			<?php else : ?>
				<p><?php esc_html_e( 'No recent content found.', 'rx-theme' ); ?></p>
			<?php endif; ?>

			<div class="rx-dashboard-actions">
				<a class="button button-primary" href="<?php echo esc_url( admin_url( 'post-new.php' ) ); ?>">
					<?php esc_html_e( 'Add New Post', 'rx-theme' ); ?>
				</a>
				<a class="button" href="<?php echo esc_url( admin_url( 'post-new.php?post_type=page' ) ); ?>">
					<?php esc_html_e( 'Add New Page', 'rx-theme' ); ?>
				</a>
				<a class="button" href="<?php echo esc_url( admin_url( 'edit.php' ) ); ?>">
					<?php esc_html_e( 'All Posts', 'rx-theme' ); ?>
				</a>
			</div>
		</div>
		<?php
	}

	/**
	 * Quick Actions Widget.
	 */
	public static function render_quick_actions_widget() {
		$nonce = wp_create_nonce( 'rx_dashboard_action' );

		?>
		<div class="rx-dashboard-wrap">
			<p class="rx-muted">
				<?php esc_html_e( 'Fast links for common RX Theme and WordPress tasks.', 'rx-theme' ); ?>
			</p>

			<div class="rx-dashboard-actions">
				<a class="button button-primary" href="<?php echo esc_url( admin_url( 'customize.php' ) ); ?>">
					<?php esc_html_e( 'Open Customizer', 'rx-theme' ); ?>
				</a>

				<a class="button" href="<?php echo esc_url( admin_url( 'widgets.php' ) ); ?>">
					<?php esc_html_e( 'Widgets', 'rx-theme' ); ?>
				</a>

				<a class="button" href="<?php echo esc_url( admin_url( 'nav-menus.php' ) ); ?>">
					<?php esc_html_e( 'Menus', 'rx-theme' ); ?>
				</a>

				<a class="button" href="<?php echo esc_url( admin_url( 'upload.php' ) ); ?>">
					<?php esc_html_e( 'Media Library', 'rx-theme' ); ?>
				</a>

				<a class="button" href="<?php echo esc_url( admin_url( 'plugins.php' ) ); ?>">
					<?php esc_html_e( 'Plugins', 'rx-theme' ); ?>
				</a>

				<a class="button" href="<?php echo esc_url( admin_url( 'themes.php' ) ); ?>">
					<?php esc_html_e( 'Themes', 'rx-theme' ); ?>
				</a>

				<a class="button" href="<?php echo esc_url( admin_url( 'options-general.php' ) ); ?>">
					<?php esc_html_e( 'Settings', 'rx-theme' ); ?>
				</a>

				<a class="button" href="<?php echo esc_url( admin_url( 'tools.php' ) ); ?>">
					<?php esc_html_e( 'Tools', 'rx-theme' ); ?>
				</a>

				<a class="button" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'rx_dashboard_action', 'flush_rewrite_rules', admin_url( 'index.php' ) ), 'rx_dashboard_action', '_rxnonce' ) ); ?>">
					<?php esc_html_e( 'Flush Permalinks', 'rx-theme' ); ?>
				</a>

				<a class="button" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'rx_dashboard_action', 'clear_rx_transients', admin_url( 'index.php' ) ), 'rx_dashboard_action', '_rxnonce' ) ); ?>">
					<?php esc_html_e( 'Clear RX Transients', 'rx-theme' ); ?>
				</a>
			</div>

			<p class="rx-muted rx-small">
				<?php esc_html_e( 'Use quick actions carefully on production websites.', 'rx-theme' ); ?>
			</p>
		</div>
		<?php
	}

	/**
	 * System Info Widget.
	 */
	public static function render_system_info_widget() {
		global $wpdb;

		$mysql_version = $wpdb->db_version();
		$server        = isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : __( 'Unknown', 'rx-theme' );
		$max_upload    = size_format( wp_max_upload_size() );
		$timezone      = wp_timezone_string();
		$locale        = get_locale();
		$multisite     = is_multisite();
		$debug_log     = defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG;

		?>
		<div class="rx-dashboard-wrap">
			<ul class="rx-dashboard-list">
				<li>
					<span><?php esc_html_e( 'Server Software', 'rx-theme' ); ?></span>
					<strong><?php echo esc_html( $server ); ?></strong>
				</li>

				<li>
					<span><?php esc_html_e( 'PHP Version', 'rx-theme' ); ?></span>
					<strong><?php echo esc_html( PHP_VERSION ); ?></strong>
				</li>

				<li>
					<span><?php esc_html_e( 'Database Version', 'rx-theme' ); ?></span>
					<strong><?php echo esc_html( $mysql_version ); ?></strong>
				</li>

				<li>
					<span><?php esc_html_e( 'Max Upload Size', 'rx-theme' ); ?></span>
					<strong><?php echo esc_html( $max_upload ); ?></strong>
				</li>

				<li>
					<span><?php esc_html_e( 'Timezone', 'rx-theme' ); ?></span>
					<strong><?php echo esc_html( $timezone ? $timezone : 'UTC' ); ?></strong>
				</li>

				<li>
					<span><?php esc_html_e( 'Locale', 'rx-theme' ); ?></span>
					<strong><?php echo esc_html( $locale ); ?></strong>
				</li>

				<li>
					<span><?php esc_html_e( 'Multisite', 'rx-theme' ); ?></span>
					<?php echo $multisite ? self::status_badge( 'info', __( 'Yes', 'rx-theme' ) ) : self::status_badge( 'good', __( 'No', 'rx-theme' ) ); ?>
				</li>

				<li>
					<span><?php esc_html_e( 'Debug Log', 'rx-theme' ); ?></span>
					<?php echo $debug_log ? self::status_badge( 'warning', __( 'Enabled', 'rx-theme' ) ) : self::status_badge( 'good', __( 'Disabled', 'rx-theme' ) ); ?>
				</li>
			</ul>
		</div>
		<?php
	}

	/**
	 * Developer Notes Widget.
	 */
	public static function render_developer_notes_widget() {
		$template_dir = get_template_directory();
		$stylesheet_dir = get_stylesheet_directory();

		$recommended_files = array(
			'functions.php',
			'inc/enqueue.php',
			'inc/theme-setup.php',
			'inc/template-functions.php',
			'inc/admin/dashboard-widgets.php',
			'inc/options/color-options.php',
			'inc/options/typography-options.php',
			'inc/security/security.php',
			'inc/performance/performance.php',
			'inc/seo/seo.php',
		);

		?>
		<div class="rx-dashboard-wrap">
			<p>
				<?php esc_html_e( 'Recommended RX Theme modular structure check:', 'rx-theme' ); ?>
			</p>

			<ul class="rx-dashboard-list">
				<?php foreach ( $recommended_files as $file ) : ?>
					<?php
					$parent_exists = file_exists( trailingslashit( $template_dir ) . $file );
					$child_exists  = file_exists( trailingslashit( $stylesheet_dir ) . $file );
					$exists        = $parent_exists || $child_exists;
					?>
					<li>
						<span class="rx-code"><?php echo esc_html( $file ); ?></span>
						<?php echo $exists ? self::status_badge( 'good', __( 'Found', 'rx-theme' ) ) : self::status_badge( 'info', __( 'Optional', 'rx-theme' ) ); ?>
					</li>
				<?php endforeach; ?>
			</ul>

			<p class="rx-muted rx-small">
				<?php esc_html_e( 'This widget helps you keep RX Theme clean, modular, and developer-friendly.', 'rx-theme' ); ?>
			</p>
		</div>
		<?php
	}

	/**
	 * Handle quick dashboard actions.
	 */
	public static function handle_quick_actions() {
		if ( ! is_admin() || ! current_user_can( self::$capability ) ) {
			return;
		}

		if ( empty( $_GET['rx_dashboard_action'] ) ) {
			return;
		}

		if ( empty( $_GET['_rxnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_rxnonce'] ) ), 'rx_dashboard_action' ) ) {
			wp_die( esc_html__( 'Security check failed.', 'rx-theme' ) );
		}

		$action = sanitize_key( wp_unslash( $_GET['rx_dashboard_action'] ) );

		switch ( $action ) {
			case 'flush_rewrite_rules':
				flush_rewrite_rules();
				self::redirect_with_message( 'rx_permalinks_flushed' );
				break;

			case 'clear_rx_transients':
				self::clear_rx_transients();
				self::redirect_with_message( 'rx_transients_cleared' );
				break;
		}
	}

	/**
	 * AJAX clear dashboard cache.
	 */
	public static function ajax_clear_dashboard_cache() {
		if ( ! current_user_can( self::$capability ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Permission denied.', 'rx-theme' ),
				)
			);
		}

		check_ajax_referer( 'rx_clear_dashboard_cache', 'nonce' );

		self::clear_rx_transients();

		wp_send_json_success(
			array(
				'message' => __( 'RX dashboard cache cleared.', 'rx-theme' ),
			)
		);
	}

	/**
	 * Add custom items to WordPress "At a Glance".
	 */
	public static function add_glance_items( $items ) {
		if ( ! current_user_can( self::$capability ) ) {
			return $items;
		}

		$theme = wp_get_theme();

		$items[] = sprintf(
			'<a href="%1$s">%2$s</a>',
			esc_url( admin_url( 'themes.php' ) ),
			esc_html( sprintf( __( 'RX Theme: %s', 'rx-theme' ), $theme->get( 'Version' ) ? $theme->get( 'Version' ) : '1.0.0' ) )
		);

		return $items;
	}

	/**
	 * Get plugin count.
	 */
	private static function get_plugin_count() {
		if ( ! function_exists( 'get_plugins' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		$plugins        = get_plugins();
		$active_plugins = (array) get_option( 'active_plugins', array() );

		return array(
			'total'  => count( $plugins ),
			'active' => count( $active_plugins ),
		);
	}

	/**
	 * Clear RX transients.
	 */
	private static function clear_rx_transients() {
		global $wpdb;

		$wpdb->query(
			$wpdb->prepare(
				"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s",
				$wpdb->esc_like( '_transient_rx_' ) . '%',
				$wpdb->esc_like( '_transient_timeout_rx_' ) . '%'
			)
		);

		wp_cache_flush();
	}

	/**
	 * Redirect after action.
	 */
	private static function redirect_with_message( $message ) {
		wp_safe_redirect(
			add_query_arg(
				array(
					'rx_dashboard_message' => sanitize_key( $message ),
				),
				admin_url( 'index.php' )
			)
		);
		exit;
	}

	/**
	 * Return theme version.
	 */
	private static function theme_version() {
		$theme = wp_get_theme();
		return $theme->get( 'Version' ) ? $theme->get( 'Version' ) : '1.0.0';
	}

	/**
	 * Status badge helper.
	 */
	private static function status_badge( $type, $text ) {
		$type = sanitize_html_class( $type );

		return sprintf(
			'<span class="rx-status rx-status-%1$s">%2$s</span>',
			esc_attr( $type ),
			esc_html( $text )
		);
	}
}

RX_Theme_Dashboard_Widgets::init();

endif;

Now include it in your functions.php:

/**
 * RX Theme Admin Dashboard Widgets.
 */
if ( is_admin() ) {
	require_once get_template_directory() . '/inc/admin/dashboard-widgets.php';
}

Best folder structure:

rx-theme/
├── functions.php
└── inc/
    └── admin/
        └── dashboard-widgets.php

This file is safe for a theme because it only loads in the admin dashboard and checks manage_options permission before showing advanced dashboard information.

Leave a Reply

Your email address will not be published. Required fields are marked *