In my previous article, we looked at Transport Package issues in converting an Extra for Revolution 3. In this one, we’ll look specifically at Resources and users.
Resources
If you create a package that will run in both Revo 2 and Revo 3, the correct class_key
of a Resource properly varies. In Revo 2 it’s modDocument
. In Revo 3 it’s MODX\Revolution\modDocument
.
In the last article, we saw some code for setting the class_key
field correctly after-the-fact in a resolver. In that article, I hinted that there was a better way. Here it is: if the class_key
field of a Resource being transported in a Transport Package is unset, MODX will fill it with the correct value for the version of MODX the process is running in.
Usually, any Resources you put into a package have some fields set, like pagetitle
, description
, introtext
, published
, etc. As long as you don’t send the class_key
field, it will get set properly.
If you’ve created the fields using $resource->toArray()
, you can always just edit out the class_key
field, or if the process is automated, use unset($fields['class_key']);
. This has to be done before running the build.transport.php
script (unless you want to dig into the guts of the resulting transport file, which you definitely don’t).
Why modDocument?
If you’re wondering why we usemodDocument
here instead of modResource
, it’s because there are multiple types of modResource
objects. Most of the Resources on the site will use modDocument
, but there may also be weblinks, symlinks, or static Resources. The class keys for these are modWebLink
, modSymLink
, and modStaticResource
. The modResource
class is the parent class for those three classes, plus the modDocument
class.
Although dropping the class_key
field before building the transport package is the best method, there is a situation where you might want to fix it in a resolver. If a Revo 3 user has installed an older version of your package, and that version has the Resource class_key
field set to modDocument
, you can update it in a resolver to the correct value. Here is the code, quoted from my previous article:
$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();
}
}
This is a fairly rare occurrence. When a site is updated from Revo 2 to Revo 3, Setup updates all the Resource class keys. So the user would have to have installed the older version after upgrading to Revo 3. Still, you might want to do this, just to be on the safe side.
It’s uncommon to create anything other than modDocument
Resources in a Transport Package, but if you do, you can adapt the resolver code above to correct their class keys.
Users
The user object also has a class_key
field. In Revo 2, it’s modUser
. In Revo 3, it’s MODX\Revolution\modUser.
If your Extra doesn’t create any users, you don’t have to worry about them in your Transport Package. If you do create users, the best practice, as for Resources, is to omit or unset the class_key
field for all users before the package is built. MODX will set it correctly for you.
If the package is an upgrade, you may want to create a resolver that makes sure the class_key
is correct for the MODX version of the site, as we did for Resources just above. You can adapt the code above for this by just changing modResource
to modUser
in the code, and retrieving the objects by username
rather than alias
.
Use Statements and instanceof
As you’ve probably figured out, use
statements can’t be used in code that’s meant to run in both Revo 2 and Revo 3, because they would only be used in Revo 3, and there’s no such thing as a conditional use
statement. Because they apply at compile time rather than run time, they can’t be enclosed in an if
statement, and you can’t use a variable holding a string for them either.
There’s also no way to make instanceof
work in both Revo 2 and Revo 3 because the classes won’t be the same, and like use
you can’t use a variable to represent the class name. Luckily, MODX is very reliable about returning null
if it can’t instantiate or retrieve a class object, so something like this will work fine:
$doc = $modx->getObject($classPrefix . 'modResource', $criteria);
/* Or $doc = $modx->newObject($classPrefix . 'modResource'); */
if (! $doc) {
/* call failed */
}
If you feel you really need to find out if you have a genuine object of a specific class, you can do something like this:
if (isObject($doc) && (get_class($doc) === $classPrefix . 'modResource')) {
/* Object is legit */
} else {
/* not an instance of $classPrefix . modResource */
}
Of course if you have a separate version of your package for Revo 3, you’re free to use both use
and instanceof
at will.
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.