With Genesis 1.8 or see the Genesis 1.8 Changelog). Genesis Plugins and Child Theme Developers alike can use this class to create option pages and even extend existing option pages. If you are not a ProPlus Member, become one today to get the Beta version.
Before I move into the examples, I’d like to mention that every Genesis Admin page now has a few hooks:
- genesis_admin_init:
- Genesis_Admin_Form: $pagehook . '_settings_page_form'
- Genesis_Admin_Boxes: genesis_admin_before_metaboxes & genesis_admin_after_metaboxes
So, let's create our own child theme settings page. To do this, you will need to create a new file called child-theme-settings.php
.
Page Level Documentation
For a good walk through on theme documentation, please read Michael Fields's Theme Documentation post. For our purposes...
[php]
/**
* Child Theme Settings
* Requires Genesis 1.8 or later
*
* This file registers all of this child theme's
* specific Theme Settings, accessible from
* Genesis > Child Theme Settings.
*
* @package WPS_Starter_Genesis_Child
* @author Travis Smith <travis@wpsmith.net>
* @copyright Copyright (c) 2012, Travis Smith
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.0
* @alter 1.1.2012
*
*/
[/php]
Extending the Class
Next, if you are familiar with classes (even widgets), this will seem simple; however, if you are unfamiliar, this is an important piece of code.
[php]
/**
* Registers a new admin page, providing content and corresponding menu item
* for the Child Theme Settings page.
*
* @package WPS_Starter_Genesis_Child
* @subpackage Admin
*
* @since 1.0.0
*/
class Child_Theme_Settings extends Genesis_Admin_Boxes {
[/php]
So what's happening here is that I am creating a new class that is based on the class Genesis_Admin_Boxes, and when you dig deeper, the Genesis_Admin_Boxes class is based on the Genesis_Admin class, which is THE base class that creates menus and settings pages. The Genesis_Admin_Boxes extends the Genesis_Admin classes by preparing the pages for metaboxes.
The Construct Method
In case you don't know a function inside a class is called a method. So now, we need to construct our new Child_Theme_Settings class.
[php]
/**
* Create an admin menu item and settings page.
*
* @since 1.0.0
*/
function __construct() {
// Specify a unique page ID.
$page_id = 'child';
// Set it as a child to genesis, and define the menu and page titles
$menu_ops = array(
'submenu' => array(
'parent_slug' => 'genesis',
'page_title' => 'Genesis - WPS Starter Settings',
'menu_title' => 'WPS Starter Settings',
'capability' => 'manage_options',
)
);
// Set up page options. These are optional, so only uncomment if you want to change the defaults
$page_ops = array(
'screen_icon' => array( 'custom' => WPS_ADMIN_IMAGES . '/staff_32x32.png' ),
// 'screen_icon' => 'options-general',
// 'save_button_text' => 'Save Settings',
// 'reset_button_text' => 'Reset Settings',
// 'save_notice_text' => 'Settings saved.',
// 'reset_notice_text' => 'Settings reset.',
);
// Give it a unique settings field.
// You'll access them from genesis_get_option( 'option_name', CHILD_SETTINGS_FIELD );
$settings_field = CHILD_SETTINGS_FIELD;
// Set the default values
$default_settings = array(
'phone' => '',
'address' => '',
);
// Create the Admin Page
$this->create( $page_id, $menu_ops, $page_ops, $settings_field, $default_settings );
// Initialize the Sanitization Filter
add_action( 'genesis_settings_sanitizer_init', array( $this, 'sanitization_filters' ) );
}
[/php]
Page ID & Menu Page
There is a lot going on here that is fairly well documented. $page_id sets the admin url slug for the page. For this page, the admin url will be: wp-admin/admin.php?page=child
. $menu_ops controls the creation of the submenu item. The submenu array controls who is the parent (obviously, if you are creating a Genesis Child Theme, this will be set to 'genesis'). However, the Genesis Admin class does not limit you. If I wanted an admin page to appear under Appearance, I could change 'parent' to themes.php, or if I wanted to add an admin page to Media, I would change the parent to upload.php, etc. For more information about what parent page slugs are, see the WordPress Codex: add_submenu_page.
Next, the page title and the menu title are self-explanatory where one refers to what will be outputted on the page title area, while the other is what appears in the submenu area. Capability can be set to whatever you'd like. If you want to be consistent with Genesis, you want to set this to edit_theme_options
.
Next, we have the page options, which are optional. Currently, the screen_icon does not accept custom icons, though a ticket exists for this and may make the final edition of Genesis 1.8. Otherwise, you are limited to the standard WordPress icons. There isn't much about the available screen icon choices, so here is a small list:
- plugins
- edit
- upload
- index
- link-manager
- edit-pages
- edit-comments
- themes
- users
- tools
- options-general
Next, we have the settings field, which I have set to a constant CHILD_SETTINGS_FIELD. This really can be whatever you want it to be to refer to your settings (e.g., 'child-settings'). Then we have the default settings that you would like to be created. The settings field and the defaults will be used to create an options field so that essentially add_option ( 'child-settings' , $default_settings );
takes place later. The default settings will also be used to reset theme options. In my child theme, I have no values set, so on Reset, everything will be erased.
Finally, we have everything we need to create the admin page via, what I could coin as the creation call. And as an added bonus, we can validate/sanitize our settings via the genesis sanitization class. So we add the action, which is expecting a reference array action.
The Sanitization Method
While a lot could be said about the sanitization class, since it's not new, let's just review the various options before moving forward. They are:
- one_zero: Same as true-false
- no_html: Does not allow for any HTML
- safe_html: Removes unsafe HTML via wp_kses_post()
- requires_unfiltered_html: Keeps the option from being updated if the user lacks unfiltered_html capability
So now we will add the sanitization method:
[php]
/**
* Set up Sanitization Filters
*
* See /lib/classes/sanitization.php for all available filters.
*
* @since 1.0.0
*/
function sanitization_filters() {
genesis_add_option_filter( 'no_html', $this->settings_field,
array(
'phone',
'address',
) );
}
[/php]
The Metabox Method
Now that the page has been created and the option defaults have been set and sanitized on save, we can create our metaboxes.
[php]
/**
* Register metaboxes on Child Theme Settings page
*
* @since 1.0.0
*
* @see Child_Theme_Settings::contact_information() Callback for contact information
*/
function metaboxes() {
add_meta_box( 'contact-information', 'Contact Information', array( $this, 'contact_information' ), $this->pagehook, 'main', 'high' );
}
[/php]
No more necessary additions of in-between functions, etc., etc. Simply add the metabox. For more information on the metabox function, see the WordPress Codex: add_meta_box.
The Metabox Callback Method
Since we said we would call a contact_information method, we need to build that method.
[php]
/**
* Callback for Contact Information metabox
*
* @since 1.0.0
*
* @see Child_Theme_Settings::metaboxes()
*/
function contact_information() {
echo '<p>Phone:<br />';
echo '<input type="text" name="' . $this->get_field_name( 'phone' ) . '" id="' . $this->get_field_id( 'phone' ) . '" value="' . esc_attr( $this->get_field_value( 'phone' ) ) . '" size="50" />';
echo '</p>';
echo '<p>Address</p>';
echo '<p><textarea name="' . $this->get_field_name( 'address' ) . '" cols="78" rows="8">' . esc_textarea( $this->get_field_value( 'address' ) ) . '</textarea></p>';
}
[/php]
This is what will go inside your metabox. It is fairly straightforward but there are a couple of functions that I'd like to point out: get_field_name, get_field_id, & get_field_value. These are built in functions that will take information provided in the construct method that will generate proper HTML names, ids, and values based on your $settings_field.
The Help Method
Now my favorite part, and my contribution to the admin class, the help() method. To add contextual help, all you need to do is create a help method.
[php]
/**
* Register contextual help on Child Theme Settings page
*
* @since 1.0.0
*
*/
function help( ) {
global $my_admin_page;
$screen = get_current_screen();
if ( $screen->id != $this->pagehook )
return;
$tab1_help =
'<h3>' . __( 'H3 Heading' , CHILD_DOMAIN ) . '</h3>' .
'<p>' . __( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur in odio lacus. Fusce lacinia viverra facilisis. Nunc urna lorem, tempus in sollicitudin ac, fringilla non lacus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque lacinia, arcu ut porta laoreet, elit justo volutpat augue, commodo condimentum neque sapien a tellus. Fusce tempus elit sodales dui vehicula tempus. Aliquam lobortis laoreet tortor, facilisis blandit sem viverra at. Ut iaculis, metus ac faucibus aliquam, diam tortor commodo felis, sed fermentum velit nunc ac arcu. Ut in libero ante.' , CHILD_DOMAIN ) . '</p>';
$tab2_help =
'<h3>' . __( 'H3 Heading' , CHILD_DOMAIN ) . '</h3>' .
'<p>' . __( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur in odio lacus. Fusce lacinia viverra facilisis. Nunc urna lorem, tempus in sollicitudin ac, fringilla non lacus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque lacinia, arcu ut porta laoreet, elit justo volutpat augue, commodo condimentum neque sapien a tellus. Fusce tempus elit sodales dui vehicula tempus. Aliquam lobortis laoreet tortor, facilisis blandit sem viverra at. Ut iaculis, metus ac faucibus aliquam, diam tortor commodo felis, sed fermentum velit nunc ac arcu. Ut in libero ante.' , CHILD_DOMAIN ) . '</p>';
$tab3_help =
'<h3>' . __( 'H3 Heading' , CHILD_DOMAIN ) . '</h3>' .
'<p>' . __( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur in odio lacus. Fusce lacinia viverra facilisis. Nunc urna lorem, tempus in sollicitudin ac, fringilla non lacus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque lacinia, arcu ut porta laoreet, elit justo volutpat augue, commodo condimentum neque sapien a tellus. Fusce tempus elit sodales dui vehicula tempus. Aliquam lobortis laoreet tortor, facilisis blandit sem viverra at. Ut iaculis, metus ac faucibus aliquam, diam tortor commodo felis, sed fermentum velit nunc ac arcu. Ut in libero ante.' , CHILD_DOMAIN ) . '</p>' .
'<h4>' . __( 'H4 Heading' , CHILD_DOMAIN ) . '</h4>' .
'<p>' . __( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur in odio lacus. Fusce lacinia viverra facilisis. Nunc urna lorem, tempus in sollicitudin ac, fringilla non lacus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque lacinia, arcu ut porta laoreet, elit justo volutpat augue, commodo condimentum neque sapien a tellus. Fusce tempus elit sodales dui vehicula tempus. Aliquam lobortis laoreet tortor, facilisis blandit sem viverra at. Ut iaculis, metus ac faucibus aliquam, diam tortor commodo felis, sed fermentum velit nunc ac arcu. Ut in libero ante.' , CHILD_DOMAIN ) . '</p>';
$screen->add_help_tab(
array(
'id' => $this->pagehook . '-tab1',
'title' => __( 'Tab 1' , CHILD_DOMAIN ),
'content' => $tab1_help,
) );
$screen->add_help_tab(
array(
'id' => $this->pagehook . '-tab2',
'title' => __( 'Tab 2' , CHILD_DOMAIN ),
'content' => $tab2_help,
) );
$screen->add_help_tab(
array(
'id' => $this->pagehook . '-tab3',
'title' => __( 'Tab 3' , CHILD_DOMAIN ),
'content' => $tab3_help,
) );
// Add Genesis Sidebar
$screen->set_help_sidebar(
'<p><strong>' . __( 'For more information:', CHILD_DOMAIN ) . '</strong></p>'.
'<p><a href="' . __( 'http://www.studiopress.com/support', CHILD_DOMAIN ) . '" target="_blank" title="' . __( 'Support Forums', CHILD_DOMAIN ) . '">' . __( 'Support Forums', CHILD_DOMAIN ) . '</a></p>'.
'<p><a href="' . __( 'http://www.studiopress.com/tutorials', CHILD_DOMAIN ) . '" target="_blank" title="' . __( 'Genesis Tutorials', CHILD_DOMAIN ) . '">' . __( 'Genesis Tutorials', CHILD_DOMAIN ) . '</a></p>'.
'<p><a href="' . __( 'http://dev.studiopress.com/', CHILD_DOMAIN ) . '" target="_blank" title="' . __( 'Genesis Developer Docs', CHILD_DOMAIN ) . '">' . __( 'Genesis Developer Docs', CHILD_DOMAIN ) . '</a></p>'
);
}
[/php]
You simply have to try it!
Adding the Child Theme Settings Page
Now that we have the class built, nothing happens until we instantiate or initialize the class. So we create a function to do this after we close the class with a closing bracket. Then we call the class:
[php]
/**
* Add the Theme Settings Page
*
* @since 1.0.0
*/
function wps_add_child_theme_settings() {
global $_child_theme_settings;
$_child_theme_settings = new Child_Theme_Settings;
}
add_action( 'admin_menu', 'wps_add_child_theme_settings', 5 );
[/php]
So here is our page in full:
[php]
<?php
/**
* Child Theme Settings
* Requires Genesis 1.8 or later
*
* This file registers all of this child theme's
* specific Theme Settings, accessible from
* Genesis > Child Theme Settings.
*
* @package WPS_Starter_Genesis_Child
* @author Travis Smith <travis@wpsmith.net>
* @copyright Copyright (c) 2012, Travis Smith
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.0
* @alter 1.1.2012
*
*/
/**
* Registers a new admin page, providing content and corresponding menu item
* for the Child Theme Settings page.
*
* @package WPS_Starter_Genesis_Child
* @subpackage Admin
*
* @since 1.0.0
*/
class Child_Theme_Settings extends Genesis_Admin_Boxes {
/**
* Create an admin menu item and settings page.
*
* @since 1.0.0
*/
function __construct() {
// Specify a unique page ID.
$page_id = 'child';
// Set it as a child to genesis, and define the menu and page titles
$menu_ops = array(
'submenu' => array(
'parent_slug' => 'upload.php',
'page_title' => 'Genesis - WPS Starter Settings',
'menu_title' => 'WPS Starter Settings',
'capability' => 'manage_options',
)
);
// Set up page options. These are optional, so only uncomment if you want to change the defaults
$page_ops = array(
// 'screen_icon' => array( 'custom' => WPS_ADMIN_IMAGES . '/staff_32x32.png' ),
'screen_icon' => 'users',
// 'save_button_text' => 'Save Settings',
// 'reset_button_text' => 'Reset Settings',
// 'save_notice_text' => 'Settings saved.',
// 'reset_notice_text' => 'Settings reset.',
);
// Give it a unique settings field.
// You'll access them from genesis_get_option( 'option_name', CHILD_SETTINGS_FIELD );
$settings_field = CHILD_SETTINGS_FIELD;
// Set the default values
$default_settings = array(
'phone' => '',
'address' => '',
);
// Create the Admin Page
$this->create( $page_id, $menu_ops, $page_ops, $settings_field, $default_settings );
// Initialize the Sanitization Filter
add_action( 'genesis_settings_sanitizer_init', array( $this, 'sanitization_filters' ) );
}
/**
* Set up Sanitization Filters
*
* See /lib/classes/sanitization.php for all available filters.
*
* @since 1.0.0
*/
function sanitization_filters() {
genesis_add_option_filter( 'no_html', $this->settings_field,
array(
'phone',
'address',
) );
}
/**
* Register metaboxes on Child Theme Settings page
*
* @since 1.0.0
*
* @see Child_Theme_Settings::contact_information() Callback for contact information
*/
function metaboxes() {
add_meta_box('contact-information', 'Contact Information', array( $this, 'contact_information' ), $this->pagehook, 'main', 'high');
}
/**
* Register contextual help on Child Theme Settings page
*
* @since 1.0.0
*
*/
function help( ) {
global $my_admin_page;
$screen = get_current_screen();
if ( $screen->id != $this->pagehook )
return;
$tab1_help =
'<h3>' . __( 'H3 Heading' , CHILD_DOMAIN ) . '</h3>' .
'<p>' . __( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur in odio lacus. Fusce lacinia viverra facilisis. Nunc urna lorem, tempus in sollicitudin ac, fringilla non lacus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque lacinia, arcu ut porta laoreet, elit justo volutpat augue, commodo condimentum neque sapien a tellus. Fusce tempus elit sodales dui vehicula tempus. Aliquam lobortis laoreet tortor, facilisis blandit sem viverra at. Ut iaculis, metus ac faucibus aliquam, diam tortor commodo felis, sed fermentum velit nunc ac arcu. Ut in libero ante.' , CHILD_DOMAIN ) . '</p>';
$tab2_help =
'<h3>' . __( 'H3 Heading' , CHILD_DOMAIN ) . '</h3>' .
'<p>' . __( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur in odio lacus. Fusce lacinia viverra facilisis. Nunc urna lorem, tempus in sollicitudin ac, fringilla non lacus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque lacinia, arcu ut porta laoreet, elit justo volutpat augue, commodo condimentum neque sapien a tellus. Fusce tempus elit sodales dui vehicula tempus. Aliquam lobortis laoreet tortor, facilisis blandit sem viverra at. Ut iaculis, metus ac faucibus aliquam, diam tortor commodo felis, sed fermentum velit nunc ac arcu. Ut in libero ante.' , CHILD_DOMAIN ) . '</p>';
$tab3_help =
'<h3>' . __( 'H3 Heading' , CHILD_DOMAIN ) . '</h3>' .
'<p>' . __( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur in odio lacus. Fusce lacinia viverra facilisis. Nunc urna lorem, tempus in sollicitudin ac, fringilla non lacus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque lacinia, arcu ut porta laoreet, elit justo volutpat augue, commodo condimentum neque sapien a tellus. Fusce tempus elit sodales dui vehicula tempus. Aliquam lobortis laoreet tortor, facilisis blandit sem viverra at. Ut iaculis, metus ac faucibus aliquam, diam tortor commodo felis, sed fermentum velit nunc ac arcu. Ut in libero ante.' , CHILD_DOMAIN ) . '</p>' .
'<h4>' . __( 'H4 Heading' , CHILD_DOMAIN ) . '</h4>' .
'<p>' . __( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur in odio lacus. Fusce lacinia viverra facilisis. Nunc urna lorem, tempus in sollicitudin ac, fringilla non lacus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque lacinia, arcu ut porta laoreet, elit justo volutpat augue, commodo condimentum neque sapien a tellus. Fusce tempus elit sodales dui vehicula tempus. Aliquam lobortis laoreet tortor, facilisis blandit sem viverra at. Ut iaculis, metus ac faucibus aliquam, diam tortor commodo felis, sed fermentum velit nunc ac arcu. Ut in libero ante.' , CHILD_DOMAIN ) . '</p>';
$screen->add_help_tab(
array(
'id' => $this->pagehook . '-tab1',
'title' => __( 'Tab 1' , CHILD_DOMAIN ),
'content' => $tab1_help,
) );
$screen->add_help_tab(
array(
'id' => $this->pagehook . '-tab2',
'title' => __( 'Tab 2' , CHILD_DOMAIN ),
'content' => $tab2_help,
) );
$screen->add_help_tab(
array(
'id' => $this->pagehook . '-tab3',
'title' => __( 'Tab 3' , CHILD_DOMAIN ),
'content' => $tab3_help,
) );
// Add Genesis Sidebar
$screen->set_help_sidebar(
'<p><strong>' . __( 'For more information:', CHILD_DOMAIN ) . '</strong></p>'.
'<p><a href="' . __( 'http://www.studiopress.com/support', CHILD_DOMAIN ) . '" target="_blank" title="' . __( 'Support Forums', CHILD_DOMAIN ) . '">' . __( 'Support Forums', CHILD_DOMAIN ) . '</a></p>'.
'<p><a href="' . __( 'http://www.studiopress.com/tutorials', CHILD_DOMAIN ) . '" target="_blank" title="' . __( 'Genesis Tutorials', CHILD_DOMAIN ) . '">' . __( 'Genesis Tutorials', CHILD_DOMAIN ) . '</a></p>'.
'<p><a href="' . __( 'http://dev.studiopress.com/', CHILD_DOMAIN ) . '" target="_blank" title="' . __( 'Genesis Developer Docs', CHILD_DOMAIN ) . '">' . __( 'Genesis Developer Docs', CHILD_DOMAIN ) . '</a></p>'
);
}
/**
* Callback for Contact Information metabox
*
* @since 1.0.0
*
* @see Child_Theme_Settings::metaboxes()
*/
function contact_information() {
echo '<p>Phone:<br />';
echo '<input type="text" name="' . $this->get_field_name( 'phone' ) . '" id="' . $this->get_field_id( 'phone' ) . '" value="' . esc_attr( $this->get_field_value( 'phone' ) ) . '" size="50" />';
echo '</p>';
echo '<p>Address</p>';
echo '<p><textarea name="' . $this->get_field_name( 'address' ) . '" cols="78" rows="8">' . esc_textarea( $this->get_field_value( 'address' ) ) . '</textarea></p>';
}
}
/**
* Add the Theme Settings Page
*
* @since 1.0.0
*/
function wps_add_child_theme_settings() {
global $_child_theme_settings;
$_child_theme_settings = new Child_Theme_Settings;
}
add_action( 'admin_menu', 'wps_add_child_theme_settings', 5 );
[/php]