Jump to content
bfarber
 Share


IP.Board 3 Plugins and Hooks

Many of you have been waiting for this blog post, and I can assure you we've been equally as anxious to get it out to you, but we wanted to ensure the bulk of the system was in place first before releasing anything we had to pull back on.

General Overview

First, as used in this blog entry, the definition of a "hook" is a point in the code execution where a modification author can tell IP.Board to execute his or her code, and then return to the primary code execution. A "plugin" is a collection of hooks (any given modification may need to "hook" into 2 or 3 files, for instance, but remain one modification - which we will call a plugin).

IP.Board 3, as promised, will introduce a new hooks and plugin system for modification developers to make use of. The system is relatively extensive without a lot of "hook points" manually inserted into the source files which ultimately requires a lot of maintenance and never-ending "can you add a hook point at xyz location" requests. We wanted to provide something out of the box that would scale, that would be easy to manage and maintain, and that would accomodate most modification needs without requiring modifications to the core source code. At the same time, during development of the new hooks system we determined that we did not want to simply shift the modification responsibilities to the skin system either. While it is arguably much easier to modify the skin system than a source file, shifting responsibilities entirely would not solve the issue we are working to tackle. The ultimate goal, of course, is to allow you to enhance your board without having to modify source files to do so. This makes upgrading easier, as you don't have to reapply your mods, makes support easier, as we can easily disable your hooks without having to sift through files looking for changes, and makes adding plugins easier, as you don't have to spend 30 minutes applying code changes from an instruction file to do so.

How the hooks and plugins work for end users

There is a hooks management page in the admin control panel where all of your installed hooks are listed. You can enable and disable hooks from this page, and reposition what order they are executed in (while this generally shouldn't matter, the capability exists in case a plugin needs to hook into another plugin, for instance). You can also view detailed information about the plugin that the author has provided (such as the author name, email address and website, and all files associated with the plugin), and check your system against the minimum/maximum PHP and IPB versions the hook supports. The hooks system supports an update check URL that the author can use to notifiy you if a hook is out of date.

To install a hook, you will simply upload an XML file from the ACP interface - that's it! The hooks system, similar to the popular Universal Mod Installer for earlier versions of IP.Board, supports running necessary database queries, importing settings, language bits, skin templates, modules, tasks, help files and admin CP help files. The hook installation routine even supports a custom script callback system in case the installation routine needs to do something we don't support out of the box. Similarly, when you uninstall a hook, all of the changes are automatically reverted, and the custom script can perform additional cleanup if needed.

It's as simple as that. Import an XML file and view changes on your site immediately.

How the hooks and plugins work at the system level

When hooks are imported in the ACP, they are cached to .php files in a /hooks folder. Only hooks that are registered in the admin CP are executed, to avoid wasting resources hunting down hooks that are not being used presently.

There are three types of hooks in IP.Board 3:

  • Action overloaders
  • Skin overloaders
  • Template hooks

Action overloaders allow you to extend an action file, allowing you to do nearly anything you can imagine. An example of this might be to extend the board index source file, add your output to $this->output, and then call parent::doExecute() to allow IP.Board to finish loading the board index with your output prepended. Or, you may want to extend a source file so that when a form is submitted, you can store additional data in the database. Most properties and methods in IP.Board are set as protected, giving you full access to them from your extended class.

Skin overloaders work similar to action overloaders, except that you are extending a skin file. A good example of why you might want to do this might be to entirely change a template's contents if the user meets a certain criteria, or if you want to prepend or append HTML to a template without requiring the user to manually edit each of their skins.

Finally, template hooks provide an extremely powerful way to manipulate the HTML output, which is what most modifications are designed to do. Before and after each foreach loop, if statement, and else statement, HTML comments are inserted into the HTML output (automatically by our skin system, so as to avoid annoying our beloved skinners) with a very specific syntax. When you register your template hook in the ACP, you specify where in the skin you want to hook into. During display, if your hook is enabled, it is executed and the HTML comment is replaced with the output returned from your hook.

Overall, this provides methods for injecting your code into source code functionality and into the final output engine, covering most cases for modification authors.

We will be providing some examples with the releases of IP.Gallery, IP.Blog and IP.Downloads. I don't want to give away any details on these just yet, but some of the things users have been begging us to do that we've always said we can't as it would require modifications to IP.Board will now be possible, allowing for a much tighter integration between our applications than has ever been possible.

How the hooks and plugins work for developers

In the admin CP when you create a new plugin, you fill in some basic details such as author, plugin name, and website. You create the hook files and then on the form when creating a new plugin you configure which files are a part of the plugin (there is no limit to the number of files you can add to a single plugin). You would then develop your work as normal.

When you go to export the plugin, you can interactively configure settings, setting groups, language bits, skin templates, modules, help files, ACP help files, custom installer/uninstaller scripts, tasks, and database changes that you want to export with the hook. If you have used the universal mod installer in the past, this system is similar, with the main difference being that you interactively configure these details in the admin CP instead of through an XML file.

When you finally export the hook, your source code is collected (as well as the source code for the install/uninstall script) and included within the XML file. The hook import routine takes care of caching the code and importing all of the data you configured to export with the plugin.

Closing

Before starting on the system we wrote down 5 different popular modifications and requests that we've seen for a while to verify that once finished we would be able to accomplish each of these modifications without actually modifying the source code in IP.Board 3 - and we've passed this baseline test. We intend to release more details on the system's specifics for modification developers closer to the release of IP.Board 3 to help them learn the new system, as well as examples of how to accomplish various things without modifying the source code, through our official resource site.
 Share

Comments

Recommended Comments

OK, so I now know for sure that I don't need to make a version of the UMI for IP.Board 3.0 now. I had some plans for it, but nothing earth-shattering, so it's cool that I don't have that to worry about getting it upgraded now. I, of course, have some questions, though. :)

This new hooks system will run 'database queries', you said. Are these going to be just full queries, using the query() function of the database driver (assuming such a generic function still exists), or are these queries going to be broken down the way the UMI does it, into tables, alters, inserts, and updates? If it's the latter, it will also be able to generate the 'reverse' queries to uninstall those changes? And will this support MSSQL and PostgreSQL?

I'd like to hear some more information about the system you will have to let mod authors notify users if the mod is out of date, as coding that to work reliably on all kinds of server setups was by far the biggest headache of the UMI, and the problems continue to this day.

Will there be some specific folder creater somewhere in IPB for mod source files to go? Let me clarify that. For many of my mods, I have to code a small file which does some querying or something to generate a small block of output. I typically will dump said file into the /sources/lib directory, but it then sort of sticks out like a sore thumb as there are other IP.Board source files there. Other modders put their source files in their own custom folders (Dean, for example, has his /sources/d22mods directory). What I'd like to see is a specific folder, maybe a sobfolder of /hooks, that is just a place to store source files for modifications that don't have any other logical storage location.

Finally, you're not planning on releasing any of those 5 mods you mentioned at the end, are you? Because I'd hate for one or more of them to be my mods that I now no longer need to update. :lol:

Link to comment
Share on other sites

Great questions Michael. I do want to prefix my reply with the blanket statement that this will be a 1.0 release of such a new system, and no matter what we do there will be huge room for improvement. We're hoping that feedback during the beta processes from our modification community such as yourself will help us to refine the system to be as good as it possibly can be. With that said...

[quote name='Μichael' date='Aug 28 2008, 05:47 PM']OK, so I now know for sure that I don't need to make a version of the UMI for IP.Board 3.0 now. I had some plans for it, but nothing earth-shattering, so it's cool that I don't have that to worry about getting it upgraded now. I, of course, have some questions, though. :)

Yes, as I hinted to you before. ;)

