Tell me more ×
WordPress Answers is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I was getting tired of righting the code for adding plugin options in my plugins so I wanted to give writing a class that i could reuse a try.

my class does a bunch of the basics, registering settings, adding the menu page. i'm not at the point of creating the options themselves, b/c i'm still stuck on the fact that only 1 plugin ever seems to use the class at a time. the whole point is so that it can be re-used repeatedly, so i am obviously missing some important concept in OOP.

at its most base, i was expecting that i could say new KIA_Plugin_Options($args) in both plugins one and two (with different $args) and that each would crank out the options pages for their respective plugins. what is happening though is that 1 will work fine and the other will not get its menu page.

warning: a lot of code

<?php

class KIA_Plugin_Options {

  private $page_title;
  private $menu_title;
  private $capability;
  private $menu_slug;
  private $setting_name;
  private $option_name;

  function KIA_Plugin_Options( $args ){

    //convert $args to array 
    if(!is_array($args)) $args['page_title'] = $args; 

    if(!isset($args['page_title'])) die (__('Plugin Options needs at least the plugin\'s page title parameter.','kia_plugin_options'));

    // Define the class variables
    $this->page_title = $args['page_title']; 
    $this->menu_title = isset($args['menu_title']) ? $args['menu_title'] : $this->page_title;
    $this->capability = isset($args['capability']) ? $args['capability'] : 'manage_options';
    $this->menu_slug = isset($args['menu_slug']) ? $args['menu_slug'] : sanitize_title_with_dashes($this->menu_title);
    $this->setting_name = isset($args['setting_name']) ? $args['setting_name'] : $this->menu_slug;
    $this->option_name = isset($args['option_name']) ? $args['option_name'] : $this->menu_slug;

    // Set-up Action and Filter Hooks
    register_activation_hook(__FILE__, array(&$this,'add_defaults_options'));
    register_uninstall_hook(__FILE__, array(&$this,'delete_plugin_options'));

    //add settings page
    add_action('admin_init', array(&$this,'register_settings' ));
    add_action('admin_menu', array(&$this,'add_options_page'));

    //add settings link to plugins page
    add_filter( 'plugin_action_links', array(&$this,'add_action_links'), 10, 2 );
  }


  // ------------------------------------------------------------------------------
  // CALLBACK FUNCTION FOR: register_activation_hook(__FILE__, 'add_defaults_options')
  // ------------------------------------------------------------------------------

  // Define default option settings
  function add_defaults_options() {
    if(get_option('kia_tell_a_friend_options')) return false;

    $defaults = array( 
              "emailsubject" => __( 'I saw this and thought of you!', 'kia_tell_a_friend'),
              "emailmsg" => __( 'I just saw this!', 'kia_tell_a_friend'),
              "twittermsg" => __( 'Check this out!', 'kia_tell_a_friend')
    );
    update_option('kia_tell_a_friend_options', $defaults);
  }


  // --------------------------------------------------------------------------------------
  // CALLBACK FUNCTION FOR: register_uninstall_hook(__FILE__, 'delete_plugin_options')
  // --------------------------------------------------------------------------------------

  // Delete options table entries ONLY when plugin deactivated AND deleted
  function delete_plugin_options() {
    $options = get_option('kia_tell_a_friend_options', true);
    if(isset($options['delete'])) delete_option('kia_tell_a_friend_options');
  }


  // ------------------------------------------------------------------------------
  // CALLBACK FUNCTION FOR: add_action('admin_init', array(&$this,'register_settings' ));
  // ------------------------------------------------------------------------------

  // Init plugin options to white list our options
  function register_settings(){ 
    register_setting( $this->setting_name, $this->option_name, array(&$this,'validate_options') );
  }

  // ------------------------------------------------------------------------------
  // CALLBACK FUNCTION FOR: add_action('admin_menu', array(&$this,'add_options_page'));
  // ------------------------------------------------------------------------------

  // Add menu page
  function add_options_page() {
     $page = add_options_page( $this->page_title , $this->menu_title, $this->capability, $this->menu_slug, array(&$this,'render_form'));

    /* Using registered $page handle to hook stylesheet loading */
    add_action( 'admin_print_styles-' . $page, array(&$this,'admin_style' ));
  }

  // ------------------------------------------------------------------------------
  // CALLBACK FUNCTION FOR: add_action( 'admin_print_styles-' . $page, array(&$this,'admin_styles' ));
  // ------------------------------------------------------------------------------

  // Add menu page styles
  function admin_style() {
    wp_enqueue_style('plugin-options',plugins_url('css/options-framework.css', __FILE__));
  }


