Overview
In my previous article, I wrote about using resolvers in a transport package to modify a snippet's code. In this one, we'll zoom in on the code that handles the snippet's default properties. You can see the full code in my previous article.
We'll still use the material at the top to set the class prefix, the search and replace strings and arrays, and the function to check for the old class names. Here's that code:
function checkContent(array $terms, string $content) {
foreach ($terms as $term) {
if (strpos($content, $term) !== false) {
return true;
}
}
return false;
}
$base = MODX_CORE_PATH . 'components/classextender/model/';
$prefix = $modx->getVersionData()['version'] >= 3
? 'MODX\Revolution\\'
: '';
$uSearch = 'UserData';
$uReplace = 'userData';
$rSearch = 'ResourceData';
$rReplace = 'resourceData';
$searchArray = array(
$uSearch,
$rSearch,
);
$replaceArray = array(
$uReplace,
$rReplace,
);
The Snippet Default Properties
The old class names we're trying to fix can appear in the snippet code (which we discussed in the previous article). But there are two snippet properties in the snippets that process both resources and users. They're called UserDataClass and ResourceDataClass. Their old values are userData and resourceData. Those need to change. There is also specific code in the snippets themselves that needs to be modified. For example, in the getExtUsers snippet:
$userClass = $modx->getOption('UserDataClass', $sp, 'userData');
and in the getExtUsers snippet:
$resourceClass = $modx->getOption('resourceDataClass', $sp, 'resourceData');
As I said in an earlier article, a user might have put those properties into the snippet tag, where they would override the ones in the snippet's default properties. We already handled that in the earlier article where we modified the content of the resource that hold those snippet tags. Now we need the check the default properties of the snippet.
Here's the default property code from the previous article:
$snippets = array(
'GetExtUsers',
'SetUserPlaceholders',
'GetExtResources',
'MyGetExtUsers',
'MySetUserPlaceholders',
'MyGetExtResources',
);
$snippetCount = 0;
$propertySetCount = 0;
$fixedSnippetCount = 0;
$fixedPropertiesCount = 0;
foreach ($snippets as $snippet) {
$snippetObj = $modx->getObject($prefix . 'modSnippet', array('name' => $snippet));
if ($snippetObj) {
/* Snippet code correction was here */
/* Check snippet's default properties */
$properties = $snippetObj->getProperties();
if (isset($properties['UserDataClass'])) {
if ($properties['UserDataClass'] === $uSearch) {
$fixedPropertiesCount++;
$properties['UserDataClass'] = $uReplace;
$snippetObj->setProperties($properties);
$dirty = true;
}
}
if (isset($properties['ResourceDataClass'])) {
if ($properties['ResourceDataClass'] === $rSearch) {
$fixedPropertiesCount++;
$properties['ResourceDataClass'] = $rReplace;
$snippetObj->setProperties($properties);
$dirty = true;
}
}
if ($dirty) {
$snippetObj->save();
}
/* Check property sets, if any */
/* Property set code here
(discussed in the next article)
*/
}
}
In the code above, we first get the snippets default properties with $snippetObj->getProperties(). Note that we didn't use $snippetObj->get('properties'), which you might think would to the same thing. It doesn't, though. Both of them translate the JSON string in the properties field into a PHP array, but the two arrays are very different.
The getProperties() method gives you a simple associative array of keys and values, with one entry for each property. Using get('properties) instead gets you a nested array where each entry in the outer array is another array containing all 9 fields for that property (name, value, area, desc, options, type, lexicon, desc_trans, and area_trans). There might be a use case where we'd need all that information, but this isn't it.
Using getProperties() is a lot more convenient. As a bonus, using setProperties() after we've made any fixes saves us from having to do a search and replace operation on a nested array. MODX handles that for us behind the scenes.
The next section of code does the same thing but with ResourceDataClass property instead of the UserDataClass property:
if (isset($properties['ResourceDataClass'])) {
if ($properties['ResourceDataClass'] === $rSearch) {
$fixedPropertiesCount++;
$properties['ResourceDataClass'] = $rReplace;
$snippetObj->setProperties($properties);
$dirty = true;
}
}
Finally, if we've made any changes, we save the snippet. It's default properties come along for the ride.
if ($dirty) {
$snippetObj->save();
}
userData class name is never going to show up in the getExtResources snippet, and vice versa. It would be fairly easy to fix this by using one section of code and selecting the search term based on whether the snippet name contained "user" or "resource."This would complicate the code and make it much more difficult to understand. It would also make the code much less generic, and would interfere with the ability to change the search terms at the top of the code to change other strings. The
strpos() function is extremely fast, so it would only gain us a handful of milliseconds at best.
Coming Up
In my next article, we'll see how to update any property sets attached to our snippets.
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.