My First Habari Plugin
Friday
Aug 22, 2008
As this is a WordPress blog I’m not in the business of evanglising Habari, however much it may interest me. I do however want to make it easy for everyone to try it. Most WordPress users will find that it doesn’t yet meet their needs but every WordPress developer should get something out of understanding a bit more about it. The point of this post is a very simple comparison of plugin code.
Habari is a more controlled environment than WordPress. Depending on your view this is either restrictive or liberating and there are arguments both ways. Notably the file structure is controlled.
With WordPress you don’t need a plugin folder, and if you have one it can be named whatever you want. With Habari you must have a folder and the plugin file must share that name, using the format [folder name].plugin.php. This is important as it is part of the system that finds and runs plugins.
The file paths to the plugin directory are also different. With WordPress they are stored in wp-content/plugins/ in Habari they are stored in user/plugins/
When you get to the class itself there are more requirements. Habari plugins must exist as a class.
With WordPress there is a choice to create a class and instantiate it, or to put the plugin in plain code. Habari not only requires the plugin to be a class but also requires that the class extends a pre-existing class; the plugin class.
Extending the plugin class, as shown below, means that the plugin already has some built in actions. I will explain the benefit of this a little further down.
The other imediate difference is how the plugin information is defined. Here is a comparison:
WordPress:
/* Plugin Name: My First Plugin Plugin URI: [insert the plugin url here] Description: This is a test plugin Author: Andrew Rickmann Version: 0.1 Author URI: http://www.wp-fun.co.uk */ class my_first_plugin { } $my_first_plugin = new my_first_plugin();
Habari:
class my_first_plugin extends Plugin { function info() { return array( 'name' => 'My First Plugin', 'version' => '0.1', 'url' => '[insert the plugin url here]', 'author' => 'Andrew Rickmann', 'authorurl' => 'http://www.wp-fun.co.uk', 'license' => 'Apache License 2.0', 'description' => 'This is a test plugin', ); } }
The differences so far are minor so I won’t dwell on them too much; however, you should note that in Habari you should not instantiate the class. Habari will take care of that at the appropriate time.
Hooks
Habari, just like WordPress, uses actions and filters, to trigger activities or alter data during execution. There is a significant difference in the way they are put into practice though.
In WordPress you need to create a constructor within the class so that the code will run when the class is instantiated. You also need to create a function, called anything that you want, and then add a line to the constructor to register that function againts the appropriate hook.
In the example below I have create a function that takes in a string and returns it with an extra paragraph added. I have then registered this function against the filter hook that runs when the content is output (the_content). The result is that every post will have the extra paragraph added to the end of it. The full plugin looks like this:
/* Plugin Name: My First Plugin Plugin URI: [insert the plugin url here] Description: This is a test plugin Author: Andrew Rickmann Version: 0.1 Author URI: http://www.wp-fun.co.uk */ class my_first_plugin { /** * PHP4 Compatible constructor to redirect to the PHP5 version. * */ function my_first_plugin(){ $this->__construct(); } function __construct(){ add_filter('the_content', array(&$this,'modify_post_content') ); } function modify_post_content($content){ return $content . '<p>An extra line added to the end of the content</p>'; } } $my_first_plugin = new my_first_plugin();
Note: in this example I have included a PHP4 constructor to point to the PHP5 constructor. You could just use the PHP4 constructor on its own but this is my preference.
Habari does things quite differently. You cannot create a constructor because the class you extended already uses it. That doesn’t matter too much though because you don’t need one.
With Habari the function name you use defines which hook it will be attached to. For example, naming the function ‘action_plugins_loaded’ tells us that the function will be triggered by an action and the name of the action is plugins_loaded. You can guess when this triggers right? Habari takes care of registering the function.
To achieve the same effect as the WordPress plugin above the plugin needs a filter function called ‘filter_post_content_out’.
class my_first_plugin extends Plugin { function info() { return array( 'name' => 'My First Plugin', 'version' => '0.1', 'url' => '[insert the plugin url here]', 'author' => 'Andrew Rickmann', 'authorurl' => 'http://www.wp-fun.co.uk', 'license' => 'Apache License 2.0', 'description' => 'This is a test plugin', ); } function filter_post_content_out($content){ return $content . '<p>An extra line added to the end of the content</p>'; } }
Priorities
The last difference I want to compare in this post is setting priorities. Both WordPress and Habari let you set the priority of the function by asigning it a priority number. Lower numbers take priority and therefore run sooner than functions with higher numbers. With WordPress the default is 10, for Habari the default is 8.
In WordPress you add the number to the registration function in the constructor. The following will register the function with a priority of 5:
add_filter('the_content', array(&$this,'modify_post_content') , 5 );
With Habari the priority for every function is set in another function, called ‘set_priorities’, by creating and returning an array. Adding the following function has exactly the same effect as including the number in the code for WordPress:
function set_priorities(){ return array( 'filter_post_content_out' => 10, ); }
Setting the priorities for more than one function would require an entry in the array for each function.
Habari is similar enough to WordPress for the plugin system to not be totally alien, but it is different and requires a little thought. It is also worth noting that the documentation is a long way from the WordPress codex so a bit more work is required to figure things out. I figured out this hook by looking at the template tags in the theme and guessing. It is logical though so I only had to guess once.
The key difference is that with WordPress you create your functions and then tell WordPress they exist and what they should be attached to, but with Habari it checks if specifically named functions exist and if so runs them. Each part of the plugin process has a function named assigned to it from setting the plugin information (the ‘info’ function), to setting priorities (the ‘set_priorities’ function). It is more restrictive, but quite logical and easy to pick up.
If you want a headstart (albeit a small one) on your first Habari plugin then you can enter some basic details and download a zip file with the correct file and folder name from Fun with Habari Plugins. The WordPress version of Fun with Plugins is available as ever.
The next post will focus on other aspects of Habari plugins such as creating admin pages and extra utilities that are available.







