* The admin-panel specific functionality of the plugin.
* @subpackage LiteSpeed/admin
* @author LiteSpeed Technologies <info@litespeedtech.com>
defined('WPINC') || exit();
class Admin_Display extends Base
const NOTICE_BLUE = 'notice notice-info';
const NOTICE_GREEN = 'notice notice-success';
const NOTICE_RED = 'notice notice-error';
const NOTICE_YELLOW = 'notice notice-warning';
const DB_MSG = 'messages';
const DB_MSG_PIN = 'msg_pin';
const PURGEBYOPT_SELECT = 'purgeby';
const PURGEBYOPT_LIST = 'purgebylist';
const DB_DISMISS_MSG = 'dismiss';
const RULECONFLICT_ON = 'ExpiresDefault_1';
const RULECONFLICT_DISMISSED = 'ExpiresDefault_0';
protected $messages = array();
protected $default_settings = array();
protected $_is_network_admin = false;
protected $_is_multisite = false;
* Initialize the class and set its properties.
public function __construct()
add_action('admin_enqueue_scripts', array($this, 'enqueue_style'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts'));
$this->_is_network_admin = is_network_admin();
$this->_is_multisite = is_multisite();
if (is_multisite() && $this->_is_network_admin) {
$manage = 'manage_network_options';
$manage = 'manage_options';
if (current_user_can($manage)) {
if (!defined('LITESPEED_DISABLE_ALL')) {
add_action('wp_before_admin_bar_render', array(GUI::cls(), 'backend_shortcut'));
// `admin_notices` is after `admin_enqueue_scripts`
// @see wp-admin/admin-header.php
add_action($this->_is_network_admin ? 'network_admin_notices' : 'admin_notices', array($this, 'display_messages'));
* In case this is called outside the admin page
* @see https://codex.wordpress.org/Function_Reference/is_plugin_active_for_network
if (!function_exists('is_plugin_active_for_network')) {
require_once ABSPATH . '/wp-admin/includes/plugin.php';
// add menus ( Also check for mu-plugins)
if ($this->_is_network_admin && (is_plugin_active_for_network(LSCWP_BASENAME) || defined('LSCWP_MU_PLUGIN'))) {
add_action('network_admin_menu', array($this, 'register_admin_menu'));
add_action('admin_menu', array($this, 'register_admin_menu'));
$this->cls('Metabox')->register_settings();
* Show the title of one line
public function title($id)
* Register the admin menu display.
public function register_admin_menu()
$capability = $this->_is_network_admin ? 'manage_network_options' : 'manage_options';
if (current_user_can($capability)) {
add_menu_page('LiteSpeed Cache', 'LiteSpeed Cache', 'manage_options', 'litespeed');
$this->_add_submenu(__('Dashboard', 'litespeed-cache'), 'litespeed', 'show_menu_dash');
!$this->_is_network_admin && $this->_add_submenu(__('Presets', 'litespeed-cache'), 'litespeed-presets', 'show_menu_presets');
$this->_add_submenu(__('General', 'litespeed-cache'), 'litespeed-general', 'show_menu_general');
$this->_add_submenu(__('Cache', 'litespeed-cache'), 'litespeed-cache', 'show_menu_cache');
!$this->_is_network_admin && $this->_add_submenu(__('CDN', 'litespeed-cache'), 'litespeed-cdn', 'show_menu_cdn');
$this->_add_submenu(__('Image Optimization', 'litespeed-cache'), 'litespeed-img_optm', 'show_img_optm');
!$this->_is_network_admin && $this->_add_submenu(__('Page Optimization', 'litespeed-cache'), 'litespeed-page_optm', 'show_page_optm');
$this->_add_submenu(__('Database', 'litespeed-cache'), 'litespeed-db_optm', 'show_db_optm');
!$this->_is_network_admin && $this->_add_submenu(__('Crawler', 'litespeed-cache'), 'litespeed-crawler', 'show_crawler');
$this->_add_submenu(__('Toolbox', 'litespeed-cache'), 'litespeed-toolbox', 'show_toolbox');
// sub menus under options
add_options_page('LiteSpeed Cache', 'LiteSpeed Cache', $capability, 'litespeed-cache-options', array($this, 'show_menu_cache'));
* Helper function to set up a submenu page.
* @param string $menu_title The title that appears on the menu.
* @param string $menu_slug The slug of the page.
* @param string $callback The callback to call if selected.
private function _add_submenu($menu_title, $menu_slug, $callback)
add_submenu_page('litespeed', $menu_title, $menu_title, 'manage_options', $menu_slug, array($this, $callback));
* Register the stylesheets for the admin area.
public function enqueue_style()
wp_enqueue_style(Core::PLUGIN_NAME, LSWCP_PLUGIN_URL . 'assets/css/litespeed.css', array(), Core::VER, 'all');
* Register the JavaScript for the admin area.
public function enqueue_scripts()
wp_register_script(Core::PLUGIN_NAME, LSWCP_PLUGIN_URL . 'assets/js/litespeed-cache-admin.js', array(), Core::VER, false);
$localize_data = array();
if (GUI::has_whm_msg()) {
$ajax_url_dismiss_whm = Utility::build_url(Core::ACTION_DISMISS, GUI::TYPE_DISMISS_WHM, true);
$localize_data['ajax_url_dismiss_whm'] = $ajax_url_dismiss_whm;
if (GUI::has_msg_ruleconflict()) {
$ajax_url = Utility::build_url(Core::ACTION_DISMISS, GUI::TYPE_DISMISS_EXPIRESDEFAULT, true);
$localize_data['ajax_url_dismiss_ruleconflict'] = $ajax_url;
$promo_tag = GUI::cls()->show_promo(true);
$ajax_url_promo = Utility::build_url(Core::ACTION_DISMISS, GUI::TYPE_DISMISS_PROMO, true, null, array('promo_tag' => $promo_tag));
$localize_data['ajax_url_promo'] = $ajax_url_promo;
// Injection to LiteSpeed pages
if ($pagenow == 'admin.php' && !empty($_GET['page']) && (strpos($_GET['page'], 'litespeed-') === 0 || $_GET['page'] == 'litespeed')) {
add_filter('admin_footer_text', array($this, 'admin_footer_text'), 1);
if ($_GET['page'] == 'litespeed-crawler' || $_GET['page'] == 'litespeed-cdn') {
// Babel JS type correction
add_filter('script_loader_tag', array($this, 'babel_type'), 10, 3);
wp_enqueue_script(Core::PLUGIN_NAME . '-lib-react', LSWCP_PLUGIN_URL . 'assets/js/react.min.js', array(), Core::VER, false);
wp_enqueue_script(Core::PLUGIN_NAME . '-lib-babel', LSWCP_PLUGIN_URL . 'assets/js/babel.min.js', array(), Core::VER, false);
// Crawler Cookie Simulation
if ($_GET['page'] == 'litespeed-crawler') {
wp_enqueue_script(Core::PLUGIN_NAME . '-crawler', LSWCP_PLUGIN_URL . 'assets/js/component.crawler.js', array(), Core::VER, false);
$localize_data['lang'] = array();
$localize_data['lang']['cookie_name'] = __('Cookie Name', 'litespeed-cache');
$localize_data['lang']['cookie_value'] = __('Cookie Values', 'litespeed-cache');
$localize_data['lang']['one_per_line'] = Doc::one_per_line(true);
$localize_data['lang']['remove_cookie_simulation'] = __('Remove cookie simulation', 'litespeed-cache');
$localize_data['lang']['add_cookie_simulation_row'] = __('Add new cookie to simulate', 'litespeed-cache');
empty($localize_data['ids']) && ($localize_data['ids'] = array());
$localize_data['ids']['crawler_cookies'] = self::O_CRAWLER_COOKIES;
if ($_GET['page'] == 'litespeed-cdn') {
$home_url = home_url('/');
$parsed = parse_url($home_url);
$home_url = str_replace($parsed['scheme'] . ':', '', $home_url);
$cdn_url = 'https://cdn.' . substr($home_url, 2);
wp_enqueue_script(Core::PLUGIN_NAME . '-cdn', LSWCP_PLUGIN_URL . 'assets/js/component.cdn.js', array(), Core::VER, false);
$localize_data['lang'] = array();
$localize_data['lang']['cdn_mapping_url'] = Lang::title(self::CDN_MAPPING_URL);
$localize_data['lang']['cdn_mapping_inc_img'] = Lang::title(self::CDN_MAPPING_INC_IMG);
$localize_data['lang']['cdn_mapping_inc_css'] = Lang::title(self::CDN_MAPPING_INC_CSS);
$localize_data['lang']['cdn_mapping_inc_js'] = Lang::title(self::CDN_MAPPING_INC_JS);
$localize_data['lang']['cdn_mapping_filetype'] = Lang::title(self::CDN_MAPPING_FILETYPE);
$localize_data['lang']['cdn_mapping_url_desc'] = sprintf(__('CDN URL to be used. For example, %s', 'litespeed-cache'), '<code>' . $cdn_url . '</code>');
$localize_data['lang']['one_per_line'] = Doc::one_per_line(true);
$localize_data['lang']['cdn_mapping_remove'] = __('Remove CDN URL', 'litespeed-cache');
$localize_data['lang']['add_cdn_mapping_row'] = __('Add new CDN URL', 'litespeed-cache');
$localize_data['lang']['on'] = __('ON', 'litespeed-cache');
$localize_data['lang']['off'] = __('OFF', 'litespeed-cache');
empty($localize_data['ids']) && ($localize_data['ids'] = array());
$localize_data['ids']['cdn_mapping'] = self::O_CDN_MAPPING;
// If on Server IP setting page, append getIP link
if ($_GET['page'] == 'litespeed-general') {
$localize_data['ajax_url_getIP'] = function_exists('get_rest_url') ? get_rest_url(null, 'litespeed/v1/tool/check_ip') : '/';
$localize_data['nonce'] = wp_create_nonce('wp_rest');
// Activate or deactivate a specific crawler
if ($_GET['page'] == 'litespeed-crawler') {
$localize_data['ajax_url_crawler_switch'] = function_exists('get_rest_url') ? get_rest_url(null, 'litespeed/v1/toggle_crawler_state') : '/';
$localize_data['nonce'] = wp_create_nonce('wp_rest');
wp_localize_script(Core::PLUGIN_NAME, 'litespeed_data', $localize_data);
wp_enqueue_script(Core::PLUGIN_NAME);
public function babel_type($tag, $handle, $src)
if ($handle != Core::PLUGIN_NAME . '-crawler' && $handle != Core::PLUGIN_NAME . '-cdn') {
return '<script src="' . $src . '" type="text/babel"></script>';
* Callback that adds LiteSpeed Cache's action links.
* @param array $links Previously added links from other plugins.
* @return array Links array with the litespeed cache one appended.
public function add_plugin_links($links)
// $links[] = '<a href="' . admin_url('options-general.php?page=litespeed-cache') . '">' . __('Settings', 'litespeed-cache') . '</a>';
$links[] = '<a href="' . admin_url('admin.php?page=litespeed-cache') . '">' . __('Settings', 'litespeed-cache') . '</a>';
* Change the admin footer text on LiteSpeed Cache admin pages.
* @param string $footer_text
public function admin_footer_text($footer_text)
require_once LSCWP_DIR . 'tpl/inc/admin_footer.php';
* Builds the html for a single notice.
* @param string $color The color to use for the notice.
* @param string $str The notice message.
* @return string The built notice html.
public static function build_notice($color, $str, $irremovable = false)
$cls .= ' litespeed-irremovable';
$cls .= ' is-dismissible';
$str = Lang::maybe_translate($str);
return '<div class="litespeed_icon ' . $cls . '"><p>' . wp_kses_post($str) . '</p></div>';
public static function info($msg, $echo = false, $irremovable = false)
self::add_notice(self::NOTICE_BLUE, $msg, $echo, $irremovable);
public static function note($msg, $echo = false, $irremovable = false)
self::add_notice(self::NOTICE_YELLOW, $msg, $echo, $irremovable);
public static function success($msg, $echo = false, $irremovable = false)
self::add_notice(self::NOTICE_GREEN, $msg, $echo, $irremovable);
public static function succeed($msg, $echo = false, $irremovable = false)
self::success($msg, $echo, $irremovable);
public static function error($msg, $echo = false, $irremovable = false)
self::add_notice(self::NOTICE_RED, $msg, $echo, $irremovable);
public static function add_unique_notice($color_mode, $msgs, $irremovable = false)
'info' => self::NOTICE_BLUE,
'note' => self::NOTICE_YELLOW,
'success' => self::NOTICE_GREEN,
'error' => self::NOTICE_RED,
if (empty($color_map[$color_mode])) {
self::debug('Wrong admin display color mode!');
$color = $color_map[$color_mode];
// Go through to make sure unique
$filtered_msgs = array();
foreach ($msgs as $k => $str) {
} // Use key to make it overwritable to previous same msg
$filtered_msgs[$k] = $str;
self::add_notice($color, $filtered_msgs, false, $irremovable);
* Adds a notice to display on the admin page
public static function add_notice($color, $msg, $echo = false, $irremovable = false)
// self::debug("add_notice msg", $msg);
// Bypass adding for CLI or cron
if (defined('LITESPEED_CLI') || defined('DOING_CRON')) {
// WP CLI will show the info directly
if (defined('WP_CLI') && WP_CLI) {
if ($color == self::NOTICE_RED) {
\WP_CLI::error($v, false);
echo self::build_notice($color, $msg);
$msg_name = $irremovable ? self::DB_MSG_PIN : self::DB_MSG;
$messages = self::get_option($msg_name, array());
if (!is_array($messages)) {
foreach ($msg as $k => $str) {
$messages[$k] = self::build_notice($color, $str, $irremovable);
$messages[] = self::build_notice($color, $msg, $irremovable);
$messages = array_unique($messages);
self::update_option($msg_name, $messages);
* Display notices and errors in dashboard
public function display_messages()
if (!defined('LITESPEED_CONF_LOADED')) {
if (GUI::has_whm_msg()) {
$this->show_display_installed();
Data::cls()->check_upgrading_msg();
// If is in dev version, always check latest update
Cloud::cls()->check_dev_version();
$messages = self::get_option(self::DB_MSG, array());
if (is_array($messages)) {
foreach ($messages as $msg) {
if (strpos($msg, 'TB_iframe') && !$added_thickbox) {