Updating Manager Pages in a Plugin VI

Adding a delete draft button that works.

This is the sixth 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 saw the final form of the Edit Draft and Edit Original buttons to be placed on the Create/Edit Resource panel. In this one, we'll look at how to create a functional Delete Draft button and its corresponding function.

MODX logo

Master Code Block

The first thing we'll do here is create a master JavaScript code block that handles all our buttons. We put comments in it that serve as placeholders for the buttons, and for the deleteDraft function. We'll replace the whole comment with the appropriate code. Using the comments as placeholders makes the code easier to read and to understand.

Here's our master code block:

        $jScript = <<< STAGECOACHJS
<script type="text/javascript">
Ext.onReady(function () {
    // var siteUrl = "$siteUrl";
    // var scId = $scId;

    var buttonDiv = document.getElementById('modx-action-buttons');
    var buttonRows = buttonDiv.getElementsByClassName("x-toolbar-left-row");
    var buttonRow = buttonRows[0];

    if (buttonRow) {
        /* Buttons */

/* DeleteDraftFunction */

Notice that we've moved the three variables above our button code, because we only need to get those elements once. Then, we've added an if (buttonrow) statement so our code won't crash if the button row isn't found.

Because we already have the buttonRow element, we can take the code to find it out of our individual buttons, which now look like this:

Edit Draft Button

$editDraftButton = <<<EDITDRAFTBUTTON

    var editDraftButton = buttonRow.insertCell(0);
    editDraftButton.innerHTML = '\
        <span id="stagecoach_edit_draft_button" class="x-btn x-btn-small stagecoach-link">\
            <button onclick="window.location.replace(\\'{$managerUrl}?a=resource/update&id={$scId}\\')">Edit Draft</button>\

Edit Original Button

$editOriginalButton = <<<EDITORIGINALBUTTON

var editOriginalButton=buttonRow.insertCell(0);
    <span id="stagecoach_edit_original_button" class="x-btn x-btn-small stagecoach-link">\
        <button onclick="window.location.replace(\\' {$managerUrl}?a=resource/update&id={$liveId}\\')">Edit Original</button>\

Delete Draft Button

 $deleteDraftButton = <<<DELETDRAFTBUTTON

var deleteDraftButton = buttonRow.insertCell(0);
deleteDraftButton.innerHTML = '\
    <span id="stagecoach_delete_draft_button" class="x-btn x-btn-small stagecoach-link">\
        <button onclick="stagecoachDeleteDraft({$scId});">Delete Draft</button>\

The stageCoachDeleteDraft() function is the same as the one in the previous article

Managing the Code

In order to get the buttons and the function on the correct pages, we'll simply take our master function variable ($jScript), and use str_replace() to insert the buttons and the function when appropriate. We'll also set the variables necessary for the buttons to work properly. All this will be in the part of the plugin that executes when the OnDocFormRender event fires.

The code for the buttons and the variable has to be above this code:

/* Don't execute outside of MODX */
if ((!isset($modx)) || (!$modx instanceof modX)) {
    return '';

/* Bail if new resource is being created */
if (isset($mode) && ($mode === modSystemEvent::MODE_NEW)) {
    return '';

/* Bail if resource we're editing has been deleted */
if (isset($resource) && $resource instanceof modResource && $resource->get('deleted')) {
    return '';

switch ($modx->event->name)

    case 'OnDocFormRender': {
        /* Set text for confirm popup */
        $modx->getService('lexicon', 'modLexicon');
        $stageCoachConfirmDelete = $modx->lexicon('stagecoach_delete_confirm');

        $button = '';
        $managerUrl = $modx->getOption('manager_url'); // System Setting

        /* Get TV ID  and Resource ID; we'll use these to determins which buttons to show */
        $stagedResourceTvId = $modx->getOption('stagecoach_staged_resource_tv_id'); // System Setting
        $stageDateTvId = $modx->getOption('stagecoach_stage_date_tv_id'); // System Setting
        $resourceId = $resource->get('id'); // Id of the resource we're editing

        /* See if this resource has a staged resource */
        $c = array(
            'tmplvarid' => $stagedResourceTvId,  /* TV ID */
            'contentid' => $resourceId,  /* Resource ID */

        $query = $modx->newQuery('modTemplateVarResource', $c);
        $scId = $modx->getValue($query->prepare());

        if (!empty($scId)) { // this is an original with a staged resource with ID $scId
            /* Bail if staged resource is deleted or removed */
            $c = array('id' => $scId, 'deleted' => '0');

            /* If staged resource is gone, blank out TVs, save the resource, and bail out */
            if (! $modx->getCount('modResource', $c)) {
                $resource->setTVValue($stagedResourceTvId, '');
                $resource->setTVValue($stageDateTvId, '');
                return '';
        } else {
            /* $scId is empty; it's not an original, see if this is a staged resource
               Look for an original that has this resource in its Staged Resource TV */
            $c = array(
                'tmplvarid' => $stagedResourceTvId,  /* TV ID */
                'value' => $resourceId,  /* Resource ID */

            $query = $modx->newQuery('modTemplateVarResource', $c);
            $liveId = $modx->getValue($query->prepare());

            if ($liveId) {
                // This is a staged resource - $liveId is the ID of the original

        if (empty($scId) && empty($liveId)) {
            // No connections - bail out
            return '';

        /* replace buttons and function comments */
        if (!empty($scId)) {
            $jScript = str_replace('/* Buttons */', $editDraftButton . $deleteDraftButton, $jScript);
            $jScript = str_replace('/* DeleteDraftFunction */', $deleteDraftFunction, $jScript);
        } else {
            $jScript = str_replace('/* Buttons */', $editOriginalButton, $jScript);

        /* Inject final JavaScript */
    case 'OnWebPageInit':
        /* For future use */
    case 'OnDocFormSave':
        /* For future use */

The Logic

After the sanity checks have been passed and the necessary variables are set, we use the variables to determine what we need to know about the current resource. Once we have the IDs of the TVs, we query the modTemplateVarResource object to get the values of the TVs.

If the two TVs both have values, we first check to see if the staged resource exists with $modx->getCount(). If it doesn't (and this should never occur), some kind of mistake has been made. We blank out the two TV values and return.

If we pass this point and the $scId variable (the ID of the Staged Resource) is not empty. This is an Original Resource with an existing Staged Resource.

Next, if $scId is empty, we know this is not an Original Resource, so we check to see if it's a Staged Resource by looking for a resource that has the ID of this resource in its Staged ResourceTV. If we find one, we set the $liveId variable to its ID.

If both $scId and $liveId are empty, something is wrong and we bail out.

Now that we have the necessary information, we modify the master code (contained in the $jScript variable) with str_replace to insert the appropriate stuff.

Replacing the Comments

At this point, we know that the resource we're editing is either an Original Resource or a Staged Resource. If $scId is not empty, we know it's an Original Resource, so we replace the buttons comment with the Edit Draft button and the Delete Draft button and insert the Delete Draft function:

$jScript = str_replace('/* Buttons */', $editDraftButton . $deleteDraftButton, $jScript);
$jScript = str_replace('/* DeleteDraftFunction */', $deleteDraftFunction, $jScript);

If the $scId variable is empty, this must be a staged resource, so we only inject the Edit Original button code:

 $jScript = str_replace('/* Buttons */', $editOriginalButton, $jScript);

Finally, we inject the finished master code:


Coming Up

We have three working buttons, and they're shown on the appropriate pages. The Delete Draft button works, but we have no way to actually create a staged resource. We'll do that in PHP in the OnDocFormSave section of the switch statement in the next article.

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.