Find Out if a MODX System Event has Fired

Creating a test to determine if a particular MODX System Event has fired

There's no sense writing a plugin tied to a MODX System Event that isn't firing when you think it is. You can spend hours trying to figure out why your plugin isn't working when in fact your plugin is fine.

Example: Your code retrieves resources, modifies them, and saves them. You assume that the onDocFormSave System Event is called when the resource is saved, but it isn't. The code of your plugin will never execute.

In this article we'll see a way to make sure that a system event has fired (and how many times it went off). But first, we'll take a quick look at how plugins and system events interact.

MODX logo

Plugins and System Events

Plugins and system events make a good team. Neither one makes much sense without the other.

When you edit a plugin, you can look at the "System Events" tab and see a list of checkboxes with system event names next to them. Checking a box connects the plugin to that System Event.

As MODX goes about its business, it will occasionally fire (the technical term is "invoke") a system event. In other systems, these are often called "hooks." The most common form for this is:

$modx->invokeEvent('EventName', $parameters);

Event names all start with On followed by a descriptive name for the event, like OnDocFormSave or OnDocFormPrerender.

When the invokeEvent() method executes, it checks to see if there are any plugins connected to that event. If there are, it executes the code of the plugins. You can see more information about this process in this blog article.

Making sure the Event has Fired

When writing a plugin, it's a good practice to make sure the event you want to attach the plugin to is firing when you think it is. To do that, just add code like this to your plugin. Make sure the event is checked on the System Events tab of the plugin.

$eventName = $modx->event->name;
$modx->log(modX::LOG_LEVEL_ERROR, $eventName . ' fired');

Then, perform the action in MODX, (or in your code), that you expect to trigger the event and check the MODX Error Log.

It sometimes helps to make sure the object you're dealing with is the one that's triggering the event. For example, if your test plugin is tied to OnDocFormSave, you can do this:

$eventName = $modx->event->name;
if ($resource) {
   $pagetitle = $resource->get('pagetitle');
} else {
    $pagetitle = "Resource object not available";
$modx->log(modX::LOG_LEVEL_ERROR, $eventName . ' fired for ' . $pagetitle);

Don't forget that if you're doing this on a production site, other people may be visiting pages or working in the manager. Their actions could also be triggering the event and the plugin.

Note that the object in question may not be available in the way you're retrieving it (or not available at all) — hence the sanity check in the if section. For example, in the OnDoc ... events, the resource you're operating on will be available as $resource. In the front end, though, the current resource is more likely present as $modx->resource. Of course, if your attaching your plugin to OnChunkFormSave, there's no resource at all.

The sanity check is critical because PHP errors in plugins can often result in a crash with no feedback at all. The first version above is safer, since there's no chance that it will call get() on a non-existent object.

Another advantage of this technique is that it will show you how many times the event is firing, since each time it will add an error to the error log. It will help solve the mystery of why your plugin is executing more than once.

Using a MODX Processor

For many of the things you want to do in code with MODX, like creating users, resources, chunks, etc., there is a MODX processor that will perform the action for you with a call to $modx->runProcessor(). Usually the processors will do it in a better way. For example, if you create and save a new user, you may forget to create a user profile. The User/Create processor won't. A more likely scenario is to delete a user in your code but forget to delete the user's profile, leaving an orphan modUserProfile and some orphan intersects connecting the user to one or more user groups in your database. The security/user/delete processor will handle all that for you. You might also accidentally remove yourself as a user. The processor won't let you do that.

Almost all the processors you'd want to use will fire one or more system events. They are all in the core/model/modx/processors directory. You can look at their code to see which events they fire, when they fire them, and what parameters they send (search for invokeEvent). You can see a somewhat flawed list of the events, their variables, and the files they're called in here.

Coming Up

What if you want to fire a system event yourself in your own code? It's almost always better to call a processor, but there might be cases where that's not a good option. There's no reason you can't call $modx->invokeEvent() yourself. We'll see how to do that in the next article. In fact, there might be cases where you want to create your own system event and invoke it in your code. We'll look at how to do that in article after that.

Looking for high-quality, MODX-friendly hosting? As of May 2016, Bob's Guides is hosted at A2 hosting. (More information in the box below.)

Comments (0)

Please login to comment.