Updating Manager Pages in a Plugin X

Adding the code that actually updates the Original Resource when the stage date arrives

This is the tenth in a series of articles dealing with issues created by operations performed in plugins that work on the Create/Edit Resource Panel in the MODX Manager. In the previous article, we added the code that decides whether it's time to update the Original Resource. In this article, we'll put the (almost) final piece in place — the code that actually updates the Original Resource when the stage date arrives.

MODX logo

Updating the Original Resource

The code to actually update the Original Resource based on the content of the Staged Resource is fairly straightforward compared to some of the code in the previous articles. This code goes in the OnWebPageInit section of the plugin, replacing the comment near the end (and just below the "It's time to update the Resource" comment). The code should be indented. I've moved it to the left to make it easier to read.

Here's the Code:

/* Get the ID of the Staged Resource */
$tvr = $modx->getObject('modTemplateVarResource', array(
    'contentid' => $resourceId,
    'tmplvarid' => $stagedResourceTvId,

if (!$tvr) {
        '[StageCoach] . No StageID templateVarTemplate');
    return '';
$stageId = $tvr->get('value');
if (empty($stageId)) {
    $modx->log(modX::LOG_LEVEL_ERROR, '[StageCoach] StageID TV is empty');

/* Using the ID, get the Staged Resource Object */
$stagedResource = $modx->getObject('modResource', $stageId);
if (!$stagedResource) {
        '[StageCoach] Could not find Staged Resource');
    return '';
} elseif ($stagedResource->get('deleted')) {
    return '';

/* Get the Original Resource object */
$originalResource = $modx->getObject('modResource', $resourceId);
if (!$originalResource) {
        '[StageCoach] Could not find Original Resource');
        return '';

/* Archive original if option is set */
$archive = $modx->getOption('stagecoach_archive_original', null, false);
if ($archive) {
    $archiveFolder = $modx->getOption('stagecoach_archive_id', null, 0);
    if ($archiveFolder) {
        /* set params for duplicate - pagetitle will contain date/time */
        $params = array(
            'publishMode' => 'unpublish',
            'parent' => $archiveFolder,
            'newName' => $stagedResource->get('pagetitle') . '-' . 'Archived',
            'duplicateChildren' => false,

        /* @var $archivedResource modResource */
        $archivedResource = $originalResource->duplicate($params);

        $archivedResource->setTVValue('stageID', '');
        $archivedResource->setTVValue('stageDate', '');



/* update original resource */
$fields = $stagedResource->toArray();
$originalFields = $originalResource->toArray();

/* Don't set these fields */
unset($fields['id'], $fields['menuindex'], $fields['pagetitle'], $fields['publishedon'], $fields['alias'], $fields['published'], $fields['createdon'], $fields['hidemenu'], $fields['parent'], $fields['uri']);

$totalFields = array_merge($originalFields, $fields);

$originalResource->setTVValue('StageID', '');
$originalResource->setTVValue('StageDate', '');

/* Update publishedon date if option is set */
if ($modx->getOption('stagecoach_update_publishedon_date', null, false)) {
    $originalResource->set('publishedon', $date);

/* Save the updated Original Resource */
$success = $originalResource->save(0);

/* Do a partial cache refresh */
$cKey = $originalResource->get('context_key');
        'db' => array(),
        'auto_publish' => array('contexts' => array($cKey)),
        'context_settings' => array('contexts' => array($cKey)),
        'resource' => array('contexts' => array($cKey)),

    /* Transfer TVs here if option is set (next article) */

/* Remove staged Resource if original was saved successfully */
if ($success) {
    if (!$stagedResource->remove()) {
        $modx->log(modX::LOG_LEVEL_ERROR, '[StageCoach] Failed to remove staged resource');

} else {
    $modx->log(modX::LOG_LEVEL_ERROR, '[StageCoach] Could not save original resource');

return '';

The comments in the code above explain what each part is doing. The first section simply gets the IDs of the Staged Resource and the Original Resource by querying the appropriate modTemplateVarResource object. If that's successful, we get the Staged Resource Object and the Original Resource object.

Next, if the stagecoach_archive_original is set, we archive the Original Resource appending '-Archived' to its pagetitle. We get the stagecoach_archive_id System Setting to find the ID of the StageCoach Archives folder and use that for the parent so it will go in that folder, set it to unpublished, duplicate it, blank out our two TVs, then save the duplicate. Because we're in PHP, not JavaScript, we don't have to call the resource/duplicate processor as we did in an earlier article in this series. We can call the resource's duplicate() method.

Notice the weird way we set it to unpublished ('publishMode' => 'unpublish',). This is because we're calling the resource's duplicate method. This is what's necessary to tell the processor to make the duplicate unpublished. Setting the resource's published field to '' doesn't do it.

In the next section, we actually update the Original Resource. First, we get the fields of both the Staged Resource and the Original Resource into PHP associative arrays. If we wanted to transfer *all* the fields, we could just do this:


We can't do that because we definitely *don't* want to transfer all fields. We list all the fields that we don't want to update, and remove them from the $fields array with unset(). Important: we don't want to transfer the id field. If we changed the ID of the Original Resource, all its TV values would be lost, and any link tags on the site that point to the page would no longer work. We also don't transfer the published field since the Staged Resource is probably unpublished and we almost certainly wouldn't want to unpublish the Original Resource.

We use array_merge() to merge the fields of the Staged Resource that we didn't remove into those of the Original Resource. The ones that are not set in the $fields array (because we removed them) will keep their values from the Original Resource. Then we use fromArray() method to actually update the fields of the Original Resource, and save it. Then we do a partial cache clear so our changes will appear.

The next section (optionally) transfers TV values from the Staged Resource to the Original Resource, but we'll cover that in the next article.

Finally, if everything has gone as planned, we remove the Staged Resource. This code actually removes the Staged Resource from the database, rather than just marking it as deleted. If we had called $stagedResource->delete() instead, the Staged Resource would just be marked for deletion, but left in the Resource tree.

Coming Up

We've got one more section of code to add. It transfers the TV values from the Staged Resource to the Original Resource, but only if the stagecoach_include_tvs System Setting is set. We'll look at that code in the next, and final, article in this series.

Looking for high-quality, MODX-friendly hosting? As of May 2016, Bob's Guides is hosted at A2 hosting. (More information in the box below.)

Comments (0)

Please login to comment.