Building a Settings Page

Many plugins offer a settings page that allows the user to customize plugin options. The options offered by a settings page varies from a few check boxes, drop downs, or text inputs to multiple advanced editors that allow the user to build data sets, set up forums, or do advanced content management. Although this section focuses on building a simple settings page, you can expand the concept to fill any type of need that your plugin has.

When reduced to a bare minimum, a basic settings page consists of code that displays the page, stores the settings, and adds the page to the WordPress admin menu. The plugin created in this section will give you a solid foundation that you can use to build your own plugin settings pages.

Setting up the plugin structure

The plugin you create in this section is Example: Settings Page. To get started with this plugin, create a new plugins directory named /example-settings-page. All the files for this plugin go in this new directory. That's right, files. We're going to change up the structure a little bit in this plugin by adding multiple plugin files to the plugin directory.

As plugins get larger, having everything in one file quickly becomes hard to manage. A good practice is to separate different functionality into separate files. Similar to the way the init.php file is named because it initializes the plugin, the other files used by the plugin should be named so the purpose of each file is easy to discern when looking at the filenames.

This new plugin will have the following files, so go ahead and create five blank files and name them with the filenames given here:

  • init.php: Contains the plugin header and will load the other needed plugin files
  • settings-page.php: Holds the settings page code
  • default-settings.php: Sets the default values used for the settings
  • msp-form-class.php: Provides a class that makes adding form inputs easy
  • settings-functions.php: Provides functions to load and save the settings

By dividing the plugin code into logical groups, each of which have their own file, the code becomes much easier to maintain. With this type of setup, as new features are added to the plugin, they can easily be isolated to their own files.

All the files must be created before the plugin will function. To start, add the following code to your plugin's init.php file:

<?php
/*
Plugin Name: Example: Settings Page
Description: This plugin is offers a solid starting point for building
    settings pages
*/

require_once(dirname(__FILE__).'/default-settings.php'),
require_once(dirname(__FILE__).'/msp-form-class.php'),
require_once(dirname(__FILE__).'/settings-functions.php'),
require_once(dirname(__FILE__).'/settings-page.php'),

The require_once function loads another PHP file. If the file isn't found, a fatal error occurs and the plugin doesn't function. Therefore, trying to activate the plugin at this point causes the plugin to fail. This is good because it prevents the plugin from activating when needed files are missing, which can happen if an incomplete upload of the plugin files occurs.

image There are four primary functions to load other PHP code: include, include_once, require, and require_once. The include functions will not cause a fatal error if there is a problem loading the requested file, while the require functions will. The functions that add _once will not load the file if the file has been loaded already. This helps prevent accidentally loading a file multiple times, which can break the code or cause unexpected behavior.

Directly underneath the require_once functions, add the following line:

dirname(__FILE__).'/default-settings.php'

This section of code finds the full path to the default-settings.php file. We recommend loading the file by referring to its full path because it avoids issues with some server setups.

That's all the init.php file needs for this plugin. You can now save and upload the file to your plugin directory at /wp-content/plugins/example-settings-page. When you add new features to the plugin, add new files to hold these features and use a require_once call to load each one.

Adding a new Admin menu entry

Add the following lines of code to the settings-page.php file that you created at the beginning of this section:

<?php

function msp_add_admin_menu() {
add_options_page(
  'Example Settings Page',
  'Example Settings',
  'manage_options',
  'msp-example-settings-page',
  'msp_display_settings_page'
);
if(isset($_POST['msp_save'])) {
  add_action(“admin_head-$page”,'msp_save_settings_handler'),
}
}
add_action('admin_menu','msp_add_admin_menu'),

This code adds a new link in the DashboardimageSettings menu titled Example Setting. The add_options_page function is the key to adding this new menu. The following list describes what each argument in this function does.

  • Example Settings Page: The first argument sets the title of the page. The browser, not the settings page, displays this title.
  • Example Settings: The second argument is the name of the menu. The space is limited, so try to keep the name short.
  • manage_options: The third argument is the capability that the user must have in order to see and access the menu. For settings pages, the manage_options capability is typically the best choice as only administrators have this capability by default. edit_others_posts can be used to allow administrators and editors, whereas, edit_published_posts can be used for administrators, editors, and authors.
  • msp-example-settings-page: The fourth argument is a name that WordPress uses internally to navigate to the page. Make sure that this is a unique name or you can run into problems with other plugins. The msp at the front of the name stands for My Settings Page. Consistently using a prefix in this manner helps prevent duplicate name issues.
  • msp_display_settings_page: The fifth argument is the name of the function that is called when the page is viewed. As with the fourth argument, make sure that this is unique to your plugin. Notice the msp prefix is used here, too.

