There are times when the MODX docs just won't tell you what you need to know. You have to look at the relevant code itself. Before you can do that, though, you have to find it.
I've spent a lot of time plumbing the depths of the MODX code (sometimes I dream about it), and I thought I'd offer up some tips for finding things there.
Get Yourself a Good Code Editor
Without a decent code editor, finding things in the MODX code is almost impossible. At the very least, you need an editor with multi-file search capability. I use JetBrains' PhpStorm, which goes well beyond that. It currently costs $99 but sometimes goes on sale for $49. At either price, it is absolutely worth it if your time is worth anything at all. If you write code, it will pay for itself in no time at all and you'll wonder how you got along without it. I've also used Eclipse (briefly), NetBeans, Crimson Editor, PhpEd, PSPad, Notepad++, and a number of editors that are obsolete and/or no longer exist. PhpStorm basically made me forget almost all of them, though I do still use NuSphere's PhpEd (which now has a 64-bit version) for editing very large files.
I use PhpStorm's multi-file search a lot. I have a single PhpStorm project that includes the current version of MODX and all my extras (under the
assets/mycomponents directory). PhpStorm shows a tree on the left with all files in the project. You can right-click on any directory and select "Find in Path" and it will recursively search all files in that directory. If you right click at the top of the tree, you can search everything. A setting allows you to exclude directories from the search (e.g., setup, cache, etc.). You can also set a filter so that it only searches files of certain types (e.g., .js, and/or .php). The search results appear in a window below the code and when you click on a result, it opens the file and puts the cursor on the line with the search term
Finding Methods (functions)
This one is easy. The MODX code always has a single space between the word "function" and the function name. If you want to find the code of the
getObject() method, just search for
function getObject. Above the function, you'll find a list of the method's arguments with their types and what they're for. You'll also see the type returned from the method if there is a return value. Of course you can also look at the code of the method itself to see how it handles the arguments and performs its task.
Because the MODX code is so fragmented, you often find yourself wandering around in it. This happens with the code of extras too. I've spent many hours wandering around in the code of the Login package — many of its files are only a few lines long. Luckily, PhpStorm indexes all the functions in a project. You put the cursor on a function call, press Ctrl-b, and almost instantly, you're looking at the code of the function. Ctrl-Alt-left-arrow takes you back where you were. If the called function calls another function, you can go there, and so on. This is infinitely more pleasant than doing a search for each function in turn and quickly losing your place (if not your mind).
While walking through the methods, you often find yourself in a class for which much of the business is taken care of in a parent class or some ancestor of the current class. This is especially true if you're wandering around in the
core/model/modx directory, which contains all the MODX class files, or the labyrinth of MODX processor classes in
core/model/modx/processors directory. The
snippet/create processor (
modSnippetCreateProcessor class), for example, extends
modElementCreateProcessor, which extends
modObjectCreateProcessor, which extends
modObjectProcessor, which extends
modProcessor. Ctrl-b works here too. You just put the cursor on the class name that comes after the word "extends," press Ctrl-b, and you're looking at the parent class. You can walk up through the hierarchy of classes with a few key presses.
This is trickier because you may not be able to guess the name of the processor class. I often just go to
core/model/modx/processors/ and navigate to the processor I want, but you can also use a regular expression (regex) search in that directory. For example, if you're looking for a snippet processor, but you're not sure of the name, you can right-click on the
processors directory, select "Find in Path,", select "Regular Expression" for the search type and enter
modSnippet.+Processor in the search box. This will quickly show you a list of all the snippet processors and you can click on the one you want to see its code. The dot operator in the regex means any character and the plus means one or more. The capital letters in the search string are not important in PhpStorm unless you select a "case sensitive" search, but they might be in some other editors.
Quite often, when writing plugins, you want to know what variables are available in the plugin. This depends on the event or events the plugin is connected to. Since events don't have any code, you can't see them directly. Instead, you have to look at some point where the event is "invoked.". Of course you could look in the Appendix of my book, but maybe you don't have it handy.
Most often, events are invoked by MODX processors, so the
core/model/modx/processors directory is the place to look. If you want to see all of the MODX event invocations, you can do a search in that directory for
invokeEvent, since that will always be present when an event is fired.
If you know the event you're looking for, you can search for something like
invokeEvent('OnDocFormSave'. Notice that the end of the search string is left open because we don't know what second argument contains yet. What you'll find will look something like this:
$this->modx->invokeEvent('OnDocFormSave', array( 'mode' => modSystemEvent::MODE_NEW, 'id' => $this->object->get('id'), 'resource' => &$this->object, ));
The three members of the array are the variables that will be sent to any plugin attached to that event. In the plugin, the
$mode variable will always be either
modSystemEvent::MODE_UPD, depending on whether the calling code is creating a new object or updating an existing one. The
$id variable will contain the ID of the object and in this case, the
$resource variable is the resource object. For this particular event, you don't need to get the resource object itself because it's already available in the
In rare cases, the event is invoked through a variable like this:
$this->modx->invokeEvent($event,array( 'id' => $this->object->get('id'), 'user' => &$this->object, 'mode' => modSystemEvent::MODE_UPD, ));
In those cases, you have to look at the code earlier in the file to see what
$event is set to to see the name of the event being invoked.
Some events have no variables associated with them. In that case, there will be no second argument and you'll see something like this:
In those cases, a plugin attached to the event gets no information whatsoever.
Fuzzier Event Searches
What if you're not sure about the event name? All event names start with
On, so if you know the type of object involved (e.g., user), you can do a regex search in the processors directory for something like this:
invokeEvent\('On.*User. That will find all the user-related event invocations. You have to use the backslash to escape any parentheses and we've used an asterisk here instead of a plus sign. The asterisk means zero or more of the preceding character. Otherwise, we'd miss any events that start with
OnUser. Making the search case-sensitive would make it a little faster.
Note that some of the resource-related Manager events do not contain the term
resource, instead, they use
doc (e.g., OnDocFormSave). It's also worth noting that many of the Manager events for creating and updating objects in the Manager contain the word
Form. To see all of them, you can do a regex search for
Events that contain the word
Form are always triggered by an action performed by the user in the Manager such as saving the Create/Edit form for a user, resource, or element.
You can learn a lot about MODX from the official and unofficial documentation, but it doesn't cover everything. Knowing how to find specific bits of code can help you learn MODX from the inside out.
In future blog posts, I'll expand on this concept and discuss how to write code that searches the MODX codebase for you and creates live reports on the code that you can use for reference like the MODX object Quick Reference and xtypes pages at Bob's Guides.