Overview
In my previous article, I wrote about using resolvers in a transport package to modify chunks. In this one, we'll see examples of using code in a resolver to update snippets, their default properties, and any attached property sets. To keep this article from getting ridiculously long, we'll see the code for all three tasks here, but we'll discuss it over three articles (this one, and the next two). The code below integrates all three tasks. As we process each snippet, we first update the code of the snippet, then it's default properties, then any property sets attached to it.
As we learned in my previous articles, you can use getContent()
and setContent()
to modify the content of all elements except template variables (more on those in a later article). The process is very similar to what we did with
resources in the previous article, but the addition of snippet properties makes things more complicated.
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-specific Code
This is more complicated than the code in the previous articles, because the class names can appear in the snippet code,
and in the snippet properties. 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 getExtResources snippet:
$resourceClass = $modx->getOption('resourceDataClass', $sp, 'resourceData');
Correcting the code is actually the easy part. It's just like correcting the text of a chunk. Correcting the properties and property sets is more complex, and it's further complicated by doing it as each snippet is processed.
The snippet-specific code in the Upgrade section of the resolver looks like this:
$snippets = array(
'GetExtUsers',
'SetUserPlaceholders',
'GetExtResources',
'MyGetExtUsers',
'MySetUserPlaceholders',
'MyGetExtResources',
);
$snippetCount = 0;
$propertySetCount = 0;
$fixedSnippetCount = 0;
$fixedPropertiesCount
foreach ($snippets as $snippet) {
$snippetObj = $modx->getObject($prefix . 'modSnippet', array('name' => $snippet));
if ($snippetObj) {
$snippetCount++;
$dirty = false;
$content = $snippetObj->getContent();
if (checkContent($searchArray, $content)) {
$fixedSnippetCount++;
$content = str_replace($searchArray, $replaceArray, $content);
$snippetObj->setContent($content);
$dirty = true;
}
/* 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 */
$propertySets = $snippetObj->getMany('PropertySets');
if (!empty($propertySets)) {
foreach ($propertySets as $propertySet) {
$dirty = false;
$propsetId = $propertySet->get('property_set');
$propertySetCount++;
$actualPropertySet = $modx->getObject($prefix . 'modPropertySet', $propsetId);
$props = $actualPropertySet->get('properties');
if (isset($props['UserDataClass'])) {
if ($props['UserDataClass']['value'] === $uSearch) {
$fixedPropertySetCount++;
$props['UserDataClass']['value'] = $uReplace;
$actualPropertySet->set('properties',$props);
$dirty = true;
}
}
if (isset($props['ResourceDataClass'])) {
if ($props['ResourceDataClass']['value'] === $rSearch) {
$fixedPropertyCount++;
$props['ResourceDataClass']['value'] = $rReplace;
$actualPropertySet->set('properties',$props);
$dirty = true;
}
}
if ($dirty) {
$actualPropertySet->save();
}
}
}
}
}
In the following section, we'll take a closer look at the part that modifies the snippet code.
The Snippet Code
The code in first part of the loop above should look familiar:
if (checkContent($searchArray, $content)) {
$fixedSnippetCount++;
$content = str_replace($searchArray, $replaceArray, $content);
$snippetObj->setContent($content);
$dirty = true;
}
It's just like the code in the previous articles, except for the addition of the $dirty
variable and the missing
save()
line. We don't want to save the snippet twice, so if either the snippet or it's default properties need
changing we'll set $dirty = true
. Later, we'll save it, but only if its "dirty."
We get the snippet, then get its code with $snippetObj->getContent()
. Once we have that, we use our checkContent()
function to see if it contains either of the old class names. If it does, we update the content to the new class names,
update the snippet's code with setContent()
and set it as "dirty." Notice that we don't save it. That happens later in
the code.
If the old class names don't appear in the code, we move on to checking the snippet's default properties. That makes
this code quite unusual in that there are (If I've counted them correctly) eleven if
statements, but not a single
else
statement.
Coming Up
In my next article, we'll look at the code section above that modifies the snippet's default properties. In the one after that, we'll discuss the code section that handles any property sets attached to the snippet.
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.