Creating Extras for Revo 3 Part 2: Transport Packages

Advice on building Transport Packages for Revolution 3 Extras.

By Bob Ray
May 10, 2022
Creating Extras for Revo 3 Part 2: Transport Packages

In the previous article, we saw some general information about the issues involved in updating an Extra so it will work in MODX Revolution 3. In this article, we’ll start looking at Transport Packages, which are what you build to upload to the MODX Extras repository that ultimately show up as the installable Extras you see inside MODX Revolution.

After learning how to create a Transport Package for Revo 3 in this article, in the next one we’ll explore how to handle Transport Package objects themselves in code.

Creating Transport Packages for Revo 3

As you probably know, the typical way of creating a non-trivial Extra for Revo 3 is to customize and run a script called build.transport.php. There’s not a lot you can do in the Transport Package script to tailor your package for Revo 2 or Revo 3, especially if you’ve decided to create a package that will install your Extra for both versions of MODX. That’s because when the build script runs, it can’t know which version you’ll be installing the Extra in.

The build script will have to instantiate MODX, and that will determine that nature of the objects it puts in the package. If the build script runs in Revo 2, it will create objects for Revo 2. If it runs in Revo 3, it will create Revo 3 objects. At this point, it’s better to run the script in Revo 2. Revo 3 will handle a Revo 2-style package, but a Revo 3 package will throw lots of errors when installed in Revo 2. Of course if you choose to have two separate versions, you should create each one in the environment it’s intended for. Your Revo 3 build script should be written for Revo 3, so when it creates a category, object, for example, instead of this code:

$category = $modx->newObject('modCategory');

You’d do this:

$category = $modx->newObject('MODX\Revolution\modCategory');

or this:

use MODX\Revolution\modCategory;
/* ... */
$category = $modx->newObject('modCategory');

You could also do this:

use MODX\Revolution\modCategory as Category;
/* ... */
$category = $modx->newObject('Category');

though I think this last option just makes the code more difficult to follow.

The use statement creates an alias where the last bit (after the final backslash) will be interpreted later in the code as the whole line. On other words, PHP will see modCategory and know that you mean MODX\Revolution\modCategory.

Exceptions to the Rule

We said above that there’s no way for the build script to know which version of MODX is running during Setup. This is not the case, though, for validators and resolvers. These run during the actual installation of the program, and as we saw in the previous article, it’s easy for them to find out the version of MODX they’re running under with code like this:

$isMODX3 = $modx->getVersionData()['version] >= 3;

For example, Resources in Revo 3 should have a class_key of MODX\Revolution\modDocument. A resolver that processes Resources used in your Extra can do this:

$isMODX3 = $modx->getVersionData()['version] >= 3;
$classPrefix = $isMODX3 ? 'MODX\Revolution\\' : '';

/* Get the resources here and loop through them setting the class_key: */
$aliases = array(
    'myresource1',
    'myresource2',
    /* ... */
);

foreach ($aliases as $alias) {
    $resource = $modx->getObject($classPrefix . 'modResource, array('alias' => $alias));
    if ($resource) {
        $resource->set('class_key', $classPrefix . 'modDocument);
        $resource->save();
    }
}

(The double backslash at the end of the Revo 3 prefix is necessary because without it, the final quote will be interpreted literally and will throw a syntax error.)

The code above will set the class_key properly in both versions, but as we'll see in the next article, there's a much better way to get the Resource class_key set properly during Setup with a lot less code.

You might be thinking that the test for Revo 3 could be improved by writing it like this:

$classPrefix = $modx->getVersionData()['version] >= 3; ? 'MODX\Revolution\\' : '';

I can pretty much guarantee, though, that there will be places in your code where you’ll just want to know the version, and you won’t want to be cluttering up your code with calls to getVersionData() every time you want to find that out.

With the two-line version, you can just do this later in the code:

if ($isMODX3) {
    /* Do something */
} else {
    /* Do something else */
}

If you’re not familiar with the PHP ternary operator, this line of code:

$classPrefix = $isMODX3 ? 'MODX\Revolution\\' : '';

is the equivalent of this code:

if ($isMODX3) {
    $classPrefix = 'MODX\Revolution\\';
} else {
    $classPrefix = '';
}

In the ternary operator the first term after the equals sign is the “if” part. The part just after the question mark is the “then” part, and the part after the colon is the “else” part.

Although the code above for setting the class_key field is not the best way to do that, there is a potential situation where the code above is necessary as we’ll see in the next article.


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.