Comments
wesley
August 22nd, 2008 at 7:55 pm
Thanks, this is interesting. I’ve been thinking about cross platform plugin support.
Rick Cockrum (http://sagrising.cockrumpublishing.com)
August 22nd, 2008 at 8:40 pm
Nice comparison of some of the differences between writing WordPress and Habari plugins.
You are quite right about Habari’s documentation on writing plugins being a little thin right now, but there is an introduction to writing plugins on Habari’s wiki, as well as a list of Habari’s plugin hooks that makes the job of finding what to hook into to accomplish a task easier.
skippy (http://skippy.net/)
August 22nd, 2008 at 8:50 pm
Excellent introduction! We know that the documentation is weak right now. The API is really starting to settle down, so now that it’s less of a moving target documentation will get a greater priority.
And of course, you’re invited to help us generate that documentation! Your introduction here demonstrates a terrific understanding of what new plugin authors need to gain proficiency.
Matt Read (http://mattread.com/)
August 22nd, 2008 at 8:59 pm
“With Habari you must have a folder and the plugin file must share that name, using the format [folder name].plugin.php. This is important as it is part of the system that finds and runs plugins.”
Actaully that is not true. You can name the folder anything you want and the plugin file [anything].plugin.php. So you do not need to make them match.
And this is a great post! Thanks for doing it. And nice idea about the plugin wizard (can you make it use tabs instead of spaces
).
mikelietz (http://mikelietz.org/whine/)
August 22nd, 2008 at 9:08 pm
Thanks!
I’m looking forward to the plugin info for adding to the admin pages - thinking about creating a theme/plugin editor for the admin.
Andrew Rickmann (http://www.arickmann.co.uk)
August 22nd, 2008 at 10:22 pm
@Wesley, I have thought about it but I am not yet convinced. There could be a lot of work involved. I am going to look at converting one or two over though just for the practice.
@Rick, Thanks for linking to those pages. I have been using those and really should have linked to them in the article.
@Skippy, so far I haven’t done anything that isn’t documented but once I do I will certainly look to add to the documentation.
@Matt, thanks for the clarification. The documentation suggests that it is required although it doesn’t state it outright. Consider the tabs done as of the next update.
@Mike, I am looking forward to the admin pages bit a lot as I think there are UI helper classes, which means I won’t have to write any.
Ali B. (http://www.awhitebox.com)
August 23rd, 2008 at 4:21 am
“I am looking forward to the admin pages bit a lot as I think there are UI helper classes, which means I won’t have to write any”
Yup. FormUI takes care of the GUI and whatnot for the plugins configuration. In fact, even the admin pages (the publish page for example) use this class to construct and handle their GUI. It’s pretty cool.
Thanks for the enjoyable article and the detailed comparison. It sure sheds some light on how robust and easy the plugin system in Habari is. And great job on the plugin generation tool, that’s neat!
We sure could use your help to make the documentation better. I agree with skippy that you show a great deal of understanding on what potential plugin authors might need.
You can always stop by at #habari on freenode if you need anything.
Owen (http://asymptomatic.net)
August 24th, 2008 at 6:57 am
Nothing like writing about Habari and getting the PR squad showing up at your doorstep!
I have only a couple of minor thoughts to add to your excellent post.
Habari also allows you to manually register functions/methods as plugin sinks using the Plugins::register() method. This could be useful for when you want to do only one of multiple things based on a configuration option, and register only the correct function. Of course, you could just as easily do this with a switch() within the automatically registered function.
The filter_post_content_out() function is interesting in that it affects the output of $post->content_out. $post->content contains the actual post body content. Adding the “_out” suffix allows it to be modified by that specific filter.
Using this mechanism, you can create multiple suffixes that filter in different ways. You could, for example, output $post->content_summary and then code a plugin function filter_post_content_suffix() to alter just that output. If a filter for a suffix doesn’t exist, it just outputs the full content, so nothing breaks. This can be useful for outputting post archive listings specially for just the archive pages, or on any page.
This bit of functionality is probably not documented well because we’re (at least I am) expecting it to change slightly to improve filtering and output support, but that’s how and why things are named as they are.
I’m looking forward to part 2!
Andrew Rickmann (http://www.arickmann.co.uk)
August 24th, 2008 at 7:31 am
You’re not wrong Owen. I had heard about the community ethos surrounding Habari and, PR aside, I got a glimpse of that.
I must admit to jumping into the plugin writing before reading all the getting started stuff. Having read into it more I am starting to understand how the filters work. It makes it very easy to look at the template and filter what you want.
Is there a trac ticket somewhere that explains how it might change?
Owen (http://asymptomatic.net)
August 26th, 2008 at 12:57 pm
There aren’t any concrete plans for this right now, but the idea I came up with and we had discussed a bit can be found in this recent mailing list post. The change would basically be to go from echoing $post->content_out to echoing $post->content->out, and would extend to more of Habari’s intrinsic objects. But keep in mind that this isn’t finalized, so it might change before it’s implemented or not be implemented at all.