Fine-Tuning the Dirwalker Jumplist

This final article in the exploration of the DirWalker class, Bob shows how to solve the problem of duplicate events.

By Bob Ray  |  April 19, 2022  |  5 min read
Fine-Tuning the Dirwalker Jumplist

If you’ve been following along with this series of articles on using DirWalker to produce a report on MODX System Events and have looked recently at the output here, you may have noticed that the problem of having multiple references to the same event has been solved. This article is for those curious about how it was done.

To review, the problem with our previous code was that when the same event was fired more than once, either in the same file or another one, the same link was produced for each instance. Any link in the jumplist for that event name would take the user to the first instance.

The Solution

In the previous article, we “solved” the problem by calling array_unique() on the array used in the jumplist, but that wasn’t a real solution. It just removed any links to the other instances of the event from the jumplist.

The real solution to the problem is to make each link unique by adding a suffix to each event name, using the name with the suffix for the link and removing the suffix before displaying the event name.

The Code

I won’t burden you with the whole Snippet. We’ll just look at the changes necessary to solve the problem. First, in the processFile() method, we add the suffix using PHP’s uniqid() function, which creates a unique number based on the current time (in milliseconds):

'event' => $match[1] . '-' . uniqid(),

The dash is there so we can easily strip the suffix when displaying the output. It’s a suffix, rather than a prefix, so it won’t affect the sorting of the jumplist.

Next, in the section that assembles the jumplist, we use the full name (with the suffix) for the link and the name without the suffix for the displayed event name:

$jumpList = '';
$jumpArray = array();
/* Put the event names in an array so we can sort them */
foreach($files as $file => $events) {
    foreach ($events as $event) {
        $jumpArray[] = $event['event'];
    }
}
sort($jumpArray);

/* Make the jumplist */
foreach ($jumpArray as $link) {
    $eventName = substr($link, 0, strpos($link, '-'));
    $jumpList .= '<a href="[[~[[*id]] ]]#' . $link . '">' .
        $eventName . '</a> &nbsp;&nbsp;';
}

The first foreach loop above creates an array containing the event names with their suffixes. In the second foreach loop, $link is the event name with the suffix, and we set the $eventName variable, which is the event name without the suffix. This line strips the suffix:

$eventName = substr($link, 0, strpos($link, '-'));

In the PHP substr() function, the first argument is the full string being processed, the second is the starting position of the substring we want (in this case, 0), and the third is its length—which we get using strpos(). The strpos() function reports the position the hyphen (counting from 0), which is exactly what we want.

Notice that the $tempArray variable we used in the last version is gone, because we no longer need it.

Note: arguably, the use of a name= in the code below should be replaced by a id=. Using name here is not valid HTML, but some very old browsers won’t recognize anything else as a link target.

Finally, we do the same thing with the anchor links in the report and the displayed names of the events:

foreach($events as $event) {
        $l = $event['event']; /* link */
        $e = substr($l, 0, strpos($l, '-')); /* event name */
        $v = $event['variables'];
        if (strpos($v, 'array') !== false) {
            $v = preg_replace('#^\s*\'#m', '<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\'', $v);
            $v = preg_replace('#^\s*\)\);#m', '<br />&nbsp;&nbsp;&nbsp;&nbsp;);', $v);
        } else {
            $v = str_replace(');', '', $v);
        }
        /* Anchor link to event */
       $output .= '<a name="' . $l . '"></a>';
       /* Event name and variables */
       $output .= "&nbsp;&nbsp;&nbsp;&nbsp;<span style=\"color:teal;\">Event:</span> <b>" . $e . '</b><br />';
       $output .= "&nbsp;&nbsp;&nbsp;&nbsp;<span style=\"color:teal;\">Variables:</span> " . $v . '';
    }

We’ve added a variable, $l, which we use for the link target. The variable $e is still the event name, but now we have to get it by stripping the suffix as we did for the jumplist. Otherwise the code is the same.

One last change was made. Since we don’t mind having multiple references to the same event, we search for all .php files instead of just .class files. When looking just in the class files, we miss some events that occur in legacy processors that do not yet have corresponding class-based processors. So now our include line looks like this:

$dw->setIncludes('.php');

Many of the event invocations will appear several times because we’re now processing both the new, class-based processors and the legacy .php processors.

Performance Issues

The new code does slow down the process slightly, but not much. And since the whole page can be cached, it’s not much of a penalty. You may have noticed that every link in the jumplist and every anchor link in the report gets a unique suffix, whether they need it or not. Only repeated events need a unique link. The fact is, though, that it’s faster to create and add a unique link than to figure out whether or not it’s needed. Having a suffix on some event names and not others would also slow down the code that creates the output.

If you look closely at the output of the code above at Bob’s Guides, you’ll see that although the report has plenty of useful information, it still has some issues. Fixing those is left as an exercise for the reader.


Bob Ray is the author of the MODX: The Official Guide and dozens of MODX Extras including QuickEmail, NewsPublisher, SiteCheck, GoRevo, Personalize, EZfaq, MyComponent and many more. His website is Bob’s Guides. It not only includes a plethora of MODX tutorials but there are some really great bread recipes there, as well.