Just as the register_widget function cannot be called when a plugin first loads, the add_options_page function also must wait until WordPress is ready before it can be called. To call the function when WordPress is ready, it's wrapped in a function that's called when the admin_menu action is run.

Other than registering the new admin menu, this code also does a check that adds a page-specific action if form data with a msp_save variable has been submitted. When this action fires, the msp_save_settings_handler function will process and save the submitted form data.

Creating a settings form

There are as many ways to set up a settings form as there are stars in the sky. Well, maybe not quite that many, but we're sure that the numbers are close. Most of these methods use large sections of repeated code for each individual input.

This form shows how each type of HTML form input type can be integrated into your settings form. Instead of manually coding each input, which is time consuming and error prone, a set of functions is provided that make adding new inputs very easy.

Open your plugin settings-page.php file and follow these steps to add the code that handles the HTML form input for your settings page:

  1. Open this file in your text editor: settings-page.php
  2. Add the following line of code at the bottom of the settings-php file:
    function msp_display_settings_page() {
    $form=new MSP_Form(msp_get_settings());
    ?>

    The msp-form-class.php file, which we will create later, contains a new class called MSP_Form. This class accepts an array of settings to assign the initial values of the form inputs. The settings come from the msp_get_settings function, which will be defined in the settings-functions.php file (covered in the next section).

    When using a class like this, a variable stores an object. In this case, the object is stored in a variable called $form. Later in this form code, the $form variable will be used to easily add new form inputs by using the functions provided by the MSP_Form class.

  3. Press Enter and type the following lines of code:
    <?php if(isset($_GET['updated'])) : ?>
    <div id="message_58_chapter-05" class="updated fade">
      <p><strong>Settings saved.</strong></p>
    </div>
    <?php endif; ?>

    When the form data is saved, the page redirects to a new settings page link that contains a variable named updated. So, this section of code displays a Settings saved message when this redirect happens, confirming to the user that their settings changes are saved.

  4. Press Enter and type the following lines of code:
    <div class="wrap">
    <?php screen_icon(); ?>
    <h2>Example Settings Page</h2>

    This section simply follows the page structure used by WordPress's built-in editors so that your settings page fits in with the style of WordPress.

  5. Press Enter and type the following line of code:
    <form method="post" action="<?php echo $_SERVER['REQUEST_URI']; ?>">

    Many settings pages use code that submits the form data to the options.php page built into WordPress. To have a bit more control over how the data is saved, this settings page form sends the data back to itself, allowing this plugin's code to have full control over how the data is stored.

  6. Press Enter and type the following line of code:
    <?php wp_nonce_field('msp-update-settings'), ?>

    The wp_nonce_field function is part of the nonce system of WordPress. Nonces protect a site against attackers. All your WordPress-managed forms should use nonces and use them properly. The key is to have the wp_nonce_field function call (with a unique attribute to identify the form's purpose) inside the HTML form tags and a call to check_admin_referer (that uses a matching attribute) before any action is taken with the form data. The check_admin_referer call can be found in the msp_save_settings_handler function at the end of this file's code.

  7. Press Enter and type the following code:
    <table class="form-table">
    <tr valign="top">
    <th scope="row"><label for="text">Text</label></th>
    <td>
    <?php $form->add_text('text'), ?>
    </td>
    </tr>
    <tr valign="top">
    <th scope="row"><label for="textarea">Text Area</label></th>
    <td>
    <?php $form->add_textarea('textarea'), ?>
    </td>
    </tr>

    This is the table structure commonly used in editors throughout WordPress, using the HTML markup to create tables. It is simple and easy to expand to have new options. I typically just copy a single row, paste a few copies, and then modify each copy to have a new input when I expand my forms.

    The call to the $form->add_text function is what adds the text input to the form. This function accepts an argument that defines what the name of the setting is, text in this case. The textarea section of the code follows the same format as this section.

  8. Press Enter and type the following lines of code:
    <tr valign="top">
    <th scope="row">Multi-Checkbox</th>
    <td>
    <label title="1">
    <?php $form->add_multicheckbox('multicheckbox','1'), ?> 1
    </label><br />
    <label title="2">
    <?php $form->add_multicheckbox('multicheckbox','2'), ?> 2
    </label><br />
    <label title="3">
    <?php $form->add_multicheckbox('multicheckbox','3'), ?> 3
    </label><br />
    <label title="4">
    <?php $form->add_multicheckbox('multicheckbox','4'), ?> 4
    </label>
    </td>
    </tr>

    This section makes use of the MSP_Form class' add_multicheckbox function to create a form input that allows multiple values to be stored in a single setting. The second argument used for this function sets the value that the specific check box has. When loading data from this type of setting, the values of the checked inputs will be stored in an array.

  9. Press Enter and type the following lines of code:
    <tr valign="top">
    <th scope="row">Radio</th>
    <td>
    <label title="Option 1">
    <?php $form->add_radio('radio','1'), ?>
    Option 1
    </label>
    <br />
    <label title="Option 2">
    <?php $form->add_radio('radio','2'), ?>
    Option 2
    </label>
    <br />
    <label title="Option 3">
    <?php $form->add_radio('radio','3'), ?>
    Option 3
    </label>
    </td>
    </tr>

    This section makes use of the MSP_Form class's add_radio function to create a form input using radios buttons. It uses the same format as the multicheckbox inputs from Step 8. The second argument is used to set the value used for the individual input. Unlike the multicheckbox inputs, the data loaded for a radio setting is a string and not an array.

  10. Press Enter and type the following lines of code:
    <tr valign="top">
    <th scope="row"><label for="select">Select</label></th>
    <td>
    <?php
    $options = array(
      '1'=>'Option 1',
      '2'=>'Option 2',
      '3'=>'Option 3',
    );
    ?>
    <?php $form->add_select('select',$options); ?>
    </td>
    </tr>
    </table>

    Select inputs can be very difficult to code by hand. The MSP_Form class makes adding a select input very easy. First, create an associative, or named, array. A named array sets the key to be used for each value. In other words, each array input looks like ‘1’=>‘Option 1’, where 1 is the value to be stored for that setting and Option 1 is the description to show for that value. Then the named array is passed in as the second argument to the add_select function.

  11. Press Enter and type the following lines of code:
    <p class="submit">
    <input type="submit" name="msp_save" class="button-primary" value="Save
        Changes" />
    </p>

    Note the msp_save value used for the submit button's name. This is the name used to check for a settings form submission toward the top of this file.

  12. Press Enter and type the following lines of code:
    <?php $form->add_used_inputs(); ?>
    </form>
    </div>

    This call to add_used_inputs is very important for handling the submitted form data.

  13. Press Enter and type the following lines of code:
    <?php
    }
    function msp_save_settings_handler() {
    check_admin_referer('msp-update-settings'),
    $settings=MSP_Form::get_post_data();
    msp_update_settings($settings);
    }

    The msp_save_settings_handler completes the settings-page.php code. First, the nonce set inside the form is checked with the check_admin_referer to ensure that proper use of nonces is used. The MSP_Form class function get_post_data is used to store that submitted settings into the $settings variable. These settings are then passed to the msp_update_settings function (defined in the settings-functions.php file) to save the settings.

When you finish, the code in your entire settings-page.php file looks like this:

<?php

function msp_add_admin_menu() {
add_options_page(
  'Example Settings Page',
  'Example Settings',
  'manage_options',
  'msp-example-settings-page',
  'msp_display_settings_page'
);
if(isset($_POST['msp_save'])) {
  add_action("admin_head-$page",'msp_save_settings_handler'),
}
}
add_action('admin_menu','msp_add_admin_menu'),

function msp_display_settings_page() {
$form=new MSP_Form(msp_get_settings());
?>
<?php if(isset($_GET['updated'])) : ?>
<div id="message_58_chapter-05" class="updated fade">
  <p><strong>Settings saved.</strong></p>
</div>
<?php endif; ?>
<div class="wrap">
<?php screen_icon(); ?>
<h2>Example Settings Page</h2>
<form method="post" action="<?php echo $_SERVER['REQUEST_URI']; ?>">
<?php wp_nonce_field('msp-update-settings'), ?>
<table class="form-table">
<tr valign="top">
<th scope="row"><label for="text">Text</label></th>
<td>
<?php $form->add_text('text'), ?>
</td>
</tr>
<tr valign="top">
<th scope="row"><label for="textarea">Text Area</label></th>
<td>
<?php $form->add_textarea('textarea'), ?>
</td>
</tr>
<tr valign="top">
<th scope="row"><label for="checkbox">Checkbox</label></th>
<td>
<?php $form->add_checkbox('checkbox'), ?>
</td>
</tr>
<tr valign="top">
<th scope="row">Multi-Checkbox</th>
<td>
<label title="1">
<?php $form->add_multicheckbox('multicheckbox','1'), ?> 1
</label><br />
<label title="2">
<?php $form->add_multicheckbox('multicheckbox','2'), ?> 2
</label><br />
<label title="3">
<?php $form->add_multicheckbox('multicheckbox','3'), ?> 3
</label><br />
<label title="4">
<?php $form->add_multicheckbox('multicheckbox','4'), ?> 4
</label>
</td>
</tr>
<tr valign="top">
<th scope="row">Radio</th>
<td>
<label title="Option 1">
<?php $form->add_radio('radio','1'), ?>
Option 1
</label>
<br />
<label title="Option 2">
<?php $form->add_radio('radio','2'), ?>
Option 2
</label>
<br />
<label title="Option 3">
<?php $form->add_radio('radio','3'), ?>
Option 3
</label>
</td>
</tr>
<tr valign="top">
<th scope="row"><label for="select">Select</label></th>
<td>
<?php
$options = array(
  '1'=>'Option 1',
  '2'=>'Option 2',
  '3'=>'Option 3',
);
?>
<?php $form->add_select('select',$options); ?>
</td>
</tr>
</table>
<p class="submit">
<input type="submit" name="msp_save" class="button-primary" value="Save Changes" />
</p>
<?php $form->add_used_inputs(); ?>
</form>
</div>
<?php
}
function msp_save_settings_handler() {
check_admin_referer('msp-update-settings'),
$settings=MSP_Form::get_post_data();
msp_update_settings($settings);
}

Configuring default settings

A nice feature of this settings form code is that default settings can be set easily. These default settings are loaded even if the settings form hasn't been saved, allowing for reliable use of the defaults.

To set up the defaults, add the following code to a new file and save it as default-settings.php in your /example-settings page plugin directory:

<?php
function msp_get_default_settings() {
  $defaults=array(
   'text' => 'Sample Text',
   'textarea' => 'Sample Textarea Text',
   'checkbox' => '1',
   'multicheckbox' => array('2','3'),
   'radio'    => '2',
   'select'   => '3',
  );
  return $defaults;
}

By modifying the $defaults array, new default values can be added, removed, or modified easily. The format for this type of array is setting_name'=>'setting_value', where setting_name is the name of the setting and setting_value is the default value you want to use for that setting.

Adding settings functions

The settings functions manage loading and saving settings. Both functions are optimized for performance and reliability. Add the following code to a new file and save it as settings-functions.php in your /example-settings-page plugin directory:

<?php
function msp_get_settings($name=null) {
static $settings=null;

if(is_null($settings)) {
$settings=get_option('msp-example-settings'),
if(!is_array($settings)) $settings=array();

$defaults=msp_get_default_settings();
$settings=array_merge($defaults,$settings);
}

if(is_null($name)) return $settings;
if(isset($settings[$name])) return $settings[$name];
return '';
}

function msp_update_settings($settings) {
update_option('msp-example-settings',$settings);

$redirect_url=array_shift(explode('?',$_SERVER['REQUEST_URI;]));
$redirect_url.='?page='.$_REQUEST['page'].'&updated=true';

wp_redirect($redirect_url);
}

$all_settings=msp_get_settings();
$text=msp_get_settings('text'),

By calling the function with no argument, all the settings are returned. When you pass a setting name, the value for just that setting is returned.

The msp_update_settings function accepts a new array of settings to be saved. After the settings are saved, a new redirect link with the “updated” variable is built that displays the Settings saved message. WordPress's wp_redirect function then redirects the site to this new link.

Creating the MSP_Form class

The MSP_Form class code is quite lengthy. It is well worth the effort as it makes form building very easy.

Add the following code to a new file and save it as msp-form-class.php in your /example-settings-page plugin directory:

<?php
class MSP_Form {
var $inputs=array();
var $settings=array();
function MSP_Form($settings=array()) {
if(is_array($settings)) $this->settings=$settings;
}
function add_used_inputs() {
$value=implode(',',array_unique($this->inputs));
$this->add_hidden('___msp_form_used_inputs',$value);
}
function get_post_data() {
if(!isset($_POST['___msp_form_used_inputs'])) {
return $_POST;
}
$data=array();
$inputs=explode(',',$_POST['___msp_form_used_inputs']);
foreach((array)$inputs as $var) {
$real_var=str_replace('[]','',$var);
if(isset($_POST[$real_var])) {
$data[$real_var]=stripslashes_deep($_POST[$real_var]);
}
else if($var!=$real_var) {
$data[$real_var]=array();
}
else {
$data[$real_var]='';
}
}
return $data;
}

// $form->add_text('name'),
function add_text($name,$options=array()) {
if(!isset($options['class'])) $options['class']='regular-text';
$this->_add_input('text',$name,$options);
}
function add_textarea($name,$options=array()) {
$this->_add_input('textarea',$name,$options);
}
function add_checkbox($name,$options=array()) {
if($this->_get_setting($name)) $options['checked']='checked';
$this->_add_input('checkbox',$name,$options);
}
function add_file($name,$options=array()) {
$this->_add_input('file',$name,$options);
}
function add_password($name,$options=array()) {
$this->_add_input('password',$name,$options);
}
// $form->add_select('num',array('1'=>'One','2'=>'Two'));
function add_select($name,$values,$options=array()) {
$options['values']=$values;
$this->_add_input('select',$name,$options);
}

// $form->add_radio('type','extended'),
function add_radio($name,$value,$options=array()) {
if($this->_get_setting($name)==$value) $options['checked']='checked';
$options['value']=$value;
$this->_add_input('radio',$name,$options);
}
function add_multicheckbox($name,$value,$options=array()) {
$setting=$this->_get_setting($name);
if(is_array($setting) && in_array($value,$setting)) {
$options['checked']='checked';
}
$options['value']=$value;
$this->_add_input('checkbox',"{$name}[]",$options);
}
function add_hidden($name,$value,$options=array()) {
$options['value']=$value;
$this->_add_input('hidden',$name,$options);
}

// $form->add_submit('save','Save'),
function add_submit($name,$description,$options=array()) {
$options['value']=$description;
$this->_add_input('submit',$name,$options);
}
function add_button($name,$description,$options=array()) {
$options['value']=$description;
$this->_add_input('button',$name,$options);
}
function add_reset($name,$description,$options=array()) {
$options['value']=$description;
$this->_add_input('reset',$name,$options);
}

// $form->add_image('imagemap','http://domain.com/img.gif'),
function add_image($name,$image_url,$options=array()) {
$options['src']=$image_url;
$this->_add_input('image',$name,$options);
}

// This function should not be called directly.
function _add_input($type,$name,$options=array()) {
$this->inputs[]=$name;
$settings_var=str_replace('[]','',$name);
$css_var=str_replace('[','-',str_replace(']','',$settings_var));

if(!is_array($options)) $options=array();
$options['type']=$type;
$options['name']=$name;
if(!isset($options['value']) && 'checkbox'!=$type) {
$options['value']=$this->_get_setting($settings_var);
}
if('radio'==$type || $settings_var!=$name) {
if(empty($options['class'])) $options['class']=$css_var;
}
else {
if(empty($options['id'])) $options['id']=$css_var;
}

$scrublist=array($type=>array());
$scrublist['textarea']=array('value','type'),
$scrublist['file']=array('value'),
$scrublist['dropdown']=array('value','values','type'),

$attributes = '';
foreach($options as $var => $val) {
  if(!is_array($val) && !in_array($var,$scrublist[$type]))
  $attributes.="$var='".esc_attr($val)."' “;
}

if('textarea'==$options['type']) {
  echo "<textarea $attributes>";
  echo format_to_edit($options['value']);
  echo "</textarea>
";
}
else if('select'==$options['type']) {
  echo "<select $attributes>
";
  if(is_array($options['values'])) {
  foreach($options['values'] as $val=>$name) {
  $selected=($options['value']==$val)?' selected="selected"':'';
  echo "<option value="$val"$selected>$name</option>
";
  }
  }
  echo "</select>
";
}
else {
 echo "<input $attributes />
";
}
}

// This function should not be called directly.
function _get_setting($name) {
if(isset($this->settings[$name])) {
return $this->settings[$name];
}
return '';
}
}

You can use 13 functions to add inputs to a form. The following shows an example of how to use each one:

$form->add_text('setting_name'),
$form->add_textarea('setting_name'),
$form->add_checkbox('setting_name'),
$form->add_file('setting_name'),
$form->add_password('setting_name'),
$form->add_select('setting_name',array('1'=>'One','2'=>'Two'));
$form->add_radio('setting_name','value_1'),
$form->add_radio('setting_name','value_2'),
$form->add_multicheckbox('setting_name','value_1'),
$form->add_multicheckbox('setting_name','value_2'),
$form->add_hidden('setting_name','value'),
$form->add_submit('setting_name','value'),
$form->add_button('setting_name','value'),
$form->add_reset('setting_name','value'),
$form->add_image('imagemap','http://domain.com/img.gif'),

A feature that all the form input functions support is an optional last parameter to set additional HTML tag attributes to the final output. Here is an example of a block of code that sets additional HTML markup to the final output:

$form->add_text('setting_name',array('class'=>'regular-text code'));
$form->add_text('setting_name',array('style'=>'width:250px;font-
    size:2em;'));
$form->add_textarea('setting_name',array('rows'=>'10','cols'=>'30'));
$form->add_checkbox('setting_name',array('checked'=>'checked'));

This adds the class regular-text and code to the first text input, adds inline styling to control the width and font size of the second text input, uses 10 rows and 30 columns for the textarea input, and forces the checkbox to always be checked on page load for the last input.

This last optional argument can be used on any of the inputs to set needed tag attributes. By using this last argument in creative ways, you can always rely on using the input form functions rather than coding inputs by scratch.

Testing the plugin

After you have the files entered, you're ready to activate the Example: Settings Page plugin.

Because the code is divided, if you get an error about not being able to activate the plugin, note which file and line number had the error. This will help you quickly fix your error.

After activating the plugin, visit your Dashboard and go to SettingsimageExample Settings to see the settings form in action, as shown in Figure 5-10. Notice how the form is populated by the default values you set. These default values are set the first time the msp_get_settings function is called. Therefore, even if the user has never gone to your settings page, the defaults will be available. In addition, when you add new settings and update the defaults to have these new settings, those new defaults will also automatically become available.

Figure 5-10: Example Settings page.

image

After testing out the settings options, pop into the settings-page.php file and try adding new settings. When you have the new settings, make sure you update the $defaults array in default-settings.php.

This plugin can be extended with code from another one of the example plugins. To load the settings, simply use the msp_get_settings function.

For example, the widget function from the Example: My User Widget plugin you created earlier in this chapter could be updated to make use of two settings, guest_message and user_message.

function widget($args) {
$user=wp_get_current_user();
if(!isset($user->user_nicename))
$message=msp_get_settings('guest_message'),
else
$message=msp_get_settings('user_message').$user->user_nicename;

extract($args);

echo $before_widget;
echo "<p>$message</p>";
echo $after_widget;
}

Plugin development has helped WordPress give users the ability to extend the basic WordPress installation via functions and features provided by useful plugins. The contributions of plugin code from thousands of people around the world built up a platform capable of amazing things.

With the variety of plugins you developed through the course of this chapter, you already have a solid set of starting points for your own plugin developments. Apply a little creativity and effort into making one of the plugins your own, and you'll be amazed at what can be done.

You have the tools. Now show the world what you can do.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.93.175