Adding Administration Pages

 

By using this template software, you automatically get an Options page under the Plugins menu. How this is set up is documented in Options Administration Page.

But often plugins need more than that rather simplistic options page. One option to to create another administration page. This will create another menu item somewhere in the administration menus. Sometimes that is what you want, but more often what is better is to have one menu item in the administration area for all your configuration information. You don’t want users to have to look around for different menu items for different things. It is also not a good idea to unnecessarily pollute the administration menus with lots of stuff.

A second option is to split existing options page into a page with tabs on it, wherein one tab is the stock options page you already get for free, and other tabs have whatever you want on them. I recommend this option for most cases.

 Option 1: Creating New Administration Pages & Menu Items

Creating new pages in the administration section is a matter of calling the right WP function to register a function that outputs page contend. These WP APIs are described in http://codex.wordpress.org/Administration_Menus.

To use in this plugin, you need to know two things. First, you can create a function in your XXX_Plugin class to output such page content. When a WP function parameter takes an input function for a callback, use the object-oriented form of that. In other words, pass “array(&$this, ‘yourFunctionName’)”.

Second, you need to know where to make those calls. The calls to these APIs must originate in the XXX_Plugin::addActionsAndFilters() function. Looking at the template you, you will see the following call:

1
2
3
public function addActionsAndFilters() {
    // Add options administration page
    add_action('admin_menu', array(&$this, 'addSettingsSubMenuPage'));

This hooks into the admin_menu action a call to $this->addSettingsSubMenuPage(). In that function a call is made to add_submenu_page to set up a menu item that will display the contents of $this->settingsPage():

1
2
3
4
5
6
7
8
9
10
protected function addSettingsSubMenuPageToPluginsMenu() {
    $this->requireExtraPluginFiles();
    $displayName = $this->getPluginDisplayName();
    add_submenu_page('plugins.php',
        $displayName,
        $displayName,
        'manage_options',
        $this->getSettingsSlug(),
        array(&$this, 'settingsPage'));
    }

Note: if you are creating other pages, you will need to create a “slug” for each that is a unique string to identify your page. In the above, we use the function “getSettingsSlug()”

1
2
3
protected function getSettingsSlug() {
    return get_class($this) . 'Settings';
}

Here we use “get_class($this)” as a prefix to another string, ‘Settings’ in this case. The point of this is to add a prefix so that your slug is unique and doesn’t collide with some other plugin’s slugs. I recommend as a best practice to use this “get_class($this) . ‘SomeString'” convention for admin page slugs.

Note also, that in the above add_submenu_page example, we pass in the ‘manage_options’ WP capability name. With this template code, you have the option to make this configurable by defining a “role option” where the plugin administrator can set what level of user (Admin, Editor, etc) gets the menu item. In that case you define a role option (see Handling Options and Enforcing Role Security) the replace ‘manage_options’ above with $this->roleToCapability($this->getRoleOption(‘TheOptionName’)

The best way to go about adding administration pages is to look at that example in the code and in Options Administration Page.

Option 2: Changing the Existing Options Page into a set of Tabs

The idea here is that your existing options page is changed into a page with JQuery UI Tabs. One tab is the current options page, the rest of the tabs include content you create. Here are the steps to create this.

First, you will need to get a copy of the JQuery UI CSS. To get it, you need to download JQuery UI and pull it out. Here is a version you can download: jquery-ui.css quickly. Place this file in your plugin’s css/ sub-directory.

In your XXX_Plugin.php file, find the addActionsAndFilters() function. Add the following code. Notice that we are checking the for the options page “slug”. This is a way of only adding these styles and scripts if the options/settings page is being viewed. We don’t want to add these on all pages.

1
2
3
4
5
6
7
8
9
10
11
12
13
public function addActionsAndFilters() {
        add_action('admin_enqueue_scripts', array(&$this, 'enqueueAdminPageStylesAndScripts'));
}
 
public function enqueueAdminPageStylesAndScripts() {
    // Needed for the Settings Page
    if (strpos($_SERVER['REQUEST_URI'], $this->getSettingsSlug()) !== false) {
        wp_enqueue_style('jquery-ui', plugins_url('/css/jquery-ui.css', __FILE__));
        wp_enqueue_script('jquery-ui-core');
        wp_enqueue_script('jquery-ui-tabs');
        // enqueue any othere scripts/styles you need to use
    }
}
Second, we override the settingsPage() function to output DIVs that will become Tabs and Javascript to initialize the tabs. Use the following template code (Reference: http://jqueryui.com/demos/tabs/)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public function settingsPage() {
	if (!current_user_can('manage_options')) {
		wp_die(__('You do not have sufficient permissions to access this page.', 'TEXT-DOMAIN'));
	}
	?>
<div>
	Header section above all the tabs
</div>
 
<script type="text/javascript">
	jQuery(function() {
		jQuery("#plugin_config_tabs").tabs();
	});
</script>
 
<div class="plugin_config">
	<div id="plugin_config_tabs">
		<ul>
			<li><a href="#plugin_config-1">Tab 1 Label</a></li>
			<li><a href="#plugin_config-2">Tab 2 Label</a></li>
			<li><a href="#plugin_config-3">Options</a></li>
		</ul>
		<div id="plugin_config-1">
			<?php $this->outputTab1Contents(); ?>
		</div>
		<div id="plugin_config-2">
			<?php $this->outputTab2Contents(); ?>
		</div>
		<div id="plugin_config-3">
			<?php parent::settingsPage(); ?>
		</div>
	</div>
</div>
<?php
}
Notice the call to the superclass parent::settingsPage() to place the stock options page in the content DIV of the third tab.
You would have to create functions like “outputTab1Contents()” and outputTab2Contents() as functions in your XXX_Plugin class. You could simply put the code in-line in their DIVs, but I find this makes the settingsPage() function really long and hard to read. Moving some of the content to other functions makes this more readable. You might also want to put content in another file then use PHP include() to add it.
In the tabs that you create, the best practice is to use AJAX calls to update configuration items from the page instead of doing a form post that does a page transition. See Creating AJAX Calls.

  13 Responses to “Adding Administration Pages”

  1. Hey michael,
    My name is Dean, Im trying to build a plugin. Ive been struggling a bit with your template,
    I couldn’t get any extra admin pages to work ,when I did, you could only go to one as the other told me I didnt have the correct permissions!
    So I decided to just go with your Jquery tabs. So I downloaded a fresh plugin template to start again and when I went to install it I got this error

    Warning: Invalid argument supplied for foreach() in /home/a2287993/public_html/wp-admin/includes/class-wp-upgrader.php on line 558

    I went through your upgrade documentaion but couldnt find anything pertaining to this,
    any ideas??
    Dean

  2. Adding a top-level menu page instead of a submenu page is an easy edit. Add a new function to your XXX_LifeCycle.php file directly underneath the other protected function addSettingsSubMenuPageToSettingsMenu() function:


    protected function addSettingsSubMenuPageToTopLevelMenu() {
    $this->requireExtraPluginFiles();
    $displayName = $this->getPluginDisplayName();
    add_menu_page($displayName,
    $displayName,
    'manage_options',
    $this->getSettingsSlug(),
    array(&$this, 'settingsPage'
    //, $icon_path
    //, $menu_position
    ));
    }

    Then head back up to line 123 of XXX_LifeCycle.php and adjust the addSettingsSubMenuPage() function:


    public function addSettingsSubMenuPage() {
    //$this->addSettingsSubMenuPageToPluginsMenu();
    //$this->addSettingsSubMenuPageToSettingsMenu();
    $this->addSettingsSubMenuPageToTopLevelMenu();
    }

  3. I’ve tried your example without modifying anything. This is the same copy of your example but I’ve got this “notice”:
    Notice: wp_enqueue_style was called incorrectly. Scripts and styles should not be registered or enqueued until the wp_enqueue_scripts, admin_enqueue_scripts, or login_enqueue_scripts hooks.

    Where I’ve made a error? My plugin doesn’t nothing so far. I’m just in begining of writing
    I’m on wordpress 3.8.1, no-plugin except this one. default theme 20-14.

    Thank a lot,
    Francois

    P.S.: Sorry for my poor english, i’m french!

  4. Francois – can you upload your code to http://pastebin.com/ and link it here? The “XXX_Plugin.php” file should be a good start.

  5. Just to add to Francois’ message above I am getting the same error.:

    Notice: wp_enqueue_style was called incorrectly. Scripts and styles should not be registered or enqueued until the wp_enqueue_scripts, admin_enqueue_scripts, or login_enqueue_scripts hooks.

    For your information I am using the Twenty Fourteen theme version 1. I am also using localhost, I wonder if that may play a part?

  6. Hi i just manage to do a Main Menu a Top level menu in admin. but I cant manage to understand slug..

    I cant make a submenu for my mainmenu.. it only work if i made it plugins.php submenu, instead of plugins.php y try to send the value of $this->getSettingsSlug() , wich supouse to be the main slug… it dosent work

    protected function addCategorySubMenuPageToSettingsMenu() {
    $this->requireExtraPluginFiles();
    $displayName = $this->getPluginDisplayName();
    add_submenu_page($this->getSettingsSlug(),
    $displayName,
    $displayName,
    ‘manage_options’,
    $this->getSettingsSlug(),
    array(&$this, ‘settingsPage’));
    }

    Of course i trigger the function before

    public function addSettingsSubMenuPage() {

    $this->addSettingsSubMenuPageToTopLevelMenu();
    $this->addCategorySubMenuPageToSettingsMenu();
    }

Leave a Reply to Dean Armstrong Cancel reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>