'Codestar Framework by Codestar', 'framework_class' => '', // menu settings 'menu_title' => '', 'menu_slug' => '', 'menu_type' => 'menu', 'menu_capability' => 'manage_options', 'menu_icon' => null, 'menu_position' => null, 'menu_hidden' => false, 'menu_parent' => '', 'sub_menu_title' => '', // menu extras 'show_bar_menu' => true, 'show_sub_menu' => true, 'show_in_network' => true, 'show_in_customizer' => false, 'show_search' => true, 'show_reset_all' => true, 'show_reset_section' => true, 'show_footer' => true, 'show_all_options' => true, 'show_form_warning' => true, 'sticky_header' => true, 'save_defaults' => true, 'ajax_save' => true, 'form_action' => '', // admin bar menu settings 'admin_bar_menu_icon' => '', 'admin_bar_menu_priority' => 50, // footer 'footer_text' => '', 'footer_after' => '', 'footer_credit' => '', // database model 'database' => '', // options, transient, theme_mod, network 'transient_time' => 0, // contextual help 'contextual_help' => array(), 'contextual_help_sidebar' => '', // typography options 'enqueue_webfont' => true, 'async_webfont' => false, // others 'output_css' => true, // theme 'nav' => 'normal', 'theme' => 'dark', 'class' => '', // external default values 'defaults' => array(), ); // run framework construct public function __construct($key, $params = array()) { $this->unique = $key; $this->args = apply_filters("csf_{$this->unique}_args", wp_parse_args($params['args'], $this->args), $this); $this->sections = apply_filters("csf_{$this->unique}_sections", $params['sections'], $this); // run only is admin panel options, avoid performance loss $this->pre_tabs = $this->pre_tabs($this->sections); $this->pre_fields = $this->pre_fields($this->sections); $this->pre_sections = $this->pre_sections($this->sections); $this->get_options(); $this->set_options(); $this->save_defaults(); add_action('admin_menu', array($this, 'add_admin_menu')); add_action('admin_bar_menu', array($this, 'add_admin_bar_menu'), $this->args['admin_bar_menu_priority']); add_action('wp_ajax_csf_' . $this->unique . '_ajax_save', array($this, 'ajax_save')); if ($this->args['database'] === 'network' && !empty($this->args['show_in_network'])) { add_action('network_admin_menu', array($this, 'add_admin_menu')); } // wp enqeueu for typography and output css parent::__construct(); } // instance public static function instance($key, $params = array()) { return new self($key, $params); } public function pre_tabs($sections) { $result = array(); $parents = array(); $count = 100; foreach ($sections as $key => $section) { if (!empty($section['parent'])) { $section['priority'] = (isset($section['priority'])) ? $section['priority'] : $count; $parents[$section['parent']][] = $section; unset($sections[$key]); } $count++; } foreach ($sections as $key => $section) { $section['priority'] = (isset($section['priority'])) ? $section['priority'] : $count; if (!empty($section['id']) && !empty($parents[$section['id']])) { $section['subs'] = wp_list_sort($parents[$section['id']], array('priority' => 'ASC'), 'ASC', true); } $result[] = $section; $count++; } return wp_list_sort($result, array('priority' => 'ASC'), 'ASC', true); } public function pre_fields($sections) { $result = array(); foreach ($sections as $key => $section) { if (!empty($section['fields'])) { foreach ($section['fields'] as $field) { $result[] = $field; } } } return $result; } public function pre_sections($sections) { $result = array(); foreach ($this->pre_tabs as $tab) { if (!empty($tab['subs'])) { foreach ($tab['subs'] as $sub) { $sub['ptitle'] = $tab['title']; $result[] = $sub; } } if (empty($tab['subs'])) { $result[] = $tab; } } return $result; } // add admin bar menu public function add_admin_bar_menu($wp_admin_bar) { if (is_network_admin() && ($this->args['database'] !== 'network' || $this->args['show_in_network'] !== true)) { return; } if (!empty($this->args['show_bar_menu']) && empty($this->args['menu_hidden'])) { global $submenu; $menu_slug = $this->args['menu_slug']; $menu_icon = (!empty($this->args['admin_bar_menu_icon'])) ? '' : ''; $wp_admin_bar->add_node(array( 'id' => $menu_slug, 'title' => $menu_icon . esc_attr($this->args['menu_title']), 'href' => esc_url((is_network_admin()) ? network_admin_url('admin.php?page=' . $menu_slug) : admin_url('admin.php?page=' . $menu_slug)), )); if (!empty($submenu[$menu_slug])) { foreach ($submenu[$menu_slug] as $menu_key => $menu_value) { $wp_admin_bar->add_node(array( 'parent' => $menu_slug, 'id' => $menu_slug . '-' . $menu_key, 'title' => $menu_value[0], 'href' => esc_url((is_network_admin()) ? network_admin_url('admin.php?page=' . $menu_value[2]) : admin_url('admin.php?page=' . $menu_value[2])), )); } } } } public function ajax_save() { $result = $this->set_options(true); if (!$result) { wp_send_json_error(array('error' => esc_html__('Error while saving the changes.', 'csf'))); } else { wp_send_json_success(array('notice' => $this->notice, 'errors' => $this->errors)); } } // get default value public function get_default($field) { $default = (isset($field['default'])) ? $field['default'] : ''; $default = (isset($this->args['defaults'][$field['id']])) ? $this->args['defaults'][$field['id']] : $default; return $default; } // save defaults and set new fields value to main options public function save_defaults() { $tmp_options = $this->options; foreach ($this->pre_fields as $field) { if (!empty($field['id'])) { $this->options[$field['id']] = (isset($this->options[$field['id']])) ? $this->options[$field['id']] : $this->get_default($field); } } if ($this->args['save_defaults'] && empty($tmp_options)) { $this->save_options($this->options); } } // set options public function set_options($ajax = false) { // XSS ok. // No worries, This "POST" requests is sanitizing in the below foreach. see #L337 - #L341 $response = ($ajax && !empty($_POST['data'])) ? json_decode(wp_unslash(trim($_POST['data'])), true) : $_POST; // Set variables. $data = array(); $noncekey = 'csf_options_nonce' . $this->unique; $nonce = (!empty($response[$noncekey])) ? $response[$noncekey] : ''; $options = (!empty($response[$this->unique])) ? $response[$this->unique] : array(); $transient = (!empty($response['csf_transient'])) ? $response['csf_transient'] : array(); if (wp_verify_nonce($nonce, 'csf_options_nonce')) { $importing = false; $section_id = (!empty($transient['section'])) ? $transient['section'] : ''; if (!$ajax && !empty($response['csf_import_data'])) { // XSS ok. // No worries, This "POST" requests is sanitizing in the below foreach. see #L337 - #L341 $import_data = json_decode(wp_unslash(trim($response['csf_import_data'])), true); $options = (is_array($import_data) && !empty($import_data)) ? $import_data : array(); $importing = true; $this->notice = esc_html__('Settings successfully imported.', 'csf'); } if (!empty($transient['reset'])) { foreach ($this->pre_fields as $field) { if (!empty($field['id'])) { $data[$field['id']] = $this->get_default($field); } } $this->notice = esc_html__('Default settings restored.', 'csf'); } else if (!empty($transient['reset_section']) && !empty($section_id)) { if (!empty($this->pre_sections[$section_id - 1]['fields'])) { foreach ($this->pre_sections[$section_id - 1]['fields'] as $field) { if (!empty($field['id'])) { $data[$field['id']] = $this->get_default($field); } } } $data = wp_parse_args($data, $this->options); $this->notice = esc_html__('Default settings restored.', 'csf'); } else { // sanitize and validate foreach ($this->pre_fields as $field) { if (!empty($field['id'])) { $field_id = $field['id']; $field_value = isset($options[$field_id]) ? $options[$field_id] : ''; // Ajax and Importing doing wp_unslash already. if (!$ajax && !$importing) { $field_value = wp_unslash($field_value); } // Sanitize "post" request of field. if (!isset($field['sanitize'])) { if (is_array($field_value)) { $data[$field_id] = wp_kses_post_deep($field_value); } else { $data[$field_id] = wp_kses_post($field_value); } } else if (isset($field['sanitize']) && is_callable($field['sanitize'])) { $data[$field_id] = call_user_func($field['sanitize'], $field_value); } else { $data[$field_id] = $field_value; } // Validate "post" request of field. if (isset($field['validate']) && is_callable($field['validate'])) { $has_validated = call_user_func($field['validate'], $field_value); if (!empty($has_validated)) { $data[$field_id] = (isset($this->options[$field_id])) ? $this->options[$field_id] : ''; $this->errors[$field_id] = $has_validated; } } } } } $data = apply_filters("csf_{$this->unique}_save", $data, $this); do_action("csf_{$this->unique}_save_before", $data, $this); $this->options = $data; $this->save_options($data); do_action("csf_{$this->unique}_save_after", $data, $this); if (empty($this->notice)) { $this->notice = esc_html__('Settings saved.', 'csf'); } return true; } return false; } // save options database public function save_options($data) { if ($this->args['database'] === 'transient') { set_transient($this->unique, $data, $this->args['transient_time']); } else if ($this->args['database'] === 'theme_mod') { set_theme_mod($this->unique, $data); } else if ($this->args['database'] === 'network') { update_site_option($this->unique, $data); } else { update_option($this->unique, $data); } do_action("csf_{$this->unique}_saved", $data, $this); } // get options from database public function get_options() { if ($this->args['database'] === 'transient') { $this->options = get_transient($this->unique); } else if ($this->args['database'] === 'theme_mod') { $this->options = get_theme_mod($this->unique); } else if ($this->args['database'] === 'network') { $this->options = get_site_option($this->unique); } else { $this->options = get_option($this->unique); } if (empty($this->options)) { $this->options = array(); } return $this->options; } // admin menu public function add_admin_menu() { extract($this->args); if ($menu_type === 'submenu') { $menu_page = call_user_func('add_submenu_page', $menu_parent, esc_attr($menu_title), esc_attr($menu_title), $menu_capability, $menu_slug, array($this, 'add_options_html')); } else { $menu_page = call_user_func('add_menu_page', esc_attr($menu_title), esc_attr($menu_title), $menu_capability, $menu_slug, array($this, 'add_options_html'), $menu_icon, $menu_position); if (!empty($sub_menu_title)) { call_user_func('add_submenu_page', $menu_slug, esc_attr($sub_menu_title), esc_attr($sub_menu_title), $menu_capability, $menu_slug, array($this, 'add_options_html')); } if (!empty($this->args['show_sub_menu']) && count($this->pre_tabs) > 1) { // create submenus foreach ($this->pre_tabs as $section) { call_user_func('add_submenu_page', $menu_slug, esc_attr($section['title']), esc_attr($section['title']), $menu_capability, $menu_slug . '#tab=' . sanitize_title($section['title']), '__return_null'); } remove_submenu_page($menu_slug, $menu_slug); } if (!empty($menu_hidden)) { remove_menu_page($menu_slug); } } add_action('load-' . $menu_page, array($this, 'add_page_on_load')); } public function add_page_on_load() { if (!empty($this->args['contextual_help'])) { $screen = get_current_screen(); foreach ($this->args['contextual_help'] as $tab) { $screen->add_help_tab($tab); } if (!empty($this->args['contextual_help_sidebar'])) { $screen->set_help_sidebar($this->args['contextual_help_sidebar']); } } add_filter('admin_footer_text', array($this, 'add_admin_footer_text')); } public function add_admin_footer_text() { $default = 'Thank you for creating with Codestar Framework'; echo (!empty($this->args['footer_credit'])) ? $this->args['footer_credit'] : $default; } public function error_check($sections, $err = '') { if (!$this->args['ajax_save']) { if (!empty($sections['fields'])) { foreach ($sections['fields'] as $field) { if (!empty($field['id'])) { if (array_key_exists($field['id'], $this->errors)) { $err = '!'; } } } } if (!empty($sections['subs'])) { foreach ($sections['subs'] as $sub) { $err = $this->error_check($sub, $err); } } if (!empty($sections['id']) && array_key_exists($sections['id'], $this->errors)) { $err = $this->errors[$sections['id']]; } } return $err; } // option page html output public function add_options_html() { $has_nav = (count($this->pre_tabs) > 1) ? true : false; $show_all = (!$has_nav) ? ' csf-show-all' : ''; $ajax_class = ($this->args['ajax_save']) ? ' csf-save-ajax' : ''; $sticky_class = ($this->args['sticky_header']) ? ' csf-sticky-header' : ''; $wrapper_class = ($this->args['framework_class']) ? ' ' . $this->args['framework_class'] : ''; $theme = ($this->args['theme']) ? ' csf-theme-' . $this->args['theme'] : ''; $class = ($this->args['class']) ? ' ' . $this->args['class'] : ''; $nav_type = ($this->args['nav'] === 'inline') ? 'inline' : 'normal'; $form_action = ($this->args['form_action']) ? $this->args['form_action'] : ''; do_action('csf_options_before'); echo '
'; do_action('csf_options_after'); } } }