Archive for March, 2008

How to Give Your Plugin Settings a Submenu

While rebuilding the posts plugins for WordPress 2.5 I became frustrated by the excessive length of their settings pages and more than a little envious of other plugins which managed to split their settings into subpages accessible from a submenu.

I pored through more opaque code than is comfortable and eventually decided I should try and build an easy, reusable solution. Here’s the end result (download code):

class PluginSubpages {
  var $pages = array();
  var $parent_page = '';
  var $current_page = array();

  function PluginSubpages() {

  function __construct() {
    $this->parent_page = $_SERVER['QUERY_STRING'];
    $p1 = strpos($this->parent_page, 'page=');
    $p2 = strpos($this->parent_page, '&');
    if ($p2 === false) {
      $this->parent_page = substr($this->parent_page, $p1+5);
    } else {
      $this->parent_page = substr($this->parent_page, $p1+5, $p2-$p1-5);
  function add_subpage( $title, $slug, $view ) {
    $this->pages[] = array('title' => $title, 'slug' => $slug, 'view' => $view);
  function page_from_slug( $slug ) {
    if (!isset($slug)) {
      return $this->pages[0];
    foreach ($this->pages as $page) {
      if ($page['slug'] === $slug) {
        return $page;
    die('non-existent slug');
  function display() {
    echo "\n<ul id=\"submenu\" style=\"display: block\">\n";
    $base = $_SERVER['PHP_SELF'] . '?page=' . $this->parent_page . '&subpage=';
    $this->current_page = $this->page_from_slug($_GET['subpage']);
    foreach($this->pages as $page) {	
      if($page === $this->current_page) {
        echo "<li><a href=\"$base{$page['slug']}\" class=\"current\">{$page['title']}</a></li>\n";
      } else {
        echo "<li><a href=\"$base{$page['slug']}\">{$page['title']}</a></li>\n";
    echo "</ul>\n";

There’s one nasty trick in there which I’ll come to but first … how to use it.

You’ll already have the code to register your admin settings page:

function plugin_option_menu() {
  add_options_page('Plugin Options', 'Plugin', 8,'plugin-file', 'plugin_options_page');

add_action('admin_menu', 'plugin_option_menu', 1);

function plugin_options_page(){

Instead of filling ‘plugin_options_page’ with all your settings code you use PluginSubpages to delegate the hard work.

function plugin_options_page(){
  echo '<div class="wrap"><h2>Plugin</h2></div>';
  $m = new PluginSubpages();
  // register the subpages
  $m->add_subpage('General', 'general', 'plugin_general_options_subpage');
  $m->add_subpage('Other', 'other', 'plugin_other_options_subpage');
  // show them!

Each of the subpage functions behaves independently, e.g.,

function plugin_general_options_subpage(){
  $options = get_option('plugin-general');
  if (isset($_POST['update_options'])) {
    <div class="wrap">
    <h2>General Settings</h2>
    <form method="post" action="">
    <div class="submit">
      <input type="submit" name="update_options" value="Save General Settings" />

Now about that ‘nasty trick’… PluginSubpages->display() spits out the HTML for the menu as an unordered list. How should the menu list be styled? I could include specific inline CSS styles for the menu but I thought it would be better if the subpage menu looked like the preexisting admin menu.

This is the evil bit. I found that giving the subpage menu the id of ‘submenu’, the id of the admin menu I could steal all its styles and the subpage menu would fit into its surrounding seamlessly. The only catch is that CSS ids cannot be duplicated — each must be unique. In practice, though, every browser I tried coped without a squeak. Just don’t expect your admin pages to validate if you use this technique.

1 comment March 27th, 2008

Novice Notes on the Official WordPress Plugin Directory

As I’ve said I’ve been wrestling with the plugin directory and, as I suspected, the trouble is down to my lack of smarts. Two things to be aware of if you are wanting to host your plugins at the official site:

  • When they say that you should name your tags/releases using only numbers and periods they mean it. I was using 2.5 bxx not thinking a space would cause an issue but of course it did when the automatic updater kept giving up on the zip files it downloaded. From now on, 2.5bxx until I can drop the beta designation.
  • That stray space thing managed to keep hidden for a few days because I couldn’t even get that far. I’ve been grumbling that my installation instructions were not showing correctly and trying, in vain, to get help… well, a little while ago as I was poring over the readme.txt for the umpteenth time I was struck by lightning (OK I’m exaggerating) and thought to check the encoding of the file. I don’t know how but the readme.txt files I’d uploaded were encoded as utf-8. The Readme Validator hadn’t caught the problem but it was enough to make the directory ignore the files.

So no spaces in release tags and just plain old ANSI in the readme.

3 comments March 25th, 2008


I saw the film ‘Once‘ tonight. Very moving. Here’s a clip with the Oscar-winning song.

Glen Hansard – Falling Slowly

I don’t know you
But I want you
All the more for that
Words fall through me
And always fool me
And I can’t react
And games that never amount
To more than they’re meant
Will play themselves out

Take this sinking boat and point it home
We’ve still got time
Raise your hopeful voice you have a choice
You’ve made it now

Falling slowly, eyes that know me
And I can’t go back
Moods that take me and erase me
And I’m painted black
You have suffered enough
And warred with yourself
It’s time that you won

Take this sinking boat and point it home
We’ve still got time
Raise your hopeful voice you had a choice
You’ve made it now

Take this sinking boat and point it home
We’ve still got time
Raise your hopeful voice you had a choice
You’ve made it now
Falling slowly sing your melody
I’ll sing along

March 24th, 2008

Still Fighting the Official Plugins Directory…

I haven’t got a response from the official WordPress plugin directory to work out why the proper instructions are not displaying and meanwhile I am getting a lot of folks wondering what on earth is going on and why the post plugins are no longer working.

Here are some emergency directions for the interim…

First follow these links to download the latest versions of Similar Posts, Recent Posts, Random Posts, or Recent Comments. You will also need a new copy of the Post Plugin Library which is now configured as a plugin.

Load stuff up to the plugins directory (you will notice that some of the folder names have been changed to accommodate the requirements of the WordPress folks) and activate as normal. The library should be automatically activated when any of the other plugins is activated.

Hopefully after all this hullabaloo future updating will happen smoothly and automatically (wishful thinking!).

Please get in touch if you are still having problems. The report-a-bug option under the settings menu is a helpful way of doing so … or just leave a comment.

March 24th, 2008

WordPress 2.5 and Automatic Plugin Updates

Update: Check out this post for some extra instructions.

Well I’m wrestling with the new ability of WordPress 2.5 to notify when a fresh version of a plugin is available on the official directory. Up until now I haven’t used the directory but today I tried to get my post plugins up and running over there so that the automated update functionality could be used.

It is working … just. Please bear with me if you have problems.

  • I have had to make the Post-Plugin Library into a plugin in its own right.
  • The folders the plugins go into has changed in some cases: similar-posts remains the same but recent-posts has become recent-posts-plugin and so on. This is because I had to find a unique name for each plugin at the directory.
  • After the first automatic update you might need to re-activate the plugin.
  • … and who knows what else …

And, by the way, Happy Easter!

2 comments March 23rd, 2008

Site Outage…

Apologies for the mess the site has been in for the last 18 hours. A mangled .htaccess file (who knows how?) made the site inaccessible and then to compound problems I was locked out of ftp so I couldn’t put things right.

March 20th, 2008

WordPress Plugins Updated: Similar Posts, Recent Posts, Random Posts, and Recent Comments

Finally! I have posted the updated (2.5) versions of my post plugins and they are full of enhancements and even the odd fix… Check them out from the plugins page but please take note:

  • They are still beta releases and, given the number of modifications I have made, I am sure I will have a few issues to correct. If you have any problems try reporting them through the in-built bug-reporting tool. Other comments are, of course, welcome on each plugin’s own page.
  • The plugin code has been substantially refactored to minimise duplication and, as a result, the four plugins now share a library. Please take care to read the upgrade directions rather than blundering ahead (the way I usually do myself!).
  • If you have been using the Plugin Output Cache you will need to update to the latest version.

So … new features, new options, and new output tags … and a few bug fixes as well.

New Features

  • Ready for WordPress 2.5 with a new matching admin interface.
  • Random Posts is about twice as fast as before.
  • Similar Posts has had a lot of work. It now uses its own table instead of using custom fields. Tag-based similarity has been added and the balance between content, title, and tags is fully adjustable. You can now add similar posts to your feeds without an extra plugin (Similar Posts Feed has been discontinued). I have supplied stop lists for English, French, German, Spanish, and Italian (with more to come) — and stemming algorithms to match. I also have plans for various refinements and extensions of the similarity algorithm, including some support for Japanese, Chinese and Korean.
  • When used as widgets the plugins have a new option to only show under certain circumstances by using WordPress Conditional Tags like ‘is_single(), e.g.,
    is_single() && is_paged()
  • The plugin display can now be injected on a post-by-post basis by using embedded tags, e.g., <!--SimilarPosts-->.
  • You can now report bugs from the plugin settings pages and automatically send along basic information to aid debugging, like what version of PHP, MySQL etc. are in use.
  • There is now an option to completely remove the plugins and all their settings without having to fiddle with phpMyAdmin.
  • Increased security with proper nonce-protection and better screening of settings.
  • A much better memory footprint, especially when more than one of the plugins is installed.
  • The plugins are set up for internationalisation … but as of yet not translated.
  • It is now much easier to extend the plugins with your own output template tags.
  • The plugins are much more careful of how they handle multi-byte character sets.

New Options (or settings as WP 2.5 calls them)

  • It is now possible to have no output at all if the plugin finds no matching posts.
  • The fallback text when no posts are listed can now contain embedded output tags.
  • You can now choose to only include posts that are more than, or less than, a certain number of days, months, or years old.
  • A content filter can be turned on to expand tags embedded in posts so that plugin output can be injected on a post-by-post basis.
  • The Recent Comments’ option to exclude certain comment authors (which never worked properly!) has been replaced with the option to omit comments left by the post’s author.
  • It is now possible to include ‘&’ in parameters passed by query-string.

New Output Tags

  • {totalposts} and {totalpages}
  • {postid}
  • {postviews}
  • alternate {commentlink2}
  • alternate {excerpt} preserving HTML etc.
  • a variety of ways to crop {title} etc.
  • {image}
  • {categoryid}
  • {commenterip}
  • and {php} which lets you insert your own code!

Bug Fixes

  • Better validation of settings.
  • Fixed an ordering bug in Recent Comments when grouped by post.
  • Fixed a problem on some systems with ‘include’ of relative paths.
  • No longer troubled by the awkward bug in MySQL version 4.1.21.

That should be plenty to play with!

24 comments March 17th, 2008


March 2008
« Jan   Apr »

Posts by Month