In my last post I asked the question: should plugins should be written to be as extensible, if not more, as the core WordPress code; i.e. should we expect a plugin to be written with the expectation that someone will write a plugin to further modify it? I promised an example so here it is.
I have written a very basic page menu plugin using the principles I outlined yesterday. I will explain each section and include the code here but the plugin can be downloaded at the bottom of the post.
The plugin uses the template redirect hook to trigger just before the blog’s theme is loaded. At this point it sets default values for the home page URL, the title of the home page in the menu, and the arguments that will be used to fetch the pages (what to sort by and in what order).
At this point the first set of filters will run:
After those filters the pages are fetched using the WordPress get_pages function and the array of pages that is returned is passed to the callback function. We now have the final list of pages that the plugin will display.
Following that the plugin checks the current theme folder for a template file called ‘fun_menu_template.php’. If it finds it, it will use the file path to that, otherwise it will use the default template. Whichever path is chosen this is then passed through a filter and the result is stored.
Here is the code:
[php]
function menu_init(){
$home_page_url = get_option('home');
$home_page_default_text = 'Home';
//set the default arguments
$default_arguments = array(
'sort_order' => "ASC",
'sort_column' => "menu_order"
);
//apply filters
$this->home_page_link = apply_filters('fun_menu_home',array($home_page_default_text,$home_page_url));
$page_array_arguments = apply_filters('fun_menu_page_arguments',$default_arguments);
$pages_filter_callback = apply_filters('fun_menu_pages_filter',array($this,'process_pages'));
//start the processing
$retrieved_pages = get_pages($page_array_arguments);
$this->filtered_pages = array_filter( $retrieved_pages , $pages_filter_callback );
//check the themes directory for an alternative template
if (file_exists( TEMPLATEPATH . '/fun_menu_template.php') ){
$template_url = TEMPLATEPATH . '/fun_menu_template.php';
} else {
$template_url = dirname(__FILE__) . '/fun_menu_template.php';
}
//use either the supplied, alternate, or result of filter
$this->template_url = apply_filters( 'fun_menu_template' , $template_url );
}
There are only two more functions in the plugin:
The pages filter. This filter checks every page to see if it should be included. In this plugin it simple returns true to indicate that the page should be included.
[php]
function process_pages($page){
return true;
}
The last function is called from within the users theme although it could just as easily be called from a widget. This gives the variables more useful names and the includes the template.
[php]
function display_menu(){
//setup the variables
$home_permalink = $this->home_page_link[1];
$home_title = $this->home_page_link[0];
$fun_menu_pages = $this->filtered_pages;
//include the template
include($this->template_url);
}
The template itself is just a very simple bulleted list. In the real world this plugin would certainly be including some CSS and maybe even some javascript as well to make it into a proper menu:
[html]
The end result when this plugin is activated and a call to the display_menu function added to the theme is a small bulleted list of links:

The child plugin is very simple. In the constructor three hooks are used to filter the appropriate information:
[php]
add_filter('fun_menu_home',array($this,'change_home_page_title'));
add_filter('fun_menu_pages_filter',array($this,'change_pages_filter_callback'));
add_filter('fun_menu_template',array($this,'change_template_path'));
These hooks call three functions. Number one changes the title shown for the home page:
[php]
function change_home_page_title($home_page){
//update the array
$home_page[0] = 'Go Home';
//send it back
return $home_page;
}
The second function changes the page filter callback to point to a filter function in this plugin. This filter doesn’t just pass back true, it checks each page for a custom field that tells the system to exclude the page from the menu:
[php]
function change_pages_filter_callback($callback){
//no need to edit just send back a different one
return array($this,'process_pages');
}
function process_pages($page){
//check against a custom field to see if it should be excluded
if ( get_post_meta($page->ID, 'menu', $single = true) == 'exclude' ) { return false;}
return true;
}
The last function changes the template path to point to a template in this plugin’s folder.
[php]
function change_template_path($path){
return dirname(__FILE__) . '/menu_template.php';
}
The results are clear to see:
![]()
The revised template is an ordered list instead of an unordered list, the home page no reads ‘Ho Home’ instead of simple ‘Home’ and one the pages has been filtered out.
I hope you can see from this where the potential lies. With so many options it would be easy for a plugin, or a theme, to produce something quite different without replicating the serious bits of the code. It also feels like a very neat solution. Of course there are a lot of plugins that wouldn’t suit this approach but if you can add filters, callbacks and templates you should consider it at least.
Note: I am becoming quite inspired by Habari at the moment. Habari uses the template system in themes but in a more integrated way. If you want to see it in action, in the next few days I will be writing about plugin templates at Fun with Habari.
Download both the sample plugins in one zip file.
(__)
`
Where Is That Settings Page? | Wordpress Blog NL
[...] the weekend, I happened to come across a post written by Andrew Rickmann which showcased an idea to create a configure link next next to the usual Activate/Deactivate Edit [...]
(__)
`
links for 2008-10-08 « Tom Altman’s Wedia Conversation
[...] Configurable Plugins | WP FUN In my last post I asked the question: should plugins should be written to be as extensible, if not more, as the core WordPress code; i.e. should we expect a plugin to be written with the expectation that someone will write a plugin to further modify it? I promised an example so here it is. (tags: wordpress plugins programming) [...]