plugin_slug = $plugin->get_plugin_slug(); $this->plugin_settings = $plugin->get_plugin_settings(); $this->plugin_default_settings = $plugin->default_settings(); $this->plugin_basename = plugin_basename(WPMM_PATH . $this->plugin_slug . '.php'); // Load admin style sheet and JavaScript. add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_styles')); add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts')); // Add the options page and menu item. add_action('admin_menu', array($this, 'add_plugin_menu')); // Add an action link pointing to the options page if (is_multisite() && is_plugin_active_for_network($this->plugin_basename)) { // settings link will point to admin_url of the main blog, not to network_admin_url add_filter('network_admin_plugin_action_links_' . $this->plugin_basename, array($this, 'add_settings_link')); } else { add_filter('plugin_action_links_' . $this->plugin_basename, array($this, 'add_settings_link')); } // Add admin notices add_action('admin_notices', array($this, 'add_notices')); // Add ajax methods add_action('wp_ajax_wpmm_subscribers_export', array($this, 'subscribers_export')); add_action('wp_ajax_wpmm_subscribers_empty_list', array($this, 'subscribers_empty_list')); add_action('wp_ajax_wpmm_dismiss_notices', array($this, 'dismiss_notices')); add_action('wp_ajax_wpmm_reset_settings', array($this, 'reset_settings')); // Add text to footer add_filter('admin_footer_text', array($this, 'admin_footer_text'), 5); } public static function get_instance() { if (null == self::$instance) { self::$instance = new self; } return self::$instance; } /** * Load CSS files * * @since 2.0.0 * @return type */ public function enqueue_admin_styles() { if (!isset($this->plugin_screen_hook_suffix)) { return; } $screen = get_current_screen(); if ($this->plugin_screen_hook_suffix == $screen->id) { $wp_scripts = wp_scripts(); $ui = $wp_scripts->query('jquery-ui-core'); wp_enqueue_style($this->plugin_slug . '-admin-jquery-ui-styles', '//ajax.googleapis.com/ajax/libs/jqueryui/' . (!empty($ui->ver) ? $ui->ver : '1.11.4') . '/themes/smoothness/jquery-ui' . WPMM_ASSETS_SUFFIX . '.css', array(), WP_Maintenance_Mode::VERSION); wp_enqueue_style($this->plugin_slug . '-admin-chosen', WPMM_CSS_URL . 'chosen' . WPMM_ASSETS_SUFFIX . '.css', array(), WP_Maintenance_Mode::VERSION); wp_enqueue_style($this->plugin_slug . '-admin-timepicker-addon-script', WPMM_CSS_URL . 'jquery-ui-timepicker-addon' . WPMM_ASSETS_SUFFIX . '.css', array(), WP_Maintenance_Mode::VERSION); wp_enqueue_style($this->plugin_slug . '-admin-styles', WPMM_CSS_URL . 'style-admin' . WPMM_ASSETS_SUFFIX . '.css', array('wp-color-picker'), WP_Maintenance_Mode::VERSION); } } /** * Load JS files and their dependencies * * @since 2.0.0 * @return */ public function enqueue_admin_scripts() { if (!isset($this->plugin_screen_hook_suffix)) { return; } $screen = get_current_screen(); if ($this->plugin_screen_hook_suffix == $screen->id) { wp_enqueue_media(); wp_enqueue_script($this->plugin_slug . '-admin-timepicker-addon-script', WPMM_JS_URL . 'jquery-ui-timepicker-addon' . WPMM_ASSETS_SUFFIX . '.js', array('jquery', 'jquery-ui-datepicker'), WP_Maintenance_Mode::VERSION); wp_enqueue_script($this->plugin_slug . '-admin-script', WPMM_JS_URL . 'scripts-admin' . WPMM_ASSETS_SUFFIX . '.js', array('jquery', 'wp-color-picker'), WP_Maintenance_Mode::VERSION); wp_enqueue_script($this->plugin_slug . '-admin-chosen', WPMM_JS_URL . 'chosen.jquery' . WPMM_ASSETS_SUFFIX . '.js', array(), WP_Maintenance_Mode::VERSION); wp_localize_script($this->plugin_slug . '-admin-script', 'wpmm_vars', array( 'ajax_url' => admin_url('admin-ajax.php'), 'plugin_url' => admin_url('options-general.php?page=' . $this->plugin_slug) )); } // For global actions like dismiss notices wp_enqueue_script($this->plugin_slug . '-admin-global', WPMM_JS_URL . 'scripts-admin-global' . WPMM_ASSETS_SUFFIX . '.js', array('jquery'), WP_Maintenance_Mode::VERSION); } /** * Export subscribers list in CSV format (refactor @ 2.0.4) * * @since 2.0.0 * @global object $wpdb * @throws Exception */ public function subscribers_export() { global $wpdb; try { // check capabilities if (!current_user_can('manage_options')) { throw new Exception(__('You do not have access to this resource.', $this->plugin_slug)); } // get subscribers and export $results = $wpdb->get_results("SELECT email, insert_date FROM {$wpdb->prefix}wpmm_subscribers ORDER BY id_subscriber DESC", ARRAY_A); if (!empty($results)) { $filename = 'subscribers-list-' . date('Y-m-d') . '.csv'; header('Content-Type: text/csv'); header('Content-Disposition: attachment;filename=' . $filename); $fp = fopen('php://output', 'w'); fputcsv($fp, array('email', 'insert_date')); foreach ($results as $item) { fputcsv($fp, $item); } fclose($fp); } } catch (Exception $ex) { wp_send_json_error($ex->getMessage()); } } /** * Empty subscribers list * * @since 2.0.4 * @global object $wpdb * @throws Exception */ public function subscribers_empty_list() { global $wpdb; try { // check capabilities if (!current_user_can('manage_options')) { throw new Exception(__('You do not have access to this resource.', $this->plugin_slug)); } // delete all subscribers $wpdb->query("DELETE FROM {$wpdb->prefix}wpmm_subscribers"); wp_send_json_success(sprintf(__('You have %d subscriber(s)', $this->plugin_slug), 0)); } catch (Exception $ex) { wp_send_json_error($ex->getMessage()); } } /** * Reset settings (refactor @ 2.0.4) * * @since 2.0.0 * @throws Exception */ public function reset_settings() { try { // check capabilities if (!current_user_can('manage_options')) { throw new Exception(__('You do not have access to this resource.', $this->plugin_slug)); } // check nonce existence if (empty($_POST['_wpnonce'])) { throw new Exception(__('The nonce field must not be empty.', $this->plugin_slug)); } // check tab existence if (empty($_POST['tab'])) { throw new Exception(__('The tab slug must not be empty.', $this->plugin_slug)); } // check nonce validation if (!wp_verify_nonce($_POST['_wpnonce'], 'tab-' . $_POST['tab'])) { throw new Exception(__('Security check.', $this->plugin_slug)); } // check existence in plugin default settings $tab = $_POST['tab']; if (empty($this->plugin_default_settings[$tab])) { throw new Exception(__('The tab slug must exist.', $this->plugin_slug)); } // update options using the default values $this->plugin_settings[$tab] = $this->plugin_default_settings[$tab]; update_option('wpmm_settings', $this->plugin_settings); wp_send_json_success(); } catch (Exception $ex) { wp_send_json_error($ex->getMessage()); } } /** * Add plugin in Settings menu * * @since 2.0.0 */ public function add_plugin_menu() { $this->plugin_screen_hook_suffix = add_options_page( __('WP Maintenance Mode', $this->plugin_slug), __('WP Maintenance Mode', $this->plugin_slug), 'manage_options', $this->plugin_slug, array($this, 'display_plugin_settings') ); } /** * Settings page * * @since 2.0.0 * @global object $wp_roles */ public function display_plugin_settings() { global $wp_roles; // save settings $this->save_plugin_settings(); // show settings include_once(WPMM_VIEWS_PATH . 'settings.php'); } /** * Save settings * * @since 2.0.0 */ public function save_plugin_settings() { if (!empty($_POST) && !empty($_POST['tab'])) { if (!wp_verify_nonce($_POST['_wpnonce'], 'tab-' . $_POST['tab'])) { die(__('Security check.', $this->plugin_slug)); } // DO SOME SANITIZATIONS $tab = $_POST['tab']; switch ($tab) { case 'general': $_POST['options']['general']['status'] = (int) $_POST['options']['general']['status']; if (!empty($_POST['options']['general']['status']) && $_POST['options']['general']['status'] == 1) { $_POST['options']['general']['status_date'] = date('Y-m-d H:i:s'); } $_POST['options']['general']['bypass_bots'] = (int) $_POST['options']['general']['bypass_bots']; $_POST['options']['general']['backend_role'] = !empty($_POST['options']['general']['backend_role']) ? $_POST['options']['general']['backend_role'] : array(); $_POST['options']['general']['frontend_role'] = !empty($_POST['options']['general']['frontend_role']) ? $_POST['options']['general']['frontend_role'] : array(); $_POST['options']['general']['meta_robots'] = (int) $_POST['options']['general']['meta_robots']; $_POST['options']['general']['redirection'] = esc_url($_POST['options']['general']['redirection']); if (!empty($_POST['options']['general']['exclude'])) { $exclude_array = explode("\n", $_POST['options']['general']['exclude']); // we need to be sure that empty lines will not be saved $_POST['options']['general']['exclude'] = array_filter(array_map('trim', $exclude_array)); } else { $_POST['options']['general']['exclude'] = array(); } $_POST['options']['general']['notice'] = (int) $_POST['options']['general']['notice']; $_POST['options']['general']['admin_link'] = (int) $_POST['options']['general']['admin_link']; // delete cache when is already activated, when is activated and when is deactivated if ( isset($this->plugin_settings['general']['status']) && isset($_POST['options']['general']['status']) && ( ($this->plugin_settings['general']['status'] == 1 && in_array($_POST['options']['general']['status'], array(0, 1))) || ($this->plugin_settings['general']['status'] == 0 && $_POST['options']['general']['status'] == 1) ) ) { $this->delete_cache(); } break; case 'design': $custom_css = array(); // CONTENT & CUSTOM CSS $_POST['options']['design']['title'] = sanitize_text_field($_POST['options']['design']['title']); $_POST['options']['design']['heading'] = sanitize_text_field($_POST['options']['design']['heading']); if (!empty($_POST['options']['design']['heading_color'])) { $_POST['options']['design']['heading_color'] = sanitize_text_field($_POST['options']['design']['heading_color']); $custom_css['heading_color'] = '.wrap h1 { color: ' . $_POST['options']['design']['heading_color'] . '; }'; } add_filter('safe_style_css', array($this, 'add_safe_style_css')); // add before we save $_POST['options']['design']['text'] = wp_kses_post($_POST['options']['design']['text']); remove_filter('safe_style_css', array($this, 'add_safe_style_css')); // remove after we save if (!empty($_POST['options']['design']['text_color'])) { $_POST['options']['design']['text_color'] = sanitize_text_field($_POST['options']['design']['text_color']); $custom_css['text_color'] = '.wrap h2 { color: ' . $_POST['options']['design']['text_color'] . '; }'; } // BACKGROUND & CUSTOM CSS if (!empty($_POST['options']['design']['bg_type'])) { $_POST['options']['design']['bg_type'] = sanitize_text_field($_POST['options']['design']['bg_type']); if ($_POST['options']['design']['bg_type'] == 'color' && !empty($_POST['options']['design']['bg_color'])) { $_POST['options']['design']['bg_color'] = sanitize_text_field($_POST['options']['design']['bg_color']); $custom_css['bg_color'] = 'body { background-color: ' . $_POST['options']['design']['bg_color'] . '; }'; } if ($_POST['options']['design']['bg_type'] == 'custom' && !empty($_POST['options']['design']['bg_custom'])) { $_POST['options']['design']['bg_custom'] = esc_url($_POST['options']['design']['bg_custom']); $custom_css['bg_url'] = '.background { background: url(' . $_POST['options']['design']['bg_custom'] . ') no-repeat center top fixed; background-size: cover; }'; } if ($_POST['options']['design']['bg_type'] == 'predefined' && !empty($_POST['options']['design']['bg_predefined'])) { $_POST['options']['design']['bg_predefined'] = sanitize_text_field($_POST['options']['design']['bg_predefined']); $custom_css['bg_url'] = '.background { background: url(' . esc_url(WPMM_URL . 'assets/images/backgrounds/' . $_POST['options']['design']['bg_predefined']) . ') no-repeat center top fixed; background-size: cover; }'; } } $_POST['options']['design']['custom_css'] = $custom_css; // delete cache when is activated if (!empty($this->plugin_settings['general']['status']) && $this->plugin_settings['general']['status'] == 1) { $this->delete_cache(); } break; case 'modules': $custom_css = array(); // COUNTDOWN & CUSTOM CSS $_POST['options']['modules']['countdown_status'] = (int) $_POST['options']['modules']['countdown_status']; $_POST['options']['modules']['countdown_start'] = sanitize_text_field($_POST['options']['modules']['countdown_start']); $_POST['options']['modules']['countdown_details'] = array_map('trim', $_POST['options']['modules']['countdown_details']); $_POST['options']['modules']['countdown_details']['days'] = isset($_POST['options']['modules']['countdown_details']['days']) && is_numeric($_POST['options']['modules']['countdown_details']['days']) ? $_POST['options']['modules']['countdown_details']['days'] : 0; $_POST['options']['modules']['countdown_details']['hours'] = isset($_POST['options']['modules']['countdown_details']['hours']) && is_numeric($_POST['options']['modules']['countdown_details']['hours']) ? $_POST['options']['modules']['countdown_details']['hours'] : 1; $_POST['options']['modules']['countdown_details']['minutes'] = isset($_POST['options']['modules']['countdown_details']['minutes']) && is_numeric($_POST['options']['modules']['countdown_details']['minutes']) ? $_POST['options']['modules']['countdown_details']['minutes'] : 0; if (!empty($_POST['options']['modules']['countdown_color'])) { $_POST['options']['modules']['countdown_color'] = sanitize_text_field($_POST['options']['modules']['countdown_color']); $custom_css['countdown_color'] = '.wrap .countdown span { color: ' . $_POST['options']['modules']['countdown_color'] . '; }'; } // SUBSCRIBE & CUSTOM CSS $_POST['options']['modules']['subscribe_status'] = (int) $_POST['options']['modules']['subscribe_status']; $_POST['options']['modules']['subscribe_text'] = sanitize_text_field($_POST['options']['modules']['subscribe_text']); if (!empty($_POST['options']['modules']['subscribe_text_color'])) { $_POST['options']['modules']['subscribe_text_color'] = sanitize_text_field($_POST['options']['modules']['subscribe_text_color']); $custom_css['subscribe_text_color'] = '.wrap h3, .wrap .subscribe_wrapper { color: ' . $_POST['options']['modules']['subscribe_text_color'] . '; }'; } // SOCIAL NETWORKS $_POST['options']['modules']['social_status'] = (int) $_POST['options']['modules']['social_status']; $_POST['options']['modules']['social_target'] = (int) $_POST['options']['modules']['social_target']; $_POST['options']['modules']['social_github'] = sanitize_text_field($_POST['options']['modules']['social_github']); $_POST['options']['modules']['social_dribbble'] = sanitize_text_field($_POST['options']['modules']['social_dribbble']); $_POST['options']['modules']['social_twitter'] = sanitize_text_field($_POST['options']['modules']['social_twitter']); $_POST['options']['modules']['social_facebook'] = sanitize_text_field($_POST['options']['modules']['social_facebook']); $_POST['options']['modules']['social_pinterest'] = sanitize_text_field($_POST['options']['modules']['social_pinterest']); $_POST['options']['modules']['social_google+'] = sanitize_text_field($_POST['options']['modules']['social_google+']); $_POST['options']['modules']['social_linkedin'] = sanitize_text_field($_POST['options']['modules']['social_linkedin']); // CONTACT $_POST['options']['modules']['contact_status'] = (int) $_POST['options']['modules']['contact_status']; $_POST['options']['modules']['contact_email'] = sanitize_text_field($_POST['options']['modules']['contact_email']); $_POST['options']['modules']['contact_effects'] = sanitize_text_field($_POST['options']['modules']['contact_effects']); // GOOGLE ANALYTICS $_POST['options']['modules']['ga_status'] = (int) $_POST['options']['modules']['ga_status']; $_POST['options']['modules']['ga_code'] = wpmm_sanitize_ga_code($_POST['options']['modules']['ga_code']); $_POST['options']['modules']['custom_css'] = $custom_css; // delete cache when is activated if (!empty($this->plugin_settings['general']['status']) && $this->plugin_settings['general']['status'] == 1) { $this->delete_cache(); } break; } $this->plugin_settings[$tab] = $_POST['options'][$tab]; update_option('wpmm_settings', $this->plugin_settings); } } /** * Add new safe inline style css (use by wp_kses_attr in wp_kses_post) * - bug discovered by cokemorgan: https://github.com/Designmodocom/WP-Maintenance-Mode/issues/56 * * @since 2.0.3 * @param array $properties * @return array */ public function add_safe_style_css($properties) { $new_properties = array( 'min-height', 'max-height', 'min-width', 'max-width' ); return array_merge($new_properties, $properties); } /** * Delete cache if any cache plugin (wp_cache or w3tc) is activated * * @since 2.0.1 */ public function delete_cache() { // Super Cache Plugin if (function_exists('wp_cache_clear_cache')) { wp_cache_clear_cache(is_multisite() && is_plugin_active_for_network($this->plugin_basename) ? get_current_blog_id() : ''); } // W3 Total Cache Plugin if (function_exists('w3tc_pgcache_flush')) { w3tc_pgcache_flush(); } } /** * Add settings link * * @since 2.0.0 * @param array $links * @return array */ public function add_settings_link($links) { return array_merge( array( 'wpmm_settings' => '' . __('Settings', $this->plugin_slug) . '' ), $links ); } /** * Add notices - will be displayed on dashboard * * @since 2.0.0 */ public function add_notices() { $screen = get_current_screen(); $notices = array(); if ($this->plugin_screen_hook_suffix != $screen->id) { // notice if plugin is activated if ($this->plugin_settings['general']['status'] == 1 && $this->plugin_settings['general']['notice'] == 1) { $notices['is_activated'] = array( 'class' => 'error', 'msg' => sprintf(__('The Maintenance Mode is active. Please don\'t forget to deactivate as soon as you are done.', $this->plugin_slug), admin_url('options-general.php?page=' . $this->plugin_slug)) ); } // show notice if plugin has a notice saved $wpmm_notice = get_option('wpmm_notice'); if (!empty($wpmm_notice) && is_array($wpmm_notice)) { $notices['other'] = $wpmm_notice; } } else { // delete wpmm_notice delete_option('wpmm_notice'); // notice promo for codepad ob_start(); include_once(WPMM_VIEWS_PATH . 'promo-strictthemes.php'); $notices['promo-strictthemes'] = array( 'class' => 'wpmm_notices updated notice is-dismissible', 'msg' => ob_get_clean() ); } // get dismissed notices $dismissed_notices = $this->get_dismissed_notices(get_current_user_id()); // template include_once(WPMM_VIEWS_PATH . 'notice.php'); } /** * Dismiss plugin notices via AJAX * * @throws Exception */ public function dismiss_notices() { try { if (empty($_POST['notice_key'])) { throw new Exception(__('Notice key cannot be empty.', $this->plugin_slug)); } // save new notice key $notice_key = sanitize_text_field($_POST['notice_key']); $this->save_dismissed_notices(get_current_user_id(), $notice_key); wp_send_json_success(); } catch (Exception $ex) { wp_send_json_error($ex->getMessage()); } } /** * Get dismissed notices * * @param int $user_id * @return array */ public function get_dismissed_notices($user_id) { $dismissed_notices = get_user_meta($user_id, $this->dismissed_notices_key, true); return array_filter(explode(',', $dismissed_notices), 'trim'); } /** * Save dismissed notices * - save as string because of http://wordpress.stackexchange.com/questions/13353/problem-storing-arrays-with-update-user-meta * * @param int $user_id * @param string $notice_key */ public function save_dismissed_notices($user_id, $notice_key) { $dismissed_notices = $this->get_dismissed_notices($user_id); $dismissed_notices[] = $notice_key; update_user_meta($user_id, $this->dismissed_notices_key, implode(',', $dismissed_notices)); } /** * Display custom text on plugin settings page * * @param string $text */ public function admin_footer_text($text) { $screen = get_current_screen(); if ($this->plugin_screen_hook_suffix == $screen->id) { $text = sprintf(__('If you like WP Maintenance Mode please leave us a %s rating. A huge thank you from WP Maintenance Mode makers in advance!', $this->plugin_slug), '★★★★★'); } return $text; } } }