MODX Snippet Development Part 4

In this article, we’ll improve the design of the Snippet to make it more usable, and improve its flexibility.

By Bob Ray  |  February 7, 2024  |  7 min read
MODX Snippet Development Part 4

In the last article, we cleaned up our code and gave the Snippet a single exit point. But there’s still a problem with the design. We’ll fix that in this article and begin adding some features that improve the Snippet’s flexibility.

Starting Point

For reference here’s where we left off in the last article:

/* NewResource snippet */

/* Default return value */
$output = '';

/* Return value for new resources that are published */
$newOutput = '<span class="new_resource">NEW!</span>';

/* Set $interval as the number of seconds in two weeks */
$interval = 1209600;

/* See if the resource is published */
$published = $modx->resource->get('published');

/* See if publication date is within the last two weeks */
if ($published) {
    /* Get the current time as a timestamp */
    $currentTime = time();

    /* Get the publishedon date (if any) and
       convert it to a unix timestamp */
    $ptime = strtotime($modx->resource->get('publishedon'));

    /* Get the resource's age in seconds */
    $age = $currentTime - $ptime;

    if ($age < $interval) {
        /* Yes, it's recent - return NEW! */
        $output = $newOutput;
    }
}

return $output;

It’s a Sin

Coders will argue about whether is a mortal sin, a venial sin, or a cardinal sin, but most will agree that it’s a sin to mix code and content together. PHP code is about making decisions and controlling the flow of the program. Theoretically, in a well-designed Snippet, there shouldn’t be any HTML or actual content. I don’t really like the term MVC (Model, View, Controller), but the concept is the same. Ideally, you have the business logic in the PHP, the form in the HTML contained in your Tpl Chunks, and the content in placeholders.

If you were going to create a menu based on your pages, for example, the PHP code of Wayfinder would provide the business logic, the Tpl Chunks would provide the form, and the Resource tree would provide the content through placeholders in the Tpl Chunks.

Conforming to some ideal of program design isn’t the only reason for moving the content out of your Snippet. Suppose you (or your client) would like to change the output of the Snippet. There should be an easier way than having to edit the raw PHP code of the Snippet.

Moving the Content

When it comes to moving your content and display format out of a Snippet, there are a number of places to put it. Sizable data sets will usually go in the database or sometimes in a file. Sizable blocks of HTML, will usually go in a Chunk. In our case, there isn’t that much to store or edit, so we’ll put it in a property in the Snippet tag. While we’re at it, we’ll also make the time interval a property, since it’s the only other thing the user might want to change.

New Code

The first obvious enhancement to our Snippet is to let the user control what will be displayed without having to edit the code of the Snippet. In this version, we simply make the string of HTML we want to use for indicating new Resources a property in the Snippet tag. The Snippet returns an empty string if the Resource wasn’t published in the last two weeks. If it’s more recent, the value passed in the tag is returned. The interval is now also a property.

[[!NewResource? &showNew=`<span class="new_resource">NEW!</span>` &interval=`1209600`]]
/* NewResource snippet */

/* Default return value */
$output = '';

/* Return value for new resources that are published */
$newOutput = $modx->getOption('showNew', $scriptProperties,
    '<span class="new_resource">NEW!</span>', true);

/* Set $interval as the number of seconds in two weeks */
$interval = $modx->getOption('interval', $scriptProperties, 1209600, true);

/* See if the resource is published */
$published = $modx->resource->get('published');

/* See if publication date is within the last two weeks */
if ($published) {
    /* Get the current time as a timestamp */
    $currentTime = time();

    /* Get the publishedon date and
       convert it to a unix timestamp */
    $ptime = strtotime($modx->resource->get('publishedon'));

    /* Get the resource's age in seconds */
    $age = $currentTime - $ptime;

    if ($age < $interval) {
        /* Yes, it's recent -- Set the return value */
            $output = $newOutput;
        }
    }
}

return $output;

The value you send in the Snippet tag’s &showNew property will be shown if the Resource meets the conditions, and nothing will show if it doesn’t. Notice how easy it was to make this change with the variables extracted and placed at the top of the Snippet. All we had to do was replace their values with a call to the getOption(), which extracts the values from the Snippet tag via the $scriptProperties array.

The $scriptProperties Array

I’ve written about this in other articles, but the only code that needs explaining above is the call to `$modx->getOption()`, so I thought put in a quick reminder about how it works. Skip this section if you already know.

Whenever MODX launches a Snippet, it gathers the properties from the Snippet tag, any attached property sets, and the Snippet’s default properties, puts them all in the same array, and sends it to the Snippet as the $scriptProperties array. It’s very common to see $scriptProperties (or some alias for it) in the second argument to getOption(). If there are many getOption() calls, the programmer will usually create a variable with a shorter name to save typing, like this:

$sp = $scriptProperties;
$modx->getOption('someOption', $sp);

The getOption() method takes four arguments. The first one is required, but the other three are optional:

public function getOption($key, $options = null, $default = null, $skipEmpty = false) {}

The first argument is the string you’re looking for. The second argument can be empty or an array. If it’s empty, getOption() will look for a MODX System Setting (or a Context, Group, or User Setting) with the key specified in the first argument. If the second argument is an array, getOption() will search the array for the key. If the key isn’t found there, it will search the settings, as described above. The third argument to getOption() is the default value to use if the key isn’t found.

The fourth argument tells getOption() what to do if the key is found but the value is empty. It must be true or false (false is the default). With the default value of false, getOption() will return whatever value it finds, even if it’s empty. When the fourth argument is set to true and the value is empty (e.g., 0, '', "", or null), though, getResources() will return the default value from its third argument instead.

That fourth argument is especially important in MODX Revolution, where Snippets can have default properties that might be empty. If the property is missing from the Snippet tag (or misspelled) and there is no default property with that key, the default value in the getOption() call will be used. But what if there is a default property with that key that was installed with the Snippet, and it’s completely empty and has never been set. In that case getOption() will return that empty value rather than using the default value in the getOption() call unless you’ve set the fourth argument to true.

There are cases where you don’t want that fourth argument. For example, say that the value you’re looking up is numeric, and might be 0. That would be considered an “empty” value in PHP, but you might not want to use the default value for it, since 0 would be an acceptable value for your Snippet.

More Uses for Properties

You can send anything that’s available in the page as the value of a property in the Snippet tag. For example, say you want to have different “New” indicators on different pages. You could create a TV called NewIndicator and put the value you want for the indicator (e.g., NEW, New!, This is NEW!!!, or nothing) in that TV on each page. Then, in the Snippet tag, you could do this:

[[!NewResource? &showNew=`[[*NewIndicator]]` &interval=`1209600`]]

Coming Up

In this article, we looked at how to move the content and user options out of the PHP code and into the Snippet tag. In the next one, we’ll see a more user-friendly way of letting the user specify the time interval.


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.