set_properties( $config_array ); } add_action( 'admin_init', array( $this, 'admin_init' ) ); } public function setup_hooks() { add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); } protected function get_default_config() { return array( 'tabs' => false, 'menu' => $this->get_default_config_menu(), ); } /** * Set Properties of the class */ protected function set_properties( array $config_array ) { // Normalise config array $config_array = wp_parse_args( $config_array, $this->get_default_config() ); if ( isset( $config_array['prefix'] ) ) { $this->prefix = ( ! empty( $config_array['prefix'] ) ) ? sanitize_key( $config_array['prefix'] ) : ''; } if ( isset( $config_array['tabs'] ) ) { $this->set_tabs( $config_array['tabs'] ); } // Do we have menu config, if yes, call the method if ( isset( $config_array['menu'] ) ) { $this->set_menu( $config_array['menu'] ); } // Do we have sections config, if yes, call the method if ( isset( $config_array['sections'] ) ) { $this->set_sections( $config_array['sections'] ); } // Do we have fields config, if yes, call the method if ( isset( $config_array['fields'] ) ) { $this->set_fields( $config_array['fields'] ); } if ( isset( $config_array['links'] ) ) { $this->set_links( $config_array['links'] ); } $this->set_active_tab(); } /** * */ public function set_active_tab() { $this->active_tab = ( isset( $_GET['tab'] ) ) ? sanitize_key( $_GET['tab'] ) : $this->settings_sections[0]['id']; } public function set_links( array $config_links ) { if ( isset( $config_links['plugin_basename'] ) && ! empty( $config_links['plugin_basename'] ) ) { $this->plugin_basename = $config_links['plugin_basename']; $this->action_links = isset( $config_links['action_links'] ) ? $config_links['action_links'] : true; $prefix = is_network_admin() ? 'network_admin_' : ''; add_filter( "{$prefix}plugin_action_links_{$this->plugin_basename}", array( $this, 'plugin_action_links' ), 10, // priority 4 // parameters ); } } public function get_default_settings_url() { $options_base_file_name = $this->config_menu['submenu'] ? 'admin.php' : 'admin.php'; if ( in_array( $options_base_file_name, array( 'options-general.php', 'edit-comments.php', 'plugins.php', 'edit.php', 'upload.php', 'themes.php', 'users.php', 'tools.php' ) ) ) { return admin_url( "{$options_base_file_name}?page={$this->config_menu['slug']}" ); } else { return admin_url( "{$options_base_file_name}?page={$this->config_menu['slug']}" ); } } public function get_default_settings_link() { return array( '' . __( 'Settings', $this->text_domain ) . '', ); } /** * Register "settings" for plugin option page in plugins list * * @param array $links plugin links * * @return array possibly modified $links */ public function plugin_action_links( $links, $plugin_file, $plugin_data, $context ) { /** * Documentation : * https://codex.wordpress.org/Plugin_API/Filter_Reference/plugin_action_links_(plugin_file_name) */ // BOOL of settings is given true | false if ( is_bool( $this->action_links ) ) { // FALSE: If it is false, no need to go further if ( ! $this->action_links ) { return $links; } // TRUE: if Settings link is not defined, lets create one if ( $this->action_links ) { return array_merge( $links, $this->get_default_settings_link() ); } } // if ( is_bool( $this->config['settings_link'] ) ) // Admin URL of settings is given if ( ! is_bool( $this->action_links ) && ! is_array( $this->action_links ) ) { $settings_link = array( '' . __( 'Settings', $this->text_domain ) . '', ); return array_merge( $settings_link, $links ); } // Array of settings_link is given if ( is_array( $this->action_links ) ) { $settings_link_array = array(); foreach ( $this->action_links as $link ) { $link_text = isset( $link['text'] ) ? sanitize_text_field( $link['text'] ) : __( 'Settings', '' ); $link_url_un_clean = isset( $link['url'] ) ? $link['url'] : '#'; $link_type = isset( $link['type'] ) ? sanitize_key( $link['type'] ) : 'default'; switch ( $link_type ) { case ( 'external' ): $link_url = esc_url_raw( $link_url_un_clean ); break; case ( 'internal' ): $link_url = admin_url( esc_url( $link_url_un_clean ) ); break; default: $link_url = $this->get_default_settings_url(); } $settings_link_array[] = '' . $link_text . ''; } return array_merge( $settings_link_array, $links ); } // if ( $this->action_links ) ) // if nothing is returned so far, return original $links return $links; } public function set_tabs( $config_tabs ) { $this->is_tabs = ( (bool) $config_tabs ) ? true : false; } /** * Register plugin option page */ public function set_menu( $config_menu ) { $this->config_menu = array_merge_recursive( $this->config_menu, wp_parse_args( $config_menu, $this->get_default_config_menu() ) ); $this->slug = $this->config_menu['slug'] = isset( $this->config_menu['slug'] ) ? sanitize_key( $this->config_menu['slug'] ) : sanitize_title( $config_menu['page_title'] ); // Is it a main menu or sub_menu if ( ! $this->config_menu['submenu'] ) { add_menu_page( $this->config_menu['page_title'], $this->config_menu['menu_title'], $this->config_menu['capability'], $this->config_menu['slug'], //slug array( $this, 'display_page' ), $this->config_menu['icon'], $this->config_menu['position'] ); } else { add_submenu_page( $this->config_menu['parent'], $this->config_menu['page_title'], $this->config_menu['menu_title'], $this->config_menu['capability'], $this->config_menu['slug'], // slug array( $this, 'display_page' ) ); } } /** * Get default config for menu * @return array $default */ public function get_default_config_menu() { return apply_filters( 'boo_settings_filter_default_menu_array', array( //The name of this page 'page_title' => __( 'Plugin Options', $this->text_domain ), // //The Menu Title in Wp Admin 'menu_title' => __( 'Plugin Options', $this->text_domain ), // The capability needed to view the page 'capability' => 'manage_options', // dashicons id or url to icon // https://developer.wordpress.org/resource/dashicons/ 'icon' => '', // Required for submenu 'submenu' => false, // position 'position' => 100, // For sub menu, we can define parent menu slug (Defaults to Options Page) 'parent' => 'options-general.php', ) ); } //DEBUG public function write_log( $type, $log_line ) { $hash = ''; $fn = plugin_dir_path( __FILE__ ) . '/' . $type . '-' . $hash . '.log'; $log_in_file = file_put_contents( $fn, date( 'Y-m-d H:i:s' ) . ' - ' . $log_line . PHP_EOL, FILE_APPEND ); } /* * @return array configured field types */ public function get_field_types() { foreach ( $this->settings_fields as $sections_fields ) { foreach ( $sections_fields as $field ) { $this->field_types[] = isset( $field['type'] ) ? sanitize_key( $field['type'] ) : 'text'; } } return array_unique( $this->field_types ); } /** * @return bool true if its plugin options page is loaded */ protected function is_menu_page_loaded() { $current_screen = get_current_screen(); return substr( $current_screen->id, - strlen( $this->config_menu['slug'] ) ) === $this->config_menu['slug']; } /** * Enqueue scripts and styles */ function admin_enqueue_scripts() { // Conditionally Load scripts and styles for field types configured // Load scripts for only plugin menu page if ( ! $this->is_menu_page_loaded() ) { return null; } // Load Color Picker if required if ( in_array( 'color', $this->get_field_types() ) ) { wp_enqueue_style( 'wp-color-picker' ); wp_enqueue_script( 'wp-color-picker' ); } if ( in_array( 'media', $this->get_field_types() ) ) { wp_enqueue_media(); } wp_enqueue_script( 'jquery' ); wp_enqueue_style('activitytime_basic_wrapper'); } /** * Set settings sections * * @param array $sections setting sections array */ function set_sections( array $sections ) { $this->settings_sections = array_merge_recursive( $this->settings_sections, $sections ); $this->sections_count = count( $this->settings_sections ); $this->sections_ids = array_values( $this->settings_sections ); return $this; } /** * Set settings fields * * @param array $fields settings fields array */ public function set_fields( $fields ) { $this->settings_fields = array_merge_recursive( $this->settings_fields, $fields ); $this->normalize_fields(); $this->setup_hooks(); return $this; } public function get_markup_placeholder( $placeholder ) { return ' placeholder="' . esc_html( $placeholder ) . '" '; } public function get_sanitize_callback_method( $type ) { return ( method_exists( $this, "sanitize_{$type}" ) ) ? array( $this, "sanitize_{$type}" ) : array( $this, "sanitize_text" ); } public function get_field_markup_callback_name( $type ) { return ( method_exists( $this, "callback_{$type}" ) ) ? "callback_{$type}" : "callback_text"; } public function get_default_field_args( $field, $section = 'default' ) { $type = isset( $field['type'] ) ? $field['type'] : 'text'; return array( 'id' => $field['id'], 'name' => $this->prefix . $field['id'], 'class' => $field['id'], 'label_for' => $field['id'], 'label' => '', 'desc' => '', 'section' => $section, 'size' => 'regular', 'options' => array(), 'callback' => ( isset( $field['callback'] ) ) ? $field['callback'] : $this->get_field_markup_callback_name( $type ), 'sanitize_callback' => '', 'type' => 'text', 'placeholder' => '', // 'min' => '', // 'max' => '', // 'step' => '', 'value' => '', 'show_in_rest' => true, 'default' => '', 'std' => '', 'options_id' => ( ! empty( $this->options_id ) ) ? $this->options_id : str_replace( '-', '_', $this->config_menu['slug'] ) ); } public function normalize_fields() { foreach ( $this->settings_fields as $section_id => $fields ) { if ( is_array( $fields ) && ! empty( $fields ) ) { foreach ( $fields as $i => $field ) { $this->settings_fields[ $section_id ][ $i ] = wp_parse_args( $field, $this->get_default_field_args( $field, $section_id ) ); } } } } /** * */ public function get_page_id_for_sections( $section_id = '' ) { // return $this->config_menu['slug'] . '_' . $section_id; return $this->config_menu['slug']; } public function get_options_group( $section_id = '' ) { return str_replace( '-', '_', $this->slug ) . "_" . $section_id; // return str_replace( '-', '_', $this->slug ); } function display_page() { // Save Default options in DB with default values // $this->set_default_db_options(); if ( 'options-general.php' != $this->config_menu['parent'] ) { settings_errors(); } echo '
'; echo "

" . get_admin_page_title() . "

"; if ( $this->debug ) { echo "TYPES of fields"; $this->var_dump_pretty( $this->get_field_types() ); // delete_option( $this->options_id); if ( $this->is_tabs ) { echo "Active Tab Options Array"; $this->var_dump_pretty( get_option( $this->active_tab ) ); } } ?>
is_tabs ) { $this->show_navigation(); } ?>
is_tabs ) { foreach ( $this->settings_sections as $section ) : if ( $section['id'] !== $this->active_tab ) { continue; } // for tabs settings_fields( $this->get_options_group( $section['id'] ) ); do_settings_sections( $this->get_page_id_for_sections( $section['id'] ) ); endforeach; // end foreach } else { // for tab-less settings_fields( $this->get_options_group() ); do_settings_sections( $this->get_page_id_for_sections() ); } ?>
script_general(); ?>
settings_sections as $section ) { if ( $this->is_tabs ) { if ( $section['id'] !== $this->active_tab ) { continue; } } // TODO: we do not need to add_option if ( false == get_option( $section['id'] ) ) { add_option( $section['id'] ); } // Callback for Section Description if ( isset( $section['callback'] ) && is_callable( $section['callback'] ) ) { $callback = $section['callback']; } else if ( isset( $section['desc'] ) && ! empty( $section['desc'] ) ) { $callback = function () use ( $section ) { echo "
" . esc_html( $section['desc'] ) . "
"; }; } else { $callback = null; } // $this->var_dump_pretty( $callback); die(); // add_settings_section( $section['id'], $section['title'], $callback, $this->slug ); add_settings_section( $section['id'], $section['title'], $callback, $this->get_page_id_for_sections( $section['id'] ) // page ); } } public function add_settings_field_loop() { //register settings fields foreach ( $this->settings_fields as $section_id => $fields ) { if ( $this->is_tabs ) { if ( $section_id !== $this->active_tab ) { continue; } } foreach ( $fields as $field ) : $field['value'] = get_option( $field['name'] ); add_settings_field( $field['name'], $field['label'], array( $this, $field['callback'] ), $this->get_page_id_for_sections( $section_id ), // page $section_id, // section $field // args ); endforeach; } } public function register_settings() { // creates our settings in the options table foreach ( $this->settings_fields as $section_id => $fields ) : foreach ( $fields as $field ) : register_setting( ( $this->is_tabs ) ? $this->get_options_group( $field['section'] ) : $this->get_options_group(), // options_group $field['name'], // options_id array( // 'type' => $field['type'], 'description' => $field['desc'], 'sanitize_callback' => ( is_callable( $field['sanitize_callback'] ) ) ? $field['sanitize_callback'] : $this->get_sanitize_callback_method( $field['type'] ), 'show_in_rest' => $field['show_in_rest'], 'default' => $field['default'], ) ); endforeach; endforeach; } function sanitize_text( $value ) { return ( ! empty( $value ) ) ? sanitize_text_field( $value ) : ''; } function sanitize_number( $value ) { return ( is_numeric( $value ) ) ? $value : 0; } function sanitize_editor( $value ) { return wp_kses_post( $value ); } function sanitize_textarea( $value ) { return sanitize_textarea_field( $value ); } function sanitize_checkbox( $value ) { return ( $value === '1' ) ? 1 : 0; } function sanitize_select( $value ) { return $this->sanitize_text( $value ); } function sanitize_radio( $value ) { return $this->sanitize_text( $value ); } function sanitize_multicheck( $value ) { return ( is_array( $value ) ) ? array_map( 'sanitize_text_field', $value ) : array(); } function sanitize_color( $value ) { if ( false === strpos( $value, 'rgba' ) ) { return sanitize_hex_color( $value ); } else { // By now we know the string is formatted as an rgba color so we need to further sanitize it. $value = trim( $value, ' ' ); $red = $green = $blue = $alpha = ''; sscanf( $value, 'rgba(%d,%d,%d,%f)', $red, $green, $blue, $alpha ); return 'rgba(' . $red . ',' . $green . ',' . $blue . ',' . $alpha . ')'; } } function sanitize_password( $value ) { $password_get_info = password_get_info( $value ); if ( isset( $password_get_info['algo'] ) && $password_get_info['algo'] ) { unset( $password_get_info ); return $value; // do nothing, we have got already stored hashed password } else { unset( $password_get_info ); return password_hash( $value, PASSWORD_DEFAULT ); } } function sanitize_url( $value ) { return esc_url_raw( $value ); } function sanitize_file( $value ) { // TODO: if the option to store file as file url return esc_url_raw( $value ); } function sanitize_html( $value ) { // nothing to save return ''; } function sanitize_posts( $value ) { // Only store post id return absint( $value ); } function sanitize_pages( $value ) { // Only store page id return absint( $value ); } function sanitize_media( $value ) { // Only store media id return absint( $value ); } /** * Displays a text field for a settings field * * @param array $args settings field args */ function callback_text( $args ) { $html = sprintf( '', $args['type'], $args['size'], $args['section'], $args['id'], $args['value'], $this->get_markup_placeholder( $args['placeholder'] ), $args['name'] ); $html .= $this->get_field_description( $args ); echo $html; unset( $html ); } /** * Initialize and registers the settings sections and fileds to WordPress * * Usually this should be called at `admin_init` hook. * * This function gets the initiated settings sections and fields. Then * registers them to WordPress and ready for use. */ function admin_init() { $this->add_settings_section(); $this->add_settings_field_loop(); $this->register_settings(); } /** * Get field description for display * * @param array $args settings field args */ public function get_field_description( $args ) { return sprintf( '

%s

', $args['desc'] ); } /** * Displays a url field for a settings field * * @param array $args settings field args */ function callback_url( $args ) { $this->callback_text( $args ); } /** * Displays a number field for a settings field * * @param array $args settings field args */ function callback_number( $args ) { $min = ( isset( $args['min'] ) && ! empty( $args['min'] ) ) ? ' min="' . $args['min'] . '"' : ''; $max = ( isset( $args['max'] ) && ! empty( $args['max'] ) ) ? ' max="' . $args['max'] . '"' : ''; $step = ( isset( $args['step'] ) && ! empty( $args['step'] ) ) ? ' step="' . $args['step'] . '"' : ''; $html = sprintf( '', $args['type'], $args['size'], $args['section'], $args['id'], $args['value'], $this->get_markup_placeholder( $args['placeholder'] ), $min, $max, $step, $args['name'] ); $html .= $this->get_field_description( $args ); echo $html; unset( $html, $min, $max, $step ); } /** * Displays a checkbox for a settings field * * @param array $args settings field args */ function callback_checkbox( $args ) { $value = $args['value']; if ( $value === '' && $args['default'] !== '' ) { $value = $args['default']; } $html = '
'; $html .= sprintf( '', $args['desc'] ); $html .= '
'; echo $html; } /** * Displays a multicheckbox for a settings field * * @param array $args settings field args */ function callback_multicheck( $args ) { $value = $args['value']; if ( empty( $value ) ) { $value = $args['default']; } $html = '
'; foreach ( $args['options'] as $key => $label ) { $checked = isset( $value[ $key ] ) ? $value[ $key ] : '0'; $html .= sprintf( '
', $label ); } $html .= $this->get_field_description( $args ); $html .= '
'; echo $html; unset( $value, $html ); } /** * Displays a radio button for a settings field * * @param array $args settings field args */ function callback_radio( $args ) { $value = $args['value']; if ( empty( $value ) ) { $value = is_array( $args['default'] ) ? $args['default'] : array(); } $html = '
'; foreach ( $args['options'] as $key => $label ) { $html .= sprintf( '
', $label ); } $html .= $this->get_field_description( $args ); $html .= '
'; echo $html; unset( $value, $html ); } /** * Displays a selectbox for a settings field * * @param array $args settings field args */ function callback_select( $args ) { $html = sprintf( '' ); $html .= $this->get_field_description( $args ); echo $html; unset( $html ); } /** * Displays a textarea for a settings field * * @param array $args settings field args */ function callback_textarea( $args ) { $html = sprintf( '', $args['size'], $args['id'], $this->get_markup_placeholder( $args['placeholder'] ), $args['value'], $args['name'] ); $html .= $this->get_field_description( $args ); echo $html; } /** * Displays the html for a settings field * * @param array $args settings field args * * @return string */ function callback_html( $args ) { echo $this->get_field_description( $args ); } /** * Displays a rich text textarea for a settings field * * @param array $args settings field args */ function callback_editor( $args ) { $name = $this->get_field_name( $args['options_id'], $args['section'], $args['id'] ); $value = $this->get_option( $args['id'], $args['section'], $args['std'] ); $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : '500px'; echo '
'; $editor_settings = array( 'teeny' => true, 'textarea_name' => $name, 'textarea_rows' => 10 ); if ( isset( $args['options'] ) && is_array( $args['options'] ) ) { $editor_settings = array_merge( $editor_settings, $args['options'] ); } wp_editor( $value, $args['section'] . '-' . $args['id'], $editor_settings ); echo '
'; echo $this->get_field_description( $args ); } /** * Displays a file upload field for a settings field * * @param array $args settings field args */ function callback_file( $args ) { $label = isset( $args['options']['btn'] ) ? $args['options']['btn'] : __( 'Choose File', '' ); $html = sprintf( '', $args['size'], $args['section'], $args['id'], $args['value'], $args['name'] ); $html .= ''; $html .= $this->get_field_description( $args ); echo $html; } /** * Generate: Uploader field * * @param array $args * * @source: https://mycyberuniverse.com/integration-wordpress-media-uploader-plugin-options-page.html */ public function callback_media( $args ) { // Set variables $default_image = isset( $args['default'] ) ? esc_url_raw( $args['default'] ) : 'https://www.placehold.it/115x115'; $max_width = isset( $args['options']['max_width'] ) ? absint( $args['options']['max_width'] ) : 150; $width = isset( $args['options']['width'] ) ? absint( $args['options']['width'] ) : ''; $height = isset( $args['options']['height'] ) ? absint( $args['options']['height'] ) : ''; $text = isset( $args['options']['btn'] ) ? sanitize_text_field( $args['options']['btn'] ) : __( 'Upload', '' ); // $name = $this->get_field_name( $args['options_id'], $args['section'], $args['id'] ); // $args['value'] = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) ); $image_size = ( ! empty( $width ) && ! empty( $height ) ) ? array( $width, $height ) : 'thumbnail'; if ( ! empty( $args['value'] ) ) { $image_attributes = wp_get_attachment_image_src( $args['value'], $image_size ); $src = $image_attributes[0]; $value = $args['value']; } else { $src = $default_image; $value = ''; } $image_style = ! is_array( $image_size ) ? "style='max-width:100%; height:auto;'" : "style='width:{$width}px; height:{$height}px;'"; $max_width = $max_width . "px"; // Print HTML field echo '
'; $this->get_field_description( $args ); // free memory unset( $default_image, $max_width, $width, $height, $text, $image_size, $image_style, $value ); } /** * Displays a password field for a settings field * * @param array $args settings field args */ function callback_password( $args ) { $html = sprintf( '', $args['size'], $args['section'], $args['id'], $args['value'], $args['name'] ); $html .= $this->get_field_description( $args ); echo $html; } /** * Displays a color picker field for a settings field * * @param array $args settings field args */ function callback_color( $args ) { $html = sprintf( '', $args['size'], $args['section'], $args['id'], $args['value'], $args['default'], $args['name'] ); $html .= $this->get_field_description( $args ); echo $html; } /** * Displays a select box for creating the pages select box * * @param array $args settings field args */ function callback_pages( $args ) { // $name = $this->get_field_name( $args['options_id'], $args['section'], $args['id'] ); $dropdown_args = array( 'selected' => $args['value'], 'name' => $args['name'], 'id' => $args['section'] . '[' . $args['id'] . ']', 'echo' => 1, ); wp_dropdown_pages( $dropdown_args ); } function callback_posts( $args ) { $default_args = array( 'post_type' => 'post', 'numberposts' => - 1 ); $posts_args = wp_parse_args( $args['options'], $default_args ); $posts = get_posts( $posts_args ); $options = array(); foreach ( $posts as $post ) : setup_postdata( $post ); $options[ $post->ID ] = esc_html( $post->post_title ); wp_reset_postdata(); endforeach; // free memory unset( $posts, $posts_args, $default_args ); //$args['options'] is required by callback_select() $args['options'] = $options; $this->callback_select( $args ); } /** * Show navigations as tab * * Shows all the settings section labels as tab */ function show_navigation() { $settings_page = $this->get_default_settings_url(); $count = count( $this->settings_sections ); // don't show the navigation if only one section exists if ( $count === 1 ) { return; } $html = ''; echo $html; } public function var_dump_pretty( $var ) { echo "
";
			var_dump( $var );
			echo "
"; } public function var_export_pretty( $var ) { echo "
";
			var_export( $var );
			echo "
"; } /** * Tabbable JavaScript codes & Initiate Color Picker * * This code uses localstorage for displaying active tabs */ function script_general() { ?>