Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have a template page in Wordpress that I want the Admin to be able to change the text on that page. I'd love to learn how to make a plugin (I know how to make a plugin so that it shows up in WP, installs when the user sets it to activate, and then create the admin panel) that shows just one text field, and the data the person enters is passed to the template page.

If I could have help finding a tutorial or simple advice on how to do this, it would be greatly appreciated.

share|improve this question

3 Answers 3

An example code for an options-page for a theme. Copy this code in the functions.php of the theme.

if ( !function_exists('localizing_theme_setup') ) {

    function localizing_theme_setup() {

        localizing_constants();

        // Make theme available for translation
        // Translations can be filed in the /languages/ directory
        load_theme_textdomain( FB_LT_TEXTDOMAIN, TEMPLATEPATH . '/languages' );

        // instance class
        $localizing_theme_options = new localizing_theme_options();
    }

}
add_action( 'after_setup_theme', 'localizing_theme_setup' );

function localizing_constants() {

    define( 'FB_LT_TEXTDOMAIN', 'localizing' );
}

if ( !class_exists( 'localizing_theme_options' ) ) {
    class localizing_theme_options {

        // constructor
        function localizing_theme_options() {

            add_action( 'admin_init', 
                array(&$this, 'localizing_theme_options_init') 
            ); 
            add_action( 'admin_menu', 
                array(&$this, 'localizing_theme_options_add_page') 
            );
        } 

        // Plugin options initialisieren 
        function localizing_theme_options_init() { 
            register_setting( 
                'localizing_theme_options', 
                'localizing_theme', 
                array(&$this, 'localizing_theme_options_validate') 
            ); 
        } 

        // Menu page Seite hinzufuegen 
        function localizing_theme_options_add_page() { 
            add_theme_page( 
                __( 'Set your Localizing Settings', FB_LT_TEXTDOMAIN ), 
                __( 'Localizing Settings', FB_LT_TEXTDOMAIN ), 
                'switch_themes', 
                'localizing_settings', 
                array( &$this, 'localizing_theme_options_do_page' ) 
            ); 
        } 

        // HTML, Simple Options Page 
        function localizing_theme_options_do_page() { 
            ?> 
            <div class="wrap"> 
                <h2><?php _e( 'Localizing Settings', FB_LT_TEXTDOMAIN ); ?></h2> 
                <form method="post" action="options.php"> 

                    <?php 
                    settings_fields('localizing_theme_options');
                    $options = get_option('localizing_theme');
                    $available_languages_files = get_available_languages();
                    if ( !empty( $available_languages_files ) ) {
                        // Translate the list into something that's easier to search
                        foreach ( $available_languages_files as $available_language ) {
                            $parts = explode( '_', $available_language );

                            if ( empty( $parts[0] ) )
                                continue;

                            $available_languages[ strtolower( $parts[0] ) ] = $available_language;

                            $santized = strtolower( $available_language );
                            $santized = str_replace( '_', '-', $santized );
                            $available_languages[$santized] = $available_language;
                            $all_available_languages[] = $available_language;
                        }
                    }
                    ?>
                    <table class="form-table">
                        <tr>
                            <th scope="row"> 
                                <?php _e( 'Available languages', FB_LT_TEXTDOMAIN ); ?> 
                            </th> 
                            <td>
                                <input type="text" disabled="disabled" name="" 
                                value="<?php echo implode( ', ', $all_available_languages ); ?>" />
                                <br />
                                <p><?php _e( 'This languages was found in the languages folder of this install.', FB_LT_TEXTDOMAIN ); ?></p>
                            </td>
                        </tr>

                        <tr valign="top"> 
                            <th scope="row"> 
                                <?php _e( 'A example checkbox', FB_LT_TEXTDOMAIN ); ?> 
                            </th> 
                            <td>
                                <input name="example_name[myoption1]" type="checkbox"  
                                value="1" <?php checked('1', 
                                $options['myoption1']); ?> />
                            </td> 
                        </tr> 
                        <tr valign="top"> 
                            <th scope="row">A example text</th> 
                            <td>
                                <input type="text" name="example_name[mytext]" 
                                value="<?php echo $options['mytext']; ?>" />
                            </td> 
                        </tr> 
                    </table> 

                    <p class="submit"> 
                        <input type="submit" class="button-primary" value="<?php _e( 'Save Changes', FB_LT_TEXTDOMAIN ); ?>" /> 
                    </p> 

                </form> 
            </div> 
            <?php    
        } 

        // Sanitize und validiere input 
        // (Akzeptiert ein array, return ein sanitized array) 
        function localizing_theme_options_validate($input) { 
            // erster Wert muss 0 oder 1 sein 
            $input['option1'] = ( $input['option1'] == 1 ? 1 : 0 ); 

            // Wert mit text 
            $input['sometext'] =  wp_filter_nohtml_kses($input['sometext']); 

            return $input; 
        } 

    } // end class
} // end if class exists

this is my options from this code:

alt text

I hope you understand the code, is also an dummy, works, but is not so fine in the php-codex for classes.

