I’ll build this as a full reusable inc/admin/notice.php module for your RX theme: admin notices, dismissible notices, theme checks, plugin recommendations, update/security warnings, dashboard notices, and safe option-based dismiss logic.
Below is an advanced inc/admin/notice.php file for your RX Theme. It includes many possible admin notice features: welcome notice, theme setup warnings, required/recommended plugin notices, PHP/WordPress version notices, SSL notice, permalink notice, debug notice, upload directory notice, dismissed notice memory, admin dashboard widget, AJAX dismiss system, and helper functions.
Create this file:
<?php
/**
* RX Theme Admin Notices
*
* File: inc/admin/notice.php
*
* @package RX_Theme
*/
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'RX_Theme_Admin_Notices' ) ) :
final class RX_Theme_Admin_Notices {
/**
* Option key for dismissed notices.
*/
const DISMISSED_OPTION = 'rx_theme_dismissed_admin_notices';
/**
* Theme slug.
*/
const THEME_SLUG = 'rx-theme';
/**
* Minimum PHP version.
*/
const MIN_PHP_VERSION = '7.4';
/**
* Minimum WordPress version.
*/
const MIN_WP_VERSION = '6.0';
/**
* Initialize hooks.
*/
public static function init() {
add_action( 'admin_init', array( __CLASS__, 'maybe_set_activation_notice' ) );
add_action( 'admin_notices', array( __CLASS__, 'render_admin_notices' ) );
add_action( 'network_admin_notices', array( __CLASS__, 'render_network_admin_notices' ) );
add_action( 'wp_ajax_rx_theme_dismiss_notice', array( __CLASS__, 'ajax_dismiss_notice' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_admin_assets' ) );
add_action( 'wp_dashboard_setup', array( __CLASS__, 'register_dashboard_widget' ) );
add_action( 'admin_menu', array( __CLASS__, 'register_notice_page' ) );
}
/**
* Add activation notice once after theme activation.
*/
public static function maybe_set_activation_notice() {
if ( get_option( 'rx_theme_activation_notice_shown' ) ) {
return;
}
set_transient( 'rx_theme_show_welcome_notice', 1, DAY_IN_SECONDS );
update_option( 'rx_theme_activation_notice_shown', 1, false );
}
/**
* Enqueue small inline admin JS/CSS.
*/
public static function enqueue_admin_assets( $hook ) {
if ( ! is_admin() ) {
return;
}
wp_register_script(
'rx-theme-admin-notice',
'',
array( 'jquery' ),
defined( 'RX_THEME_VERSION' ) ? RX_THEME_VERSION : '1.0.0',
true
);
wp_enqueue_script( 'rx-theme-admin-notice' );
wp_localize_script(
'rx-theme-admin-notice',
'rxThemeNotice',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'rx_theme_dismiss_notice_nonce' ),
)
);
$js = "
jQuery(document).on('click', '.rx-notice .notice-dismiss, .rx-dismiss-notice', function(e) {
var notice = jQuery(this).closest('.rx-notice');
var noticeId = notice.data('notice-id');
if (!noticeId) {
return;
}
jQuery.post(rxThemeNotice.ajaxUrl, {
action: 'rx_theme_dismiss_notice',
nonce: rxThemeNotice.nonce,
notice_id: noticeId
});
});
";
wp_add_inline_script( 'rx-theme-admin-notice', $js );
wp_register_style(
'rx-theme-admin-notice-style',
false,
array(),
defined( 'RX_THEME_VERSION' ) ? RX_THEME_VERSION : '1.0.0'
);
wp_enqueue_style( 'rx-theme-admin-notice-style' );
$css = "
.rx-notice {
border-left-width: 4px;
}
.rx-notice .rx-notice-title {
font-size: 15px;
font-weight: 700;
margin: 0 0 6px;
}
.rx-notice .rx-notice-actions {
margin-top: 10px;
}
.rx-notice .button {
margin-right: 6px;
}
.rx-theme-dashboard-widget ul {
margin-left: 18px;
list-style: disc;
}
.rx-theme-status-good {
color: #008a20;
font-weight: 600;
}
.rx-theme-status-warning {
color: #b26200;
font-weight: 600;
}
.rx-theme-status-danger {
color: #b32d2e;
font-weight: 600;
}
";
wp_add_inline_style( 'rx-theme-admin-notice-style', $css );
}
/**
* Main notice renderer.
*/
public static function render_admin_notices() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
self::welcome_notice();
self::php_version_notice();
self::wordpress_version_notice();
self::ssl_notice();
self::permalink_notice();
self::debug_mode_notice();
self::missing_homepage_notice();
self::site_icon_notice();
self::timezone_notice();
self::upload_directory_notice();
self::required_plugins_notice();
self::recommended_plugins_notice();
self::woocommerce_notice();
self::elementor_notice();
self::seo_plugin_notice();
self::cache_plugin_notice();
self::security_plugin_notice();
self::backup_plugin_notice();
self::theme_file_permission_notice();
self::memory_limit_notice();
self::maintenance_mode_notice();
self::discourage_search_engine_notice();
}
/**
* Network admin notice renderer.
*/
public static function render_network_admin_notices() {
if ( ! current_user_can( 'manage_network_options' ) ) {
return;
}
self::render_notice(
'rx-network-theme-notice',
'info',
__( 'RX Theme Network Notice', 'rx-theme' ),
__( 'RX Theme is active in a multisite environment. Please make sure all child sites use compatible plugins, SSL, caching, and security settings.', 'rx-theme' ),
true
);
}
/**
* Welcome notice after activation.
*/
public static function welcome_notice() {
if ( ! get_transient( 'rx_theme_show_welcome_notice' ) ) {
return;
}
if ( self::is_dismissed( 'rx-welcome-notice' ) ) {
return;
}
$message = sprintf(
wp_kses_post(
__( 'Thank you for activating <strong>RX Theme</strong>. You can now configure theme options, menus, widgets, homepage settings, performance options, and SEO settings.', 'rx-theme' )
)
);
$actions = array(
array(
'label' => __( 'Customize Theme', 'rx-theme' ),
'url' => admin_url( 'customize.php' ),
'class' => 'button button-primary',
),
array(
'label' => __( 'Theme Notices', 'rx-theme' ),
'url' => admin_url( 'themes.php?page=rx-theme-notices' ),
'class' => 'button',
),
);
self::render_notice( 'rx-welcome-notice', 'success', __( 'Welcome to RX Theme', 'rx-theme' ), $message, true, $actions );
}
/**
* PHP version warning.
*/
public static function php_version_notice() {
if ( version_compare( PHP_VERSION, self::MIN_PHP_VERSION, '>=' ) ) {
return;
}
self::render_notice(
'rx-php-version-notice',
'error',
__( 'PHP Version Too Old', 'rx-theme' ),
sprintf(
esc_html__( 'RX Theme recommends PHP %1$s or higher. Your server is using PHP %2$s. Please update PHP from your hosting control panel.', 'rx-theme' ),
esc_html( self::MIN_PHP_VERSION ),
esc_html( PHP_VERSION )
),
false
);
}
/**
* WordPress version warning.
*/
public static function wordpress_version_notice() {
global $wp_version;
if ( version_compare( $wp_version, self::MIN_WP_VERSION, '>=' ) ) {
return;
}
self::render_notice(
'rx-wp-version-notice',
'error',
__( 'WordPress Version Too Old', 'rx-theme' ),
sprintf(
esc_html__( 'RX Theme recommends WordPress %1$s or higher. Your site is using WordPress %2$s. Please update WordPress for better security and compatibility.', 'rx-theme' ),
esc_html( self::MIN_WP_VERSION ),
esc_html( $wp_version )
),
false
);
}
/**
* SSL notice.
*/
public static function ssl_notice() {
if ( is_ssl() || self::is_dismissed( 'rx-ssl-notice' ) ) {
return;
}
self::render_notice(
'rx-ssl-notice',
'warning',
__( 'SSL Is Not Active', 'rx-theme' ),
__( 'Your website is not loading through HTTPS. SSL is important for SEO, security, login protection, and user trust. Please enable SSL from your hosting panel.', 'rx-theme' ),
true
);
}
/**
* Permalink notice.
*/
public static function permalink_notice() {
if ( get_option( 'permalink_structure' ) || self::is_dismissed( 'rx-permalink-notice' ) ) {
return;
}
$actions = array(
array(
'label' => __( 'Open Permalink Settings', 'rx-theme' ),
'url' => admin_url( 'options-permalink.php' ),
'class' => 'button button-primary',
),
);
self::render_notice(
'rx-permalink-notice',
'warning',
__( 'Pretty Permalinks Are Disabled', 'rx-theme' ),
__( 'Your site is using plain permalink structure. For better SEO and clean URLs, use Post name permalink structure.', 'rx-theme' ),
true,
$actions
);
}
/**
* Debug mode notice.
*/
public static function debug_mode_notice() {
if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG || self::is_dismissed( 'rx-debug-notice' ) ) {
return;
}
self::render_notice(
'rx-debug-notice',
'warning',
__( 'WP_DEBUG Is Enabled', 'rx-theme' ),
__( 'Debug mode is active. This is useful during development, but on a live website it may expose technical information. Disable WP_DEBUG on production.', 'rx-theme' ),
true
);
}
/**
* Homepage notice.
*/
public static function missing_homepage_notice() {
if ( self::is_dismissed( 'rx-homepage-notice' ) ) {
return;
}
$show_on_front = get_option( 'show_on_front' );
$page_on_front = get_option( 'page_on_front' );
if ( 'page' === $show_on_front && ! empty( $page_on_front ) ) {
return;
}
$actions = array(
array(
'label' => __( 'Set Homepage', 'rx-theme' ),
'url' => admin_url( 'options-reading.php' ),
'class' => 'button button-primary',
),
);
self::render_notice(
'rx-homepage-notice',
'info',
__( 'Homepage Is Not Set', 'rx-theme' ),
__( 'For a professional website layout, you may set a static homepage from Reading Settings.', 'rx-theme' ),
true,
$actions
);
}
/**
* Site icon notice.
*/
public static function site_icon_notice() {
if ( has_site_icon() || self::is_dismissed( 'rx-site-icon-notice' ) ) {
return;
}
$actions = array(
array(
'label' => __( 'Add Site Icon', 'rx-theme' ),
'url' => admin_url( 'customize.php?autofocus[section]=title_tagline' ),
'class' => 'button button-primary',
),
);
self::render_notice(
'rx-site-icon-notice',
'info',
__( 'Site Icon Missing', 'rx-theme' ),
__( 'Your website does not have a site icon/favicon yet. Add one to improve branding in browser tabs, bookmarks, and mobile devices.', 'rx-theme' ),
true,
$actions
);
}
/**
* Timezone notice.
*/
public static function timezone_notice() {
if ( self::is_dismissed( 'rx-timezone-notice' ) ) {
return;
}
$timezone = get_option( 'timezone_string' );
if ( ! empty( $timezone ) ) {
return;
}
$actions = array(
array(
'label' => __( 'Set Timezone', 'rx-theme' ),
'url' => admin_url( 'options-general.php' ),
'class' => 'button button-primary',
),
);
self::render_notice(
'rx-timezone-notice',
'info',
__( 'Timezone Is Not Properly Set', 'rx-theme' ),
__( 'Your WordPress timezone is not set by city. Setting the correct timezone helps scheduled posts, cron jobs, analytics, and logs.', 'rx-theme' ),
true,
$actions
);
}
/**
* Upload directory notice.
*/
public static function upload_directory_notice() {
if ( self::is_dismissed( 'rx-upload-dir-notice' ) ) {
return;
}
$upload_dir = wp_upload_dir();
if ( empty( $upload_dir['error'] ) ) {
return;
}
self::render_notice(
'rx-upload-dir-notice',
'error',
__( 'Upload Directory Problem', 'rx-theme' ),
sprintf(
esc_html__( 'WordPress upload directory has a problem: %s', 'rx-theme' ),
esc_html( $upload_dir['error'] )
),
true
);
}
/**
* Required plugin notice.
*/
public static function required_plugins_notice() {
if ( self::is_dismissed( 'rx-required-plugins-notice' ) ) {
return;
}
$missing = array();
if ( ! self::is_plugin_active_by_file( 'classic-editor/classic-editor.php' ) ) {
$missing[] = 'Classic Editor';
}
if ( empty( $missing ) ) {
return;
}
self::render_notice(
'rx-required-plugins-notice',
'warning',
__( 'RX Theme Required/Useful Plugins Missing', 'rx-theme' ),
sprintf(
esc_html__( 'For the best editing experience, you may install: %s.', 'rx-theme' ),
esc_html( implode( ', ', $missing ) )
),
true
);
}
/**
* Recommended plugin notice.
*/
public static function recommended_plugins_notice() {
if ( self::is_dismissed( 'rx-recommended-plugins-notice' ) ) {
return;
}
$recommended = array();
if ( ! self::has_any_active_plugin(
array(
'wordpress-seo/wp-seo.php',
'rank-math/rank-math.php',
'all-in-one-seo-pack/all_in_one_seo_pack.php',
)
) ) {
$recommended[] = 'SEO plugin';
}
if ( ! self::has_any_active_plugin(
array(
'wordfence/wordfence.php',
'better-wp-security/better-wp-security.php',
'sucuri-scanner/sucuri.php',
)
) ) {
$recommended[] = 'Security plugin';
}
if ( ! self::has_any_active_plugin(
array(
'wp-super-cache/wp-cache.php',
'w3-total-cache/w3-total-cache.php',
'litespeed-cache/litespeed-cache.php',
'wp-rocket/wp-rocket.php',
)
) ) {
$recommended[] = 'Cache plugin';
}
if ( empty( $recommended ) ) {
return;
}
$actions = array(
array(
'label' => __( 'Install Plugins', 'rx-theme' ),
'url' => admin_url( 'plugin-install.php' ),
'class' => 'button button-primary',
),
);
self::render_notice(
'rx-recommended-plugins-notice',
'info',
__( 'Recommended Plugins for RX Theme', 'rx-theme' ),
sprintf(
esc_html__( 'For better SEO, speed, and security, you may add: %s.', 'rx-theme' ),
esc_html( implode( ', ', $recommended ) )
),
true,
$actions
);
}
/**
* WooCommerce notice.
*/
public static function woocommerce_notice() {
if ( self::is_dismissed( 'rx-woocommerce-notice' ) ) {
return;
}
if ( class_exists( 'WooCommerce' ) ) {
return;
}
if ( ! current_theme_supports( 'woocommerce' ) ) {
return;
}
self::render_notice(
'rx-woocommerce-notice',
'info',
__( 'WooCommerce Support Available', 'rx-theme' ),
__( 'RX Theme supports WooCommerce layout. Install WooCommerce only if you want to create an online store.', 'rx-theme' ),
true
);
}
/**
* Elementor notice.
*/
public static function elementor_notice() {
if ( self::is_dismissed( 'rx-elementor-notice' ) ) {
return;
}
if ( did_action( 'elementor/loaded' ) ) {
return;
}
self::render_notice(
'rx-elementor-notice',
'info',
__( 'Page Builder Optional', 'rx-theme' ),
__( 'RX Theme can work with Elementor or other page builders, but it is optional. Use it only if you need drag-and-drop design.', 'rx-theme' ),
true
);
}
/**
* SEO plugin notice.
*/
public static function seo_plugin_notice() {
if ( self::is_dismissed( 'rx-seo-plugin-notice' ) ) {
return;
}
if ( self::has_any_active_plugin(
array(
'wordpress-seo/wp-seo.php',
'rank-math/rank-math.php',
'all-in-one-seo-pack/all_in_one_seo_pack.php',
)
) ) {
return;
}
self::render_notice(
'rx-seo-plugin-notice',
'info',
__( 'SEO Plugin Not Detected', 'rx-theme' ),
__( 'For better search visibility, XML sitemap, meta title, meta description, Open Graph, and schema control, install a trusted SEO plugin.', 'rx-theme' ),
true
);
}
/**
* Cache plugin notice.
*/
public static function cache_plugin_notice() {
if ( self::is_dismissed( 'rx-cache-plugin-notice' ) ) {
return;
}
if ( self::has_any_active_plugin(
array(
'wp-super-cache/wp-cache.php',
'w3-total-cache/w3-total-cache.php',
'litespeed-cache/litespeed-cache.php',
'wp-rocket/wp-rocket.php',
'autoptimize/autoptimize.php',
)
) ) {
return;
}
self::render_notice(
'rx-cache-plugin-notice',
'info',
__( 'Cache Plugin Not Detected', 'rx-theme' ),
__( 'A cache/performance plugin can improve page speed, Core Web Vitals, CSS/JS optimization, and user experience.', 'rx-theme' ),
true
);
}
/**
* Security plugin notice.
*/
public static function security_plugin_notice() {
if ( self::is_dismissed( 'rx-security-plugin-notice' ) ) {
return;
}
if ( self::has_any_active_plugin(
array(
'wordfence/wordfence.php',
'better-wp-security/better-wp-security.php',
'sucuri-scanner/sucuri.php',
)
) ) {
return;
}
self::render_notice(
'rx-security-plugin-notice',
'warning',
__( 'Security Plugin Not Detected', 'rx-theme' ),
__( 'For login protection, firewall, malware scanning, and brute-force protection, consider adding a security plugin.', 'rx-theme' ),
true
);
}
/**
* Backup plugin notice.
*/
public static function backup_plugin_notice() {
if ( self::is_dismissed( 'rx-backup-plugin-notice' ) ) {
return;
}
if ( self::has_any_active_plugin(
array(
'updraftplus/updraftplus.php',
'backwpup/backwpup.php',
'duplicator/duplicator.php',
)
) ) {
return;
}
self::render_notice(
'rx-backup-plugin-notice',
'info',
__( 'Backup Plugin Not Detected', 'rx-theme' ),
__( 'Regular backups protect your website from hosting problems, hacking, mistakes, and failed updates.', 'rx-theme' ),
true
);
}
/**
* Theme file permission notice.
*/
public static function theme_file_permission_notice() {
if ( self::is_dismissed( 'rx-theme-permission-notice' ) ) {
return;
}
$stylesheet_dir = get_stylesheet_directory();
if ( is_readable( $stylesheet_dir ) ) {
return;
}
self::render_notice(
'rx-theme-permission-notice',
'error',
__( 'Theme Directory Permission Issue', 'rx-theme' ),
__( 'RX Theme directory is not readable by WordPress. Please check your file permissions from hosting file manager or FTP.', 'rx-theme' ),
true
);
}
/**
* Memory limit notice.
*/
public static function memory_limit_notice() {
if ( self::is_dismissed( 'rx-memory-limit-notice' ) ) {
return;
}
$memory_limit = wp_convert_hr_to_bytes( WP_MEMORY_LIMIT );
$recommended = 128 * MB_IN_BYTES;
if ( $memory_limit >= $recommended ) {
return;
}
self::render_notice(
'rx-memory-limit-notice',
'warning',
__( 'Low WordPress Memory Limit', 'rx-theme' ),
sprintf(
esc_html__( 'Your WordPress memory limit is %s. RX Theme recommends at least 128M for better admin performance.', 'rx-theme' ),
esc_html( WP_MEMORY_LIMIT )
),
true
);
}
/**
* Maintenance mode notice.
*/
public static function maintenance_mode_notice() {
if ( ! file_exists( ABSPATH . '.maintenance' ) ) {
return;
}
self::render_notice(
'rx-maintenance-mode-notice',
'warning',
__( 'Maintenance File Detected', 'rx-theme' ),
__( 'A .maintenance file exists in your WordPress root directory. If your site is stuck in maintenance mode, remove that file carefully.', 'rx-theme' ),
false
);
}
/**
* Search engine visibility notice.
*/
public static function discourage_search_engine_notice() {
if ( self::is_dismissed( 'rx-search-engine-notice' ) ) {
return;
}
if ( ! get_option( 'blog_public' ) ) {
$actions = array(
array(
'label' => __( 'Open Reading Settings', 'rx-theme' ),
'url' => admin_url( 'options-reading.php' ),
'class' => 'button button-primary',
),
);
self::render_notice(
'rx-search-engine-notice',
'warning',
__( 'Search Engines Are Discouraged', 'rx-theme' ),
__( 'Your website currently discourages search engines from indexing it. If this is a live website, enable search engine visibility.', 'rx-theme' ),
true,
$actions
);
}
}
/**
* Register dashboard widget.
*/
public static function register_dashboard_widget() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
wp_add_dashboard_widget(
'rx_theme_status_widget',
__( 'RX Theme Status', 'rx-theme' ),
array( __CLASS__, 'render_dashboard_widget' )
);
}
/**
* Dashboard widget content.
*/
public static function render_dashboard_widget() {
?>
<div class="rx-theme-dashboard-widget">
<p><strong><?php esc_html_e( 'Website health quick overview:', 'rx-theme' ); ?></strong></p>
<ul>
<li>
<?php esc_html_e( 'PHP Version:', 'rx-theme' ); ?>
<?php if ( version_compare( PHP_VERSION, self::MIN_PHP_VERSION, '>=' ) ) : ?>
<span class="rx-theme-status-good"><?php echo esc_html( PHP_VERSION ); ?></span>
<?php else : ?>
<span class="rx-theme-status-danger"><?php echo esc_html( PHP_VERSION ); ?></span>
<?php endif; ?>
</li>
<li>
<?php esc_html_e( 'SSL:', 'rx-theme' ); ?>
<?php if ( is_ssl() ) : ?>
<span class="rx-theme-status-good"><?php esc_html_e( 'Enabled', 'rx-theme' ); ?></span>
<?php else : ?>
<span class="rx-theme-status-warning"><?php esc_html_e( 'Not enabled', 'rx-theme' ); ?></span>
<?php endif; ?>
</li>
<li>
<?php esc_html_e( 'Permalinks:', 'rx-theme' ); ?>
<?php if ( get_option( 'permalink_structure' ) ) : ?>
<span class="rx-theme-status-good"><?php esc_html_e( 'Pretty URLs enabled', 'rx-theme' ); ?></span>
<?php else : ?>
<span class="rx-theme-status-warning"><?php esc_html_e( 'Plain URLs', 'rx-theme' ); ?></span>
<?php endif; ?>
</li>
<li>
<?php esc_html_e( 'Search Engine Visibility:', 'rx-theme' ); ?>
<?php if ( get_option( 'blog_public' ) ) : ?>
<span class="rx-theme-status-good"><?php esc_html_e( 'Indexing allowed', 'rx-theme' ); ?></span>
<?php else : ?>
<span class="rx-theme-status-danger"><?php esc_html_e( 'Indexing discouraged', 'rx-theme' ); ?></span>
<?php endif; ?>
</li>
<li>
<?php esc_html_e( 'Site Icon:', 'rx-theme' ); ?>
<?php if ( has_site_icon() ) : ?>
<span class="rx-theme-status-good"><?php esc_html_e( 'Added', 'rx-theme' ); ?></span>
<?php else : ?>
<span class="rx-theme-status-warning"><?php esc_html_e( 'Missing', 'rx-theme' ); ?></span>
<?php endif; ?>
</li>
</ul>
<p>
<a class="button button-primary" href="<?php echo esc_url( admin_url( 'themes.php?page=rx-theme-notices' ) ); ?>">
<?php esc_html_e( 'Open RX Theme Notices', 'rx-theme' ); ?>
</a>
<a class="button" href="<?php echo esc_url( admin_url( 'customize.php' ) ); ?>">
<?php esc_html_e( 'Customize Theme', 'rx-theme' ); ?>
</a>
</p>
</div>
<?php
}
/**
* Register notice page.
*/
public static function register_notice_page() {
add_theme_page(
__( 'RX Theme Notices', 'rx-theme' ),
__( 'RX Notices', 'rx-theme' ),
'manage_options',
'rx-theme-notices',
array( __CLASS__, 'render_notice_page' )
);
}
/**
* Render notice management page.
*/
public static function render_notice_page() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
if ( isset( $_POST['rx_reset_notices'] ) && check_admin_referer( 'rx_reset_notices_action', 'rx_reset_notices_nonce' ) ) {
delete_option( self::DISMISSED_OPTION );
delete_transient( 'rx_theme_show_welcome_notice' );
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'RX Theme notices have been reset.', 'rx-theme' ) . '</p></div>';
}
$dismissed = self::get_dismissed_notices();
?>
<div class="wrap">
<h1><?php esc_html_e( 'RX Theme Notices', 'rx-theme' ); ?></h1>
<p>
<?php esc_html_e( 'This page helps you manage RX Theme admin notices, dismissed warnings, and site health recommendations.', 'rx-theme' ); ?>
</p>
<h2><?php esc_html_e( 'Dismissed Notices', 'rx-theme' ); ?></h2>
<?php if ( empty( $dismissed ) ) : ?>
<p><?php esc_html_e( 'No dismissed notices found.', 'rx-theme' ); ?></p>
<?php else : ?>
<ul>
<?php foreach ( $dismissed as $notice_id => $time ) : ?>
<li>
<code><?php echo esc_html( $notice_id ); ?></code>
— <?php echo esc_html( date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), absint( $time ) ) ); ?>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<form method="post">
<?php wp_nonce_field( 'rx_reset_notices_action', 'rx_reset_notices_nonce' ); ?>
<p>
<button type="submit" name="rx_reset_notices" class="button button-primary">
<?php esc_html_e( 'Reset All Dismissed Notices', 'rx-theme' ); ?>
</button>
</p>
</form>
<hr>
<h2><?php esc_html_e( 'RX Theme Site Checklist', 'rx-theme' ); ?></h2>
<ul style="list-style:disc;margin-left:20px;">
<li><?php esc_html_e( 'Use updated WordPress version.', 'rx-theme' ); ?></li>
<li><?php esc_html_e( 'Use PHP 7.4 or higher.', 'rx-theme' ); ?></li>
<li><?php esc_html_e( 'Enable SSL/HTTPS.', 'rx-theme' ); ?></li>
<li><?php esc_html_e( 'Set post name permalink.', 'rx-theme' ); ?></li>
<li><?php esc_html_e( 'Add site icon/favicon.', 'rx-theme' ); ?></li>
<li><?php esc_html_e( 'Install SEO plugin.', 'rx-theme' ); ?></li>
<li><?php esc_html_e( 'Install cache/performance plugin.', 'rx-theme' ); ?></li>
<li><?php esc_html_e( 'Install security plugin.', 'rx-theme' ); ?></li>
<li><?php esc_html_e( 'Install backup plugin.', 'rx-theme' ); ?></li>
<li><?php esc_html_e( 'Disable WP_DEBUG on live site.', 'rx-theme' ); ?></li>
</ul>
</div>
<?php
}
/**
* Render reusable admin notice.
*/
private static function render_notice( $id, $type, $title, $message, $dismissible = true, $actions = array() ) {
if ( $dismissible && self::is_dismissed( $id ) ) {
return;
}
$allowed_types = array( 'success', 'error', 'warning', 'info' );
if ( ! in_array( $type, $allowed_types, true ) ) {
$type = 'info';
}
$classes = array(
'notice',
'notice-' . $type,
'rx-notice',
);
if ( $dismissible ) {
$classes[] = 'is-dismissible';
}
?>
<div class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>" data-notice-id="<?php echo esc_attr( $id ); ?>">
<p class="rx-notice-title"><?php echo esc_html( $title ); ?></p>
<p><?php echo wp_kses_post( $message ); ?></p>
<?php if ( ! empty( $actions ) && is_array( $actions ) ) : ?>
<p class="rx-notice-actions">
<?php foreach ( $actions as $action ) : ?>
<?php
$label = isset( $action['label'] ) ? $action['label'] : '';
$url = isset( $action['url'] ) ? $action['url'] : '#';
$class = isset( $action['class'] ) ? $action['class'] : 'button';
if ( empty( $label ) ) {
continue;
}
?>
<a class="<?php echo esc_attr( $class ); ?>" href="<?php echo esc_url( $url ); ?>">
<?php echo esc_html( $label ); ?>
</a>
<?php endforeach; ?>
</p>
<?php endif; ?>
</div>
<?php
}
/**
* AJAX dismiss notice.
*/
public static function ajax_dismiss_notice() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error(
array(
'message' => __( 'Permission denied.', 'rx-theme' ),
),
403
);
}
check_ajax_referer( 'rx_theme_dismiss_notice_nonce', 'nonce' );
$notice_id = isset( $_POST['notice_id'] ) ? sanitize_key( wp_unslash( $_POST['notice_id'] ) ) : '';
if ( empty( $notice_id ) ) {
wp_send_json_error(
array(
'message' => __( 'Invalid notice ID.', 'rx-theme' ),
),
400
);
}
self::dismiss_notice( $notice_id );
wp_send_json_success(
array(
'message' => __( 'Notice dismissed.', 'rx-theme' ),
)
);
}
/**
* Dismiss notice.
*/
private static function dismiss_notice( $notice_id ) {
$dismissed = self::get_dismissed_notices();
$dismissed[ $notice_id ] = time();
update_option( self::DISMISSED_OPTION, $dismissed, false );
}
/**
* Check notice dismissed.
*/
private static function is_dismissed( $notice_id ) {
$dismissed = self::get_dismissed_notices();
return isset( $dismissed[ $notice_id ] );
}
/**
* Get dismissed notices.
*/
private static function get_dismissed_notices() {
$dismissed = get_option( self::DISMISSED_OPTION, array() );
if ( ! is_array( $dismissed ) ) {
$dismissed = array();
}
return $dismissed;
}
/**
* Check if plugin active by file.
*/
private static function is_plugin_active_by_file( $plugin_file ) {
if ( ! function_exists( 'is_plugin_active' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
if ( is_plugin_active( $plugin_file ) ) {
return true;
}
if ( is_multisite() && function_exists( 'is_plugin_active_for_network' ) && is_plugin_active_for_network( $plugin_file ) ) {
return true;
}
return false;
}
/**
* Check if any plugin from list is active.
*/
private static function has_any_active_plugin( $plugins ) {
if ( empty( $plugins ) || ! is_array( $plugins ) ) {
return false;
}
foreach ( $plugins as $plugin ) {
if ( self::is_plugin_active_by_file( $plugin ) ) {
return true;
}
}
return false;
}
}
endif;
RX_Theme_Admin_Notices::init();
Now include it in your theme functions.php:
/**
* RX Theme admin notices.
*/
if ( is_admin() ) {
$rx_notice_file = get_template_directory() . '/inc/admin/notice.php';
if ( file_exists( $rx_notice_file ) ) {
require_once $rx_notice_file;
}
}
Recommended folder structure:
rx-theme/
├── functions.php
└── inc/
└── admin/
└── notice.php
Important: this file is for admin area only, so it should not slow down your public frontend pages.