Broadcasting your own events (from plugins) in Mango
One of the great features of Mango Blog is the plugin architecture. Generally, this means that a skin author includes extensibility points via Mango's standard events at pre-determined spots, which allows plugins to add their own content to various places on the page -- like the post content footer, in the case of Related Entries.
The skin author does so by including code similar to this in the skin:
<mango:Event name="beforePostContentEnd" />
In addition, you can include additional information in a template event by including additional attributes, like this:
<mango:Event name="beforePostContentEnd" foo="bar" />
Plugins listen for these events and respond to them.
Wouldn't it be nice if one plugin could broadcast events for other plugins to respond to? Well, they can.
The init method signature in your average plugin is based on this:
<cffunction name="init" access="public" output="false">
<cfargument name="mainManager" type="any" required="true" />
<cfargument name="preferences" type="any" required="true" />
<cfset setManager(arguments.mainManager) />
<cfset setPreferencesManager(arguments.preferences) />
<cfset setPackage("com/mypackage/myplugin") />
<cfreturn this />
</cffunction>
The "manager" and "preferencesManager" values that are being saved here are for the plugin developer's access into Mango's component API. If you want to use some Mango functionality, you should find it in one of those somewhere (instead of digging around in the Application scope).
In order to broadcast our own event, we'll need to get the plugin queue, and call its createEvent method.
<cfset getManager().getPluginQueue().createEvent( ... ) />
CreateEvent takes 4 arguments:
- Name
- Data
- Type
- Message
Name is simply the name of the event. Something like "myCustomPluginEvent" would work. When defining events, try to make them descriptive but concise. There's no need to use the word "event" in your event name, for example.
Data is a structure that will be available to the plugin that responds to your event, and should contain everything that the plugin needs to process the event. I'll cover this in more detail in a moment.
Type is the event type. There are a few to choose from:
- AdminForm
- AdminMenu
- Collection
- Delete
- ObjectAccess
- Pod
- Request
- Template
- Update
- {none} (Generic)
Each has their own usage and details, but for today I will only cover the last one: (Generic) where you pass an empty string to the third argument of the createEvent method, or do not include this argument at all (the default is an empty string).
And lastly, Message is another way to pass any necessary data in the event. This is typically used to display a message to the user, but it is not limited to a string type -- in fact, the default is an empty structure.
So, if we want to create a new generic message named "FooEvent", then we do so like this:
<cfset event = getManager().getPluginQueue().createEvent( "FooEvent", myData ) />
And then we can broadcast that event, like this:
<cfset event = getManager().getPluginQueue().broadcastEvent( event ) />
Notice that I'm re-using the event variable. The broadcastEvent method is passed the current value of the event object, and when all plugins respond that would like to, the event object is returned to the code that broadcast the event, in whatever state that the plugins left it in. In other words, plugins can modify the event object, and then it is available once again to the code that originated the event.
Above, I passed a variable called myData into the createEvent method. This can be of any type, as long as it includes everything that a plugin might need to respond to your event. It would be typical to use a structure.
When using certain event types, certain data is expected for the data argument of the createEvent method. For example, if you use the "Collection" type, the event has special handling that expects the data argument to be a structure containing keys named "query", "collection", and "arguments." You can find all of the event types and check out what they expect by looking at their event classes, located in {Mango-Install}/components/events.
And that's about it! When you broadcast the event, Mango will check for any plugins that listen for your event (by name), and let them respond to it. Afterwards, the object will be returned to your plugin, and you can continue as normal.
in Mango | 3 Responses 2010-09-07 09:00

Food for thought. A possible future article that I personally would enjoy greatly, is one that breaks down the principals, tags that are available, how to use them, requirements, and some testing procedures used in creating plugins. (More or less an extension of what you wrote here.)
Maybe I am alone on this because I am more of a creative than a programmer, but I don't innately understand what is happening in a plugin and when to use a particular method to accomplish a task etc. (information that should find it's way to the mango blog main site) This is what I really like about WordPress and is a major shortcoming of Mango Blog.