Understanding MODX System Events and Plugins

One of the great things about computers is that you can make them do some of the tedious, repetitive, grunt work for you. Say for example, that you want to set a particular TV value for new resources created in a particular folder, but only if certain other conditions are true. If it weren’t for the other conditions, you could use Form Customization, but once you introduce anything beyond checking resource field values, Form Customization won’t do it for you. You need a plugin.

Similarly, you might want to do something special with a user when the user is saved. Maybe you want to add users to a User Group based on their zip codes or phone area codes. Maybe you want to create a user group and resources group for each user so they can have resources that they alone can access. Again, you need a plugin.

In both cases, you could perform the task by hand every time a new resource or user is created, but let’s face it — you have better things to do with your time.

MODX logo

Plugins To the Rescue

People are often afraid of plugins because they don’t understand them. They are a bit mysterious, operating in the background as MODX goes about its business, but it’s a shame to give up the power of plugins just because they aren’t as obvious as snippets.

A MODX snippet is just a bit of PHP code that is executed when MODX encounters a snippet tag. The return value of the snippet replaces the tag.

Plugins, in contrast, don’t involve tags at all and often don’t have return values, but like a snippet, a plugin is just a bit of PHP code that is executed at a given time. In the case of plugins, that time is when a System Event they are tied to “fires”.

System Events

As MODX performs its usual tasks, it periodically fires what are called System Events (in many other systems, these are called “hooks”). A System Event is just MODX’s way of periodically asking, “Does anyone have anything they want done at this point?”

System Events are fired at strategic points where a developer might want to take some action. For example, when a resource or user is saved or deleted, the code that does the work invokes a particular System Event. There are many System Events, some of which are fired in more than one situation. There’s an exhaustive list of System Events and the variables available for each one here

How It Works

System Events are “fired” in PHP code. This particular example lives in the processor that saves resources:

$modx->invokeEvent('OnDocFormSave', array(
    'mode' => modSystemEvent::MODE_NEW,
    'id' => $this->object->get('id'),
    'resource' => &$this->object,
));

The code above is placed just after the code that saves the resource to the database. When MODX encounters that code, it calls the invokeEvent() method in the MODX class file. That method simply checks to see if any plugins are connected to that event. If so, it executes their code (sending along the three variables in the array). If not, it does nothing. We’ll look at that in more detail in a bit, but first, let’s back up and see how the plugins get attached to the events.

When you create or edit a plugin, there’s a “System Events” tab with checkboxes for every possible System Event. When you check a box for a particular event and save the plugin, MODX creates a record in the modx_site_plugin_events table, recording the id of the plugin and the name of the event. That’s your way of telling MODX, “when this event fires, run this plugin’s code”.

Looking at things from the other side, when the invokeEvent() method is called (say, when a resource is saved in the Manager), the invokeEvent() method gets the name of the event as its first argument, and the array of variables (like the ones in the code above) as its second argument. MODX looks at the modx_site_plugin_events table to see if there are any records for the named event. If not, it does nothing. If there are registered plugins, however, it runs them, and the variables in the second argument are sent along for the ride.

On that same tab where you set the event(s) your plugin is attached to, you can also select a property set to be used with the plugin (it has to go here, because there is no plugin tag in which to specify a property set). There is also a place to set the plugin’s “Priority”. During the invokeEvent() action, if MODX finds more than one plugin attached to the current event, it executes them in order of their priority, starting with 0. Most of the time, the order of execution doesn’t matter, but occasionally, the order in which the plugins execute could make a difference.

The Variables

In the example above, the $mode, $id, and $resource variables will be available in the plugin.

The $mode variable just indicates whether the object is new or not. Its value is a constant (the actual values are ‘new’ and ‘upd’) and will always be either modSystemEvent::MODE_NEW or modSystemEvent::MODE_UPD

The $id variable is the ID of the resource being saved and the $resource variable is the resource object itself. Note that where you would use $modx->resource in a snippet, in a plugin, you would often use just $resource. The $modx->resource variable is seldom set for an event that’s fired in the Manager, a fact that trips up a lot of beginning plugin writers. It *is* often set, though, for events that fire in the front end, like OnWebPagePrerender. You can always look here to see which variables (if any) are available for a given event.

Doing Stuff

Once you’ve determined that an event fires at the point where you want to perform some action, you simply attach a plugin to the event, write the plugin code, and leave the rest to MODX.

For example, say you want to do something when a new resource is saved (but leave existing resources alone). The code, attached to OnDocFormSave, would look something like this:

if ($mode !== modSystemEvent::MODX_NEW) {
    return;
}
/* Your code here */

The first line checks to see whether the resource is new, and if not, it simply returns without doing anything. The “Your code here” part is where you do whatever you want with the resource.

In upcoming articles, we’ll look at some examples of things you might want to do at that point.

Multiple Events

Many plugins are attached to a single event, but they can actually be attached to as many events as you like. In the ClassExtender extra, for example, one of the plugins is attached to both OnUserFormPrerender and OnUserFormSave. During the former event, it adds fields to the Create/Edit User form. During the latter, it saves the content of those fields to the database. This could have been done with two separate plugins, but having the code together is convenient and adds less clutter to the Elements tree.

When a plugin is attached to more than one event, it needs to detect which event has fired in order to know what bit of code to run. This is easy to do because the name of the event is always available in the plugin as $modx->event->name. You could use the PHP if statement to identify the current event, but usually it’s done like this:

switch($modx->event->name) {
    case 'OnDocFormPrerender':
        /* some code here */
        break;

    case 'OnDocFormSave':
        /* some different code here */
        break;
}

 

If there is code that you want to execute in both cases, (e.g., code that returns if it’s not a new resource), just put it outside the switch statement.

It’s not uncommon to see code that checks $modx->event->name in plugins that are attached to only one event. This is unnecessary, since the value of modx->event->name will always be the name of the event the plugin is attached to.

Last Words

Plugins can be a great way to automate repetitive tasks in MODX. One catch that you should be aware of, however, is that when a PHP error occurs in a plugin, things often just hang. Worse yet, you usually can’t use print or echo to display debugging information from a plugin. That’s why it’s essential to have a good code editor that highlights PHP errors as you write your code. Another valuable plugin tip is (if possible) to write your plugin as a snippet first, since snippets are much easier to debug. Always remember to convert the variables when you move the code into a plugin (e.g., changing $modx->resource to $resource).

 


For more information on how to use MODX to create a web site, see my web site Bob’s Guides, or better yet, buy my book: MODX: The Official Guide.

Looking for quality MODX Web Hosting? Look no further than Arvixe Web Hosting!

Tags: , , , , , , , , , , , , | Posted under MODX, MODX | RSS 2.0

Author Spotlight

Bob Ray

Bob Ray

I am the author of MODX: The Official Guide and over 30 MODX add-on components. I host Bob's Guides, a source of valuable information for MODX users, and I've been very active in the MODX Forums with over 14,000 posts.

Leave a Reply

Your email address will not be published. Required fields are marked *


9 − 5 =

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>