Original code:
https://gist.github.com/hlashbrooke/9267467
First the Files (2)
The Class:
<?php
if ( ! defined( 'ABSPATH' ) ) exit;
class JMAYtSettings {
private $dir;
private $file;
private $assets_url;
private $settings_base;
private $settings;
private $db_option;
private $page_title;
private $text_domain;
public function __construct($base = 'jma_plugin', $title = 'Cool Plugin', $settings = array(), $text_domain = '') {
$this->file = __FILE__ ;
$this->dir = dirname( $this->file );
$this->assets_url = esc_url( trailingslashit( plugins_url( '/', $this->file ) ) );
$this->settings_base = $base . '_';
$this->db_option = $this->settings_base . 'options_array';
$this->page_title = $title;
$this->settings = $settings;
$this->text_domain = $text_domain? $text_domain: $this->settings_base . 'textdomain';
// Initialise settings
add_action( 'admin_init', array( $this, 'init' ) );
// Register plugin settings
add_action( 'admin_init' , array( $this, 'register_settings' ) );
// Add settings page to menu
add_action( 'admin_menu' , array( $this, 'add_menu_item' ) );
// Add settings link to plugins page
add_filter( 'plugin_action_links_' . plugin_basename( $this->file ) , array( $this, 'add_settings_link' ) );
}
/**
* Initialise settings
* @return void
*/
public function init() {
$this->settings = $this->settings_fields();
}
/**
* Add settings page to admin menu
* @return void
*/
public function add_menu_item() {
$page = add_options_page( __( $this->page_title, $this->text_domain ) , __( $this->page_title, $this->text_domain ) , 'manage_options' , $this->settings_base . 'settings' , array( $this, 'settings_page' ) );
add_action( 'admin_print_styles-' . $page, array( $this, 'settings_assets' ) );
}
/**
* Load settings JS & CSS
* @return void
*/
public function settings_assets() {
// We're including the farbtastic script & styles here because they're needed for the colour picker
// If you're not including a colour picker field then you can leave these calls out as well as the farbtastic dependency for the wpt-admin-js script below
wp_enqueue_style( 'farbtastic' );
wp_enqueue_script( 'farbtastic' );
// We're including the WP media scripts here because they're needed for the image upload field
// If you're not including an image upload then you can leave this function call out
wp_enqueue_media();
wp_register_script( $this->settings_base . 'admin-js', $this->assets_url . 'settings.js', array( 'farbtastic', 'jquery' ), '1.0.0' );
wp_enqueue_script( $this->settings_base . 'admin-js' );
}
/**
* Add settings link to plugin list table
* @param array $links Existing links
* @return array Modified links
*/
public function add_settings_link( $links ) {
$settings_link = '<a href="options-general.php?page=' . $this->settings_base . 'settings">' . __( 'Settings', $this->text_domain ) . '</a>';
array_push( $links, $settings_link );
return $links;
}
/**
* Build settings fields
* @return array Fields to be displayed on settings page
*/
private function settings_fields() {
$this->settings = apply_filters( $this->settings_base . 'settings_fields', $this->settings );
return $this->settings;
}
/**
* Register plugin settings
* @return void
*/
public function register_settings() {
if( is_array( $this->settings ) ) {
$option_name = $this->db_option;
foreach( $this->settings as $section => $data ) {
// Add section to page
add_settings_section( $section, $data['title'], array( $this, 'settings_section' ), $this->settings_base . 'settings' );
foreach( $data['fields'] as $field ) {
// Validation callback for field
$validation = '';
if( isset( $field['callback'] ) ) {
$validation = $field['callback'];
}
// Register field
register_setting( $this->settings_base . 'settings', $option_name, $validation );
// Add field to page
add_settings_field( $field['id'], $field['label'], array( $this, 'display_field' ), $this->settings_base . 'settings', $section, array( 'field' => $field ) );
}
}
}
}
public function settings_section( $section ) {
$html = '<p> ' . $this->settings[ $section['id'] ]['description'] . '</p>' . "\n";
echo $html;
}
/**
* Generate HTML for displaying fields
* @param array $args Field data
* @return void
*/
public function display_field( $args ) {
$field = $args['field'];
$html = '';
$option = null;
$option_array_name = $field['id'];
$option_name = $this->db_option . '[' . $field['id'] . ']';
$option_array = get_option( $this->db_option );
if(is_array($option_array) )
$option = $option_array[$option_array_name];
$data = '';
if( isset( $field['default'] ) ) {
$data = $field['default'];
if( $option !== null ) {
$data = $option;
}
}
switch( $field['type'] ) {
case 'text':
case 'password':
case 'number':
$html .= '<input id="' . esc_attr( $field['id'] ) . '" type="' . $field['type'] . '" name="' . esc_attr( $option_name ) . '" placeholder="' . esc_attr( $field['placeholder'] ) . '" value="' . $data . '"/>' . "\n";
break;
case 'text_secret':
$html .= '<input id="' . esc_attr( $field['id'] ) . '" type="text" name="' . esc_attr( $option_name ) . '" placeholder="' . esc_attr( $field['placeholder'] ) . '" value=""/>' . "\n";
break;
case 'textarea':
$html .= '<textarea id="' . esc_attr( $field['id'] ) . '" rows="5" cols="50" name="' . esc_attr( $option_name ) . '" placeholder="' . esc_attr( $field['placeholder'] ) . '">' . $data . '</textarea><br/>'. "\n";
break;
case 'checkbox':
$checked = '';
if( $option && 'on' == $option ){
$checked = 'checked="checked"';
}
$html .= '<input id="' . esc_attr( $field['id'] ) . '" type="' . $field['type'] . '" name="' . esc_attr( $option_name ) . '" ' . $checked . '/>' . "\n";
break;
case 'checkbox_multi':
foreach( $field['options'] as $k => $v ) {
$checked = false;
if( in_array( $k, $data ) ) {
$checked = true;
}
$html .= '<label for="' . esc_attr( $field['id'] . '_' . $k ) . '"><input type="checkbox" ' . checked( $checked, true, false ) . ' name="' . esc_attr( $option_name ) . '[]" value="' . esc_attr( $k ) . '" id="' . esc_attr( $field['id'] . '_' . $k ) . '" /> ' . $v . '</label> ';
}
break;
case 'radio':
foreach( $field['options'] as $k => $v ) {
$checked = false;
if( $k == $data ) {
$checked = true;
}
$html .= '<label for="' . esc_attr( $field['id'] . '_' . $k ) . '"><input type="radio" ' . checked( $checked, true, false ) . ' name="' . esc_attr( $option_name ) . '" value="' . esc_attr( $k ) . '" id="' . esc_attr( $field['id'] . '_' . $k ) . '" /> ' . $v . '</label> ';
}
break;
case 'select':
$html .= '<select name="' . esc_attr( $option_name ) . '" id="' . esc_attr( $field['id'] ) . '">';
foreach( $field['options'] as $k => $v ) {
$selected = false;
if( $k == $data ) {
$selected = true;
}
$html .= '<option ' . selected( $selected, true, false ) . ' value="' . esc_attr( $k ) . '">' . $v . '</option>';
}
$html .= '</select> ';
break;
case 'select_multi':
$html .= '<select name="' . esc_attr( $option_name ) . '[]" id="' . esc_attr( $field['id'] ) . '" multiple="multiple">';
foreach( $field['options'] as $k => $v ) {
$selected = false;
if( in_array( $k, $data ) ) {
$selected = true;
}
$html .= '<option ' . selected( $selected, true, false ) . ' value="' . esc_attr( $k ) . '" />' . $v . '</label> ';
}
$html .= '</select> ';
break;
case 'image':
$image_thumb = '';
if( $data ) {
$image_thumb = wp_get_attachment_thumb_url( $data );
}
$html .= '<img id="' . $option_array_name . '_preview" class="image_preview" src="' . $image_thumb . '" /><br/>' . "\n";
$html .= '<input id="' . $option_array_name . '_button" type="button" data-uploader_title="' . __( 'Upload an image' , $this->text_domain ) . '" data-uploader_button_text="' . __( 'Use image' , $this->text_domain ) . '" class="image_upload_button button" value="'. __( 'Upload new image' , $this->text_domain ) . '" />' . "\n";
$html .= '<input id="' . $option_array_name . '_delete" type="button" class="image_delete_button button" value="'. __( 'Remove image' , $this->text_domain ) . '" />' . "\n";
$html .= '<input id="' . $option_array_name . '" class="image_data_field" type="hidden" name="' . $option_name . '" value="' . $data . '"/><br/>' . "\n";
break;
case 'color':
$color_value = esc_html( $data )?esc_html( $data ):0;//John's big addition to prevent empty box issue
?><div class="color-picker" style="position:relative;">
<input type="text" name="<?php esc_attr_e( $option_name ); ?>" class="color" value="<?php echo
$color_value ?>" />
<div style="position:absolute;background:#FFF;z-index:99;border-radius:100%;" class="colorpicker"></div>
</div>
<?php
break;
}
switch( $field['type'] ) {
case 'checkbox_multi':
case 'radio':
case 'select_multi':
$html .= '<br/><span class="description">' . $field['description'] . '</span>';
break;
default:
$html .= '<label for="' . esc_attr( $field['id'] ) . '"><span class="description">' . $field['description'] . '</span></label>' . "\n";
break;
}
echo $html;
}
/**
* Validate individual settings field
* @param string $data Inputted value
* @return string Validated value
*/
public function validate_field( $data ) {
if( $data && strlen( $data ) > 0 && $data != '' ) {
$data = urlencode( strtolower( str_replace( ' ' , '-' , $data ) ) );
}
return $data;
}
/**
* Load settings page content
* @return void
*/
public function settings_page() {
// Build page HTML
$html = '<div class="wrap" id="' . $this->settings_base . 'settings">' . "\n";
$html .= '<h2>' . __( $this->page_title . ' Settings' , $this->text_domain ) . '</h2>' . "\n";
$html .= '<form method="post" action="options.php" enctype="multipart/form-data">' . "\n";
$html .= '<div class="clear"></div>' . "\n";
// Get settings fields
ob_start();
settings_fields( $this->settings_base . 'settings' );
do_settings_sections( $this->settings_base . 'settings' );
$html .= ob_get_clean();
$html .= '<p class="submit">' . "\n";
$html .= '<input name="Submit" type="submit" class="button-primary" value="' . esc_attr( __( 'Save Settings' , $this->text_domain ) ) . '" />' . "\n";
$html .= '</p>' . "\n";
$html .= '</form>' . "\n";
$html .= '</div>' . "\n";
echo $html;
}
}Then the jquery (settings.js):
jQuery(document).ready(function($) {
/***** Colour picker *****/
$('.colorpicker').hide();
$('.colorpicker').each( function() {
$(this).farbtastic( $(this).closest('.color-picker').find('.color') );
});
$('.color').click(function() {
$(this).closest('.color-picker').find('.colorpicker').fadeIn();
});
$(document).mousedown(function() {
$('.colorpicker').each(function() {
var display = $(this).css('display');
if ( display == 'block' )
$(this).fadeOut();
});
});
/***** Uploading images *****/
var file_frame;
jQuery.fn.uploadMediaFile = function( button, preview_media ) {
var button_id = button.attr('id');
var field_id = button_id.replace( '_button', '' );
var preview_id = button_id.replace( '_button', '_preview' );
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frames.file_frame = wp.media({
title: jQuery( this ).data( 'uploader_title' ),
button: {
text: jQuery( this ).data( 'uploader_button_text' ),
},
multiple: false
});
// When an image is selected, run a callback.
file_frame.on( 'select', function() {
attachment = file_frame.state().get('selection').first().toJSON();
jQuery("#"+field_id).val(attachment.id);
if( preview_media ) {
jQuery("#"+preview_id).attr('src',attachment.sizes.thumbnail.url);
}
});
// Finally, open the modal
file_frame.open();
}
jQuery('.image_upload_button').click(function() {
jQuery.fn.uploadMediaFile( jQuery(this), true );
});
jQuery('.image_delete_button').click(function() {
jQuery(this).closest('td').find( '.image_data_field' ).val( '' );
jQuery( '.image_preview' ).remove();
return false;
});
});In the plugin root
Setup Class autoload
spl_autoload_register( 'jma_yt_autoloader' );
function jma_yt_autoloader( $class_name ) {
if ( false !== strpos( $class_name, 'JMAYt' ) ) {
$classes_dir = realpath(plugin_dir_path(__FILE__));
$class_file = $class_name . '.php';
require_once $classes_dir . DIRECTORY_SEPARATOR . $class_file;
}
}Setting array example:
/**
* Build settings fields
* @return array Fields to be displayed on settings page
*/
$settings = array(
/*
* start of a new section
* */
'standard' => array(
'title' => __( 'Standard', 'jmayt_textdomain' ),
'description' => __( 'These are fairly standard form input fields.', 'jmayt_textdomain' ),
/*
* fields for this section section
* */
'fields' => array(
array(
'id' => 'text_field',
'label' => __( 'Some Text' , 'jmayt_textdomain' ),
'description' => __( 'This is a standard text field.', 'jmayt_textdomain' ),
'type' => 'text',
'default' => '',
'placeholder' => __( 'Placeholder text', 'jmayt_textdomain' )
),
array(
'id' => 'password_field',
'label' => __( 'A Password' , 'jmayt_textdomain' ),
'description' => __( 'This is a standard password field.', 'jmayt_textdomain' ),
'type' => 'password',
'default' => '',
'placeholder' => __( 'Placeholder text', 'jmayt_textdomain' )
),
array(
'id' => 'secret_text_field',
'label' => __( 'Some Secret Text' , 'jmayt_textdomain' ),
'description' => __( 'This is a secret text field - any data saved here will not be displayed after the page has reloaded, but it will be saved.', 'jmayt_textdomain' ),
'type' => 'text_secret',
'default' => '',
'placeholder' => __( 'Placeholder text', 'jmayt_textdomain' )
),
array(
'id' => 'text_block',
'label' => __( 'A Text Block' , 'jmayt_textdomain' ),
'description' => __( 'This is a standard text area.', 'jmayt_textdomain' ),
'type' => 'textarea',
'default' => '',
'placeholder' => __( 'Placeholder text for this textarea', 'jmayt_textdomain' )
),
array(
'id' => 'single_checkbox',
'label' => __( 'An Option', 'jmayt_textdomain' ),
'description' => __( 'A standard checkbox - if you save this option as checked then it will store the option as \'on\', otherwise it will be an empty string.', 'jmayt_textdomain' ),
'type' => 'checkbox'
/* dont use default here */
),
array(
'id' => 'select_box',
'label' => __( 'A Select Box', 'jmayt_textdomain' ),
'description' => __( 'A standard select box.', 'jmayt_textdomain' ),
'type' => 'select',
'options' => array( 'drupal' => 'Drupal', 'joomla' => 'Joomla', 'wordpress' => 'WordPress' ),
'default' => 'wordpress'
),
array(
'id' => 'radio_buttons',
'label' => __( 'Some Options', 'jmayt_textdomain' ),
'description' => __( 'A standard set of radio buttons.', 'jmayt_textdomain' ),
'type' => 'radio',
'options' => array( 'superman' => 'Superman', 'batman' => 'Batman', 'ironman' => 'Iron Man' ),
'default' => 'batman'
),
array(
'id' => 'multiple_checkboxes',
'label' => __( 'Some Items', 'jmayt_textdomain' ),
'description' => __( 'You can select multiple items and they will be stored as an array.', 'jmayt_textdomain' ),
'type' => 'checkbox_multi',
'options' => array( 'square' => 'Square', 'circle' => 'Circle', 'rectangle' => 'Rectangle', 'triangle' => 'Triangle' )
/* dont use default here */
)
)
),
/*
* start of a new section
* */
'extra' => array(
'title' => __( 'Extra', 'jmayt_textdomain' ),
'description' => __( 'These are some extra input fields that maybe aren\'t as common as the others.', 'jmayt_textdomain' ),
/*
* fields for this section section
* */
'fields' => array(
array(
'id' => 'number_field',
'label' => __( 'A Number' , 'jmayt_textdomain' ),
'description' => __( 'This is a standard number field - if this field contains anything other than numbers then the form will not be submitted.', 'jmayt_textdomain' ),
'type' => 'number',
'default' => '',
'placeholder' => __( '42', 'jmayt_textdomain' )
),
array(
'id' => 'colour_picker',
'label' => __( 'Pick a colour', 'jmayt_textdomain' ),
'description' => __( 'This uses WordPress\' built-in colour picker - the option is stored as the colour\'s hex code.', 'jmayt_textdomain' ),
'type' => 'color',
'default' => '#21759B'
),
array(
'id' => 'an_image',
'label' => __( 'An Image' , 'jmayt_textdomain' ),
'description' => __( 'This will upload an image to your media library and store the attachment ID in the option field. Once you have uploaded an imge the thumbnail will display above these buttons.', 'jmayt_textdomain' ),
'type' => 'image',
'default' => '',
'placeholder' => ''
),
array(
'id' => 'multi_select_box',
'label' => __( 'A Multi-Select Box', 'jmayt_textdomain' ),
'description' => __( 'A standard multi-select box - the saved data is stored as an array.', 'jmayt_textdomain' ),
'type' => 'select_multi',
'options' => array( 'linux' => 'Linux', 'mac' => 'Mac', 'windows' => 'Windows' ),
'default' => array( 'linux' )
)
)
)
);Instantiate the Class (with prefix, title and settings from above as arguments):
if( is_admin() )
$jma_settings_page = new JMAYtSettings('jmayt', 'YouTube w/ Meta', $settings);