[quote name='Μichael' date='Aug 28 2008, 05:47 PM']This new hooks system will run 'database queries', you said. Are these going to be just full queries, using the query() function of the database driver (assuming such a generic function still exists), or are these queries going to be broken down the way the UMI does it, into tables, alters, inserts, and updates? If it's the latter, it will also be able to generate the 'reverse' queries to uninstall those changes? And will this support MSSQL and PostgreSQL?

It supports separation of the queries in much the same way yours does (separate create, alter, insert and update support). It can also generate the reverse of those queries in much the same way as yours. Presently, the create table is a single block field (again, similar to how UMI works) and we are thinking of ways to make this cross-database compliant. My best option presently is to allow separate create table statements based on the db engine. I took a look at where you were going with MSSQL support, but I can see race-cases and syntax differences occurring that might not work out so well in those situations.

Long story short, we're still determining how best to handle the alternate database engines.

And we don't support pgSQL at this time (officially) :P

[quote name='Μichael' date='Aug 28 2008, 05:47 PM']I'd like to hear some more information about the system you will have to let mod authors notify users if the mod is out of date, as coding that to work reliably on all kinds of server setups was by far the biggest headache of the UMI, and the problems continue to this day.

At the moment, the system supports the mod author filling in a URL that will be contacted when listing the work (with a low timeout). The mod author should return 1 or 0 to indicate if there's an update available (the version is sent in the URL for the mod author to compare against). This is a basic rough-in for the update system.

Now, what I'd like to do (but will likely need to wait for a later release, we'll see), is manage this entirely through the resources site somehow. e.g. when the mod author updates a modification on the resource site, a notification is automated that an update is available, and the callbacks go through the resource site that way. I still need to flesh out how that might work.