share|improve this answer
    
sweet, ty. so this is the same principle of a Wordpress plugin, but now I can have multiple settings for multiple areas of the site in one central location? my second question is, what makes 'themes options' different from a 'plugin'? –  HollerTrain Dec 1 '10 at 15:42
    
I like the example, but have a small question. Why hook onto after_theme_setup to define the constant? –  t31os Dec 1 '10 at 19:41
    
@HollerTrain: it give no different to plugin options, but it is importend for me, that its options of the theme. I make a great different from plugin- and theme-options. –  bueltge Dec 2 '10 at 14:58
    
qt31os: use this function only for include constants and i defined the const in this functions. My best goal is, i have only one class for a theme or plugin and this include in WP only at hook plugins_loaded or active theme. –  bueltge Dec 2 '10 at 14:59
    
Sorry i'm not quite following, so let me rephrase the question. Why not just define the constant at the start of the script? I don't doubt there's a good reason, i simply don't understand what that reason is yet... ;) –  t31os Dec 3 '10 at 11:23

Here is my way:

// get some info from the stylesheet (we need theme name & version)
$theme = wp_get_theme();

define('THE_THEME', strip_tags($theme->Name));    //  this is used as option name
define('THEME_VERSION', trim($theme->Version));

// default theme settings, the reason for a function is to avoid using a global array :)
function default_theme_options(){
  return array(
    'version' => '1.4.5',  // we use this to sync options between different theme versions
    'my_textfield' => 'A simple text field',
    'my_checkbox' => false,
    'my_select' => 2,
    'my_texarea' => 'Just a text area bla blah',
    'my_radio' => '3rd',
    'my_multicheck' => '1,3',
  );
}

// make the theme settings are properly set up
add_action('after_setup_theme', 'check_theme_options');
function check_theme_options(){

  // get current settings
  $options = get_option(THE_THEME);

  // get default settings
  $defaults = default_theme_options();

  // make sure we have the theme options stored in the db, if not store the default ones
  if(!$options) update_option(THE_THEME, $defaults);

  // new theme version? synchronize options then
  if(version_compare($options['version'], THEME_VERSION, '!=')):

     // check for new options
     foreach($defaults as $option => $value)
       if(!array_key_exists($option, $options)) $options[$option] = $defaults[$option];

     // remove deprecated options if any
     foreach($options as $option => $value)
       if(!array_key_exists($option, $defaults)) unset($options[$option]);

     // update
     update_option(THE_THEME, $options);
  endif;
}


// create the menu entry and link it to the form
add_action('admin_menu', 'add_options_menu');
function add_options_menu(){
  add_theme_page(
    __('Theme settings'),      // page title
    'My Theme Name',           // menu title
    'edit_theme_options',      // show the theme settings to all users who have this capability
    'my_theme_options_page',   // menu slug
    'the_theme_options_form'   // the fields, function below
  );
}


// trigger when the form is submitted
add_action('admin_post_save_my_options', 'save_my_options');
function save_my_options() {

  // check permissions and referer
  check_admin_referer('theme-settings');
  if(!current_user_can('edit_theme_options')) wp_die(__('You are not authorised to perform this operation.'));
  $options = get_option(THE_THEME); // get the current settings

  // change options
  foreach (default_theme_options() as $key => $value)
    if(isset($_POST[$key]))
      if(is_array($_POST[$key])) $options[$key] = strip_tags(implode(',', $_POST[$key]));
      else $options[$key] = current_user_can('unfiltered_html') ? stripslashes((string)$_POST[$key]) : stripslashes(wp_filter_post_kses((string)($_POST[$key])));

  // update settings with the post data
  update_option(THE_THEME, $options);

  // reload options page
  wp_redirect(admin_url('admin.php?page=my_theme_options_page&updated=true'));
}