  // ------------------------------------------------------------------------------
  // CALLBACK FUNCTION SPECIFIED IN: add_options_page()
  // ------------------------------------------------------------------------------

  // Render the Plugin options form
  function render_form() {
    echo "Bacon!!!";
  }

  // Sanitize and validate input. Accepts an array, return a sanitized array.
  function validate_options($input) {

    $clean = array();

     // strip html from textboxes
    $clean['pubid'] =  wp_filter_nohtml_kses($input['pubid']); // Sanitize text input (strip html tags, and escape characters)
    $clean['delete'] =  isset( $input['delete'] ) ? 'true' : 'false' ;  //checkbox

    $clean['emailsubject'] =  wp_filter_nohtml_kses($input['emailsubject']); // Sanitize text input (strip html tags, and escape characters)
    $clean['emailmsg'] =  wp_filter_post_kses($input['emailmsg']); // Sanitize textbox input (allow tags that area allowed in posts)

    $clean['twittermsg'] =  wp_filter_nohtml_kses($input['twittermsg']); // Sanitize text input (strip html tags, and escape characters)

    return $clean;
  }

  // Display a Settings link on the main Plugins page
  function add_action_links( $links, $file ) {

    if ( $file == plugin_basename( __FILE__ ) ) {
      $posk_links = '<a href="'.admin_url('options-general.php?page=tell-a-friend').'">'.__('Settings', 'kia_tell_a_friend').'</a>';
      // make the 'Settings' link appear first
      array_unshift( $links, $posk_links );
    }

    return $links;
  }


}

so then i've put that inside my first test plugin folder and the test plugin looks like this:

<?php

if (!class_exists("KIA_Test_Plugin_One")) :

class KIA_Test_Plugin_One {

  var $options;

  function KIA_Test_Plugin_One(){

    // Include required files
    $this->includes();

    // Actions
    add_action( 'init', array( &$this, 'init' ), 0 );

  }


  function includes(){
    if ( ! class_exists( 'KIA_Plugin_Options' ) ) include_once( 'plugin-options/plugin-options.class.php' );
  }

  function init(){

    $args = array ( 'page_title' => 'apple options page',
                        'menu_title' => 'apple options', 
                        'capability' => 'manage_options',
                        'menu_slug' => 'apple_options',
                        'setting_name' => 'apple_settings',
                        'option_name' => 'apple_db_options' );

    $this->options = new KIA_Plugin_Options( $args );
  }

} // end class
endif; // class_exists check


/**
* Launch the whole plugin
*/
global $KIA_Test_Plugin_One;
$KIA_Test_Plugin_One = new KIA_Test_Plugin_One();


?>

and a second dummy plugin that i want to use the same plugin options class:

<?php

if (!class_exists("KIA_Test_Plugin_Two")) :

class KIA_Test_Plugin_Two {

  var $options;

  function KIA_Test_Plugin_Two(){

    // Include required files
    $this->includes();

    // Actions
    add_action( 'init', array( &$this, 'init' ), 0 );

  }


  function includes(){
    if ( ! class_exists( 'KIA_Plugin_Options' ) ) include_once( 'plugin-options/plugin-options.class.php' );
  }

  function init(){

    $args = array ( 'page_title' => 'bacon options page',
                        'menu_title' => 'bacon options', 
                        'capability' => 'manage_options',
                        'menu_slug' => 'bacon_options',
                        'setting_name' => 'bacon_settings',
                        'option_name' => 'bacon_db_options' );

    $this->options = new KIA_Plugin_Options( $args );
  }

} // end class
endif; // class_exists check


/**
* Launch the whole plugin
*/
global $KIA_Test_Plugin_Two;
$KIA_Test_Plugin_Two = new KIA_Test_Plugin_Two();


?>
share|improve this question
Any progress or is this orphaned? :) – toscho Oct 3 '12 at 23:26
Lol... totally orphaned right now. But I did come across @bainternet's Admin Page Class which might solve my problems if I ever get back to that. github.com/bainternet/Admin-Page-Class – helgatheviking Oct 4 '12 at 0:21
Okay, I found it during my clean up tour through our unanswered questions. What do we do now? – toscho Oct 4 '12 at 0:23
What do you usually do with dead questions? I don't really remember how far along I got before abandoning this project, and don't know if/when I'll ever return to it. If you want, we can list the above Admin Page Class as the answer, since it appears to do exactly what I was attempting. – helgatheviking Oct 4 '12 at 0:41
I would close it as too localized because no one else seems to have that problem. An answer should solve and explain exactly the problem from the question, and I don't see that in code written without any relation to your question. – toscho Oct 4 '12 at 0:46
show 1 more comment

closed as too localized by toscho Oct 4 '12 at 2:29

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, see the FAQ.