[quote name='Μichael' date='Aug 28 2008, 05:47 PM']Will there be some specific folder creater somewhere in IPB for mod source files to go? Let me clarify that. For many of my mods, I have to code a small file which does some querying or something to generate a small block of output. I typically will dump said file into the /sources/lib directory, but it then sort of sticks out like a sore thumb as there are other IP.Board source files there. Other modders put their source files in their own custom folders (Dean, for example, has his /sources/d22mods directory). What I'd like to see is a specific folder, maybe a sobfolder of /hooks, that is just a place to store source files for modifications that don't have any other logical storage location.

All files uploaded are cached to a /hooks folder, yes. The names are completely random (though the originals are stored in the database for reference when displaying the file to you).

One tricky aspect of this I needed to handle was the possibility that multiple files might extend the same class (e.g. two plugins extending the board index, which we've done in our example). If both extend the board index class directly, there won't be a single instance of the object - so I had to replace out the classname when caching the file so that hook1 extends board index, hook2 extends hook1, hook3 extends hook2, and we instantiate hook3 ultimately. That was nice and tricky, but works fine.

[quote name='Μichael' date='Aug 28 2008, 05:47 PM']Finally, you're not planning on releasing any of those 5 mods you mentioned at the end, are you? Because I'd hate for one or more of them to be my mods that I now no longer need to update. :lol:

Well, at least 2 hooks will ship out of the box (used by IPB, can be disabled, and gives people a good actual implementation to mirror when making their own), and we are strongly considering some hooks for our first party applications (blog/gallery/downloads) as well.

While we did use the members online today mod (lol) as one of those 5 that I mentioned, we do not intend to include that by default, no. I think you should be safe. ;)

Link to comment
Share on other sites

Awesome, thanks Brandon. You can be sure that once I get my hands on 3.0 I am going to put this hooks system through its paces, so expect to see lots of feedback from me on that. If I come up with any more questions (quite likely) I'll let you know. :)

Link to comment
Share on other sites

This sounds great, glad to hear such a system is being integrated into IPB 3. I'll have to dust off the many ideas I have for mods but never got around to implementing. Of course, I'll first have to see what the baseline IPB 3 system has. :D

..Al

Link to comment
Share on other sites

Sounds awesome guys, can't wait to get in there and break... i mean mess with this and of course i think the first mod i will work on is porting the ip.tracker so expect lots of feedback from me too. Also does this mod have a reinstall feature like the UMI (brilliant it has a umi btw!, just awesome!!) and if so does it support reinstalling individual features (template, db updates, lang), which i asked for ages for the umi btw, as this would be great too.

Link to comment
Share on other sites

[quote name='Jaggi' date='Aug 29 2008, 05:06 AM']Sounds awesome guys, can't wait to get in there and break... i mean mess with this and of course i think the first mod i will work on is porting the ip.tracker so expect lots of feedback from me too. Also does this mod have a reinstall feature like the UMI (brilliant it has a umi btw!, just awesome!!) and if so does it support reinstalling individual features (template, db updates, lang), which i asked for ages for the umi btw, as this would be great too.
The option to install/re-install/uninstall just parts of a mod was going to be one of my new features had I needed to upgrade the UMI for IPB3.

Link to comment
Share on other sites

Boy I wish there was multiquote in the blog lol.

@Michael, in addition to putting it through it's paces, we're fully aware that a brand new feature as extensive as this will have bugs that come along with it too, so we're hopeful our modding community, in testing this new functionality, will also help us get all the bugs stamped out quickly. :) We think the new plugin system will be one of the more popular end features in IPB3. We're anxious to get this out there so we can start improving on it right away. It's just a matter of finding out what sorts of improvements it needs first.

@Jaggi - there is no reinstall individual parts functionality, though that wouldn't be a bad idea. :)

Link to comment
Share on other sites

I'm fairly intrigued about how the action overloaders are supposed to work. Are individual functions being overwritten with an extended class? Or does the hooks plugins get called in conjunction with these functions allowing them to modify the result return of these functions? I'm not quite if I completely understand how this works. Would there be a way to add to a query in the middle of a function? Or would you have to tack on an additional query after the core function is complete? Like if I wanted to add an extra text box to the post box, how would I go about adding that data to an added column to the posts table?

Looking forward to hearing more about this :)

Link to comment
Share on other sites

Pretty much the same question I asked Brandon aswell :-) He said to go about adding things to the middle of functions, you should really use the template hooks. But as for your overloader question, that (as far as I am aware) would only work well for the beginning and ending of functions

function overwrittenFunction()
{
hook stuff 

parent::overwrittenFunction();

hook stuff
}
Link to comment
Share on other sites

So you can add stuff before and after a function, but not somewhere in the middle of it. Well.. that will definitely be a huge help. Obviously it wouldn't work for every situation, but it's still a very good solution. I suppose the more core functions are broken up into other functions, the more scalable this will be.

Link to comment
Share on other sites

as long as functions are small enough there shouldn' t be a need to insert stuff into the middle, a before hook (with the possibility to not execute the standard function) and a after hook would do nicely then.

Link to comment
Share on other sites



Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...