// the theme settings form
function the_theme_options_form() {
  if(!current_user_can('edit_theme_options')) wp_die(__('You are not authorised to perform this operation.'));
  ?>
  <div class="wrap">

    <?php screen_icon('themes'); ?><h2><?php echo get_admin_page_title(); ?></h2>

    <form id="theme-settings-form" action="<?php echo admin_url('admin-post.php?action=save_my_options'); ?>" method="post" enctype="multipart/form-data">

     <?php if (isset($_GET['updated'])): // just updated? ?>
     <div class="updated fade below-h2">
       <p><?php _e('Settings saved.'); ?></p>
     </div>
     <?php endif; ?>


    <table class="form-table">
      <tr>
          <th scope="row">
            <label for="my_textfield"><?php _e("A simple textfield"); ?></label>
          </th>
          <td>
            <input id="my_textfield" size="20" name="my_textfield" type="text" value="<?php echo get_my_option('my_textfield'); ?>" />
          </td>
      </tr>

      <tr>
          <th scope="row">
            <label for="my_checkbox"><?php _e("Checkbox test"); ?></label>
          </th>
          <td>
            <input type="hidden" name="my_checkbox" value="0">
            <input id="my_checkbox" name="my_checkbox" type="checkbox" value="1" <?php checked('1', get_my_option('my_checkbox')) ?> />
          </td>
      </tr>

      <tr valign="top">
          <th scope="row">
            <label for="my_select"><?php _e("Multiple select field"); ?></label>
          </th>
          <td>
            <select name="my_select" id="my_select">
              <option value="1" <?php selected('1', get_my_option('my_select')) ?>><?php _e("option 1"); ?></option>
              <option value="2" <?php selected('2', get_my_option('my_select')) ?>><?php _e("option 2"); ?></option>
              <option value="3" <?php selected('3', get_my_option('my_select')) ?>><?php _e("option 3"); ?></option>
            </select>
          </td>
      </tr>

      <tr valign="top">
          <th scope="row">
            <label for="my_texarea"><?php _e("A textarea"); ?></label>
          </th>
          <td>
            <textarea rows="6" cols="40" name="my_textarea" id="my_textarea" class="code"><?php echo esc_html(get_my_option('my_textarea')); ?></textarea>
          </td>
      </tr>

      <tr valign="top">
          <th scope="row">
            <?php _e("A radio group:"); ?>
          </th>
          <td>
           <label for="my_radio_yes">
             <input name="my_radio" id="my_radio_yes" type="radio" value="yes" <?php checked('yes', get_my_option('my_radio')); ?> />
              <?php _e("Yes"); ?>
           </label>
           &nbsp;&nbsp;
           <label for="my_radio_no">
             <input name="my_radio" id="my_radio_no" type="radio" value="no" <?php checked('no', get_my_option('my_radio')); ?> />
              <?php _e("No"); ?>
           </label>
           &nbsp;&nbsp;
           <label for="my_radio_whatever">
             <input name="my_radio" id="my_radio_whatever" type="radio" value="whatever" <?php checked('whatever', get_my_option('my_radio')); ?> />
              <?php _e("Whatever"); ?>
           </label>
          </td>
      </tr>

      <tr valign="top">
          <th scope="row">
             <?php _e("Multiple checkbox option (eg. a list of categories):"); ?>
          </th>
          <td>
             <?php foreach(get_terms('category') as $term): // hidden input not needed here because we only send checked options ?>
             <label for="my_multicheck_<?php echo $term->term_id; ?>">
               <input id="my_multicheck_<?php echo $term->term_id; ?>" name="my_multicheck[]" type="checkbox" value="<?php echo $term->term_id; ?>" <?php checked(in_array($term->term_id, explode(',', get_my_option('my_multicheck')))); ?> />
               <?php echo $term->name; ?>
             </label>
             <br />
             <?php endforeach; ?>
          </td>
      </tr>

      <tr valign="top">
          <th scope="row">
             &nbsp;
          </th>
          <td>
             <input type="submit" class="button-secondary" name="submit" value="<?php _e("Save Changes"); ?>" />
          </td>
      </tr>

    </table>
    <?php wp_nonce_field('theme-settings'); ?>

    </form>

  </div>
  <?php
}


// apis -- eg. echo get_my_option('my_textfield');
function get_my_option($what){
  // check if it's a theme option or a normal wp option
  if($what && !array_key_exists((string)$what, default_theme_options())) return get_option($what);

  // it's a theme option
  $options = get_option(THE_THEME);
  return $options[$what];
}


function update_my_option($what, $value){
  // check if it's a theme option or a normal wp option
  if($what && !array_key_exists((string)$what, default_theme_options())) return update_option($what, $value);

  // it's a theme option
  $options = get_option(THE_THEME);
  $options[$what] = $value;
  return update_option(THE_THEME, $options);
}

This is just a short adaptation from the theme settings I implemented in my theme, which is much more complex than this.

Note that hidden input with 0 value - this is a trick to force the form to send $_POST['my_checkbox'] even if the field is unchecked.

alt text

share|improve this answer

Why do you want special admin panel for this? It seems like something that can simply be handled by page with custom template if necessary.

You can also load content of non-public page by code and use it where you need it.

See Pages in Codex.

share|improve this answer
    
If it's just some lines of text, with no formatting, creating a theme option page might be safer than including a page. You need a reference to the page, ID or slug, and both can be changed when the user accidentally deletes and re-creates the page. –  Jan Fabry Dec 1 '10 at 8:43
    
why would i want to make a page, then have to worry about making it non-indexable and having the admin have to go to a page to change text, when they could do it quickly from a plugin interface? your work around seems just that, an outdated work around –  HollerTrain Dec 1 '10 at 11:08
    
ah so theme options is just a plugin more or less? –  HollerTrain Dec 1 '10 at 11:11
    
@HollerTrain From your description, which is literally page that needs to be edited, I reasoned that actually using page might fit. :) –  Rarst Dec 1 '10 at 11:31
    
@Rarst, not every situation will require a page to be edited. Let's say I want to edit something in footer.php, header.php, sidebar.php, etc. –  HollerTrain Dec 1 '10 at 13:51

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.