We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 6949 ☆ A M B ☆
    • 19 Posts
    Hi there!

    I have a plugin that is fired on the event onDocFormSave. I want to see if a TV value has changed between the original and now-saving version and perform an action if so. Is there a way to check if a TV value has changed at the onDocFormSave event? I could be convinced to use the onBeforeDocFormSave event if it's more convenient as well smiley

    Thanks!

    Scott

    This question has been answered by multiple community members. See the first response.

      • 3749
      • 24,544 Posts
      There is definitely a way to do it. CacheMaster used to check that. It's very easy to do, but not so easy to figure out how. I think you want OnBeforeDocFormSave, but I'm not positive.

      The new TV value is buried deep in the $scriptProperies array available in the plugin. If $scriptProperties['data']['tvs'] is true, the Resource has TVs. The TVs themselves are stored as ['data']['tv1'], ['data']['tv2'] etc. The numbers are the TV IDs.

      This is part of the old code from CacheMaster (thank you GitHub). It checks to see if *any* TV has changed, so you'll have to modify it. The my_debug() function, BTW, just writes the first argument to a chunk called 'debug' -- handy for debugging plugins because you can "Quick Edit" the chunk to peek at the output. The second argument clears any previous data if set to true.

      if (!function_exists("my_debug")) {
          function my_debug($message, $clear = false)
          {
              global $modx;
              /* @var $chunk modChunk */
              $content = '';
      
              $chunk = $modx->getObject('modChunk', array('name' => 'debug'));
              if (!$chunk) {
                  $chunk = $modx->newObject('modChunk', array('name' => 'debug'));
                  $chunk->setContent('');
                  $chunk->save();
                  $chunk = $modx->getObject('modChunk', array('name' => 'debug'));
              } else {
                  if ($clear) {
                      $content = '';
                  } else {
                      $content = $chunk->getContent();
                  }
              }
              $chunk->setContent($content . "\n" . $message);
              $chunk->save();
          }
      }
      
      
      if (isset($scriptProperties['data']['tvs'])) {
              unset($scriptProperties['data']['tvs']);
              $tvs = array();
              foreach($scriptProperties['data'] as $k => $v) {
                   if(strstr($k,'tvbrowser')) {
                       continue;
                   }
                   if (substr($k,0,2) == 'tv') {
                       $tvs[$k] = $v;
                   }
              }
              $d = print_r($tvs, true);
              my_debug($d);
      
              foreach($tvs as $k => $v) {
                  $tvNumber = (integer) substr($k,2);
                  $oldVal = $resource->getTVValue($tv);
      
                  if ($val != $v) {
                      $ok = false;
                      my_debug('TV ' . $tvNumber . ' Changed' );
                      my_debug('OLD: ' . $oldVal . 'NEW: ' . $v);
                      break;
                  }
              }
          }


      If I have time, I'll try to play with this and clarify how to see if a particular TV has changed. [ed. note: BobRay last edited this post 13 years, 1 month ago.]
        Did I help you? Buy me a beer
        Get my Book: MODX:The Official Guide
        MODX info for everyone: http://bobsguides.com/modx.html
        My MODX Extras
        Bob's Guides is now hosted at A2 MODX Hosting
      • discuss.answer
        • 3749
        • 24,544 Posts
        OK, I have it. I've left in the debugging code so you can verify that it works, but you can remove it. It works in OnBeforeDocFormSave. It does *not* work in OnDocFormSave, where the TVs are no longer set. Change the $tvId and $tvName variables to match the ID of the TV. Be sure the $tvName variable starts with 'tv'.

        <?php
        if (!function_exists("my_debug")) {
            function my_debug($message, $clear = false) {
                global $modx;
                /* @var $chunk modChunk */
                $content = '';
        
                $chunk = $modx->getObject('modChunk', array('name' => 'debug'));
                if (!$chunk) {
                    $chunk = $modx->newObject('modChunk', array('name' => 'debug'));
                    $chunk->setContent('');
                    $chunk->save();
                    $chunk = $modx->getObject('modChunk', array('name' => 'debug'));
                } else {
                    if ($clear) {
                        $content = '';
                    } else {
                        $content = $chunk->getContent();
                    }
                }
                $content .= $message . "\n";
                $chunk->setContent($content);
                $chunk->save();
            }
        }
        
        my_debug('IN PLUGIN', true);
        $tvName = 'tv4208';
        $tvId = 4208;
        if (isset($scriptProperties['data']['tvs'])) {
            my_debug('OLD: ' . $resource->getTVValue($tvId));
            my_debug('NEW: ' . $scriptProperties['data'][$tvName]);
            if (isset($scriptProperties['data'][$tvName]) &&
                ($scriptProperties['data'][$tvName] !== $resource->getTVValue($tvId))){
                my_debug('CHANGED');
            } else {
                my_debug('NOT CHANGED');
            }
        }


        Note that things get a little crazy with @INHERIT TVs. If the TV value is changed in an ancestor, the plugin will report that the TV has changed when you save the ancestor, and *again* when you next save each child. Worse yet, if you blank out the TV value in a child when it's already set to the inherited value, the plugin will conclude that the TV value has changed when it really hasn't. I would not recommend using this technique with @INHERIT TVs. I didn't check it with other @ bindings, but they could be a problem as well.

        Also, if the TV is rendered for output (e.g., an Image TV), it will be perceived as changed every time whether it is or not, since getTVValue() gets the rendered output and that's not what's stored in the $scriptProperties array. I think you could code your way around that, but it would be *very* tricky. I'll see if I can come up with something that works.
          Did I help you? Buy me a beer
          Get my Book: MODX:The Official Guide
          MODX info for everyone: http://bobsguides.com/modx.html
          My MODX Extras
          Bob's Guides is now hosted at A2 MODX Hosting
          • 6949 ☆ A M B ☆
          • 19 Posts
          Hey Bob, that looks great! Will give it a try first thing tomorrow AM. I wish my work caused me to write more plugins -- they're so fun.

          I'm doing this specifically with a radio TV, so it probably doesn't have to render.

          Thanks again!

          Scott
            • 3749
            • 24,544 Posts
            This version should be more reliable and will work whether the TVs need to be rendered or not, but I think still not with @ bindings and definitely not with @INHERIT TVs.

            <?php
            if (!function_exists("my_debug")) {
                function my_debug($message, $clear = false) {
                    global $modx;
                    /* @var $chunk modChunk */
                    $content = '';
            
                    $chunk = $modx->getObject('modChunk', array('name' => 'debug'));
                    if (!$chunk) {
                        $chunk = $modx->newObject('modChunk', array('name' => 'debug'));
                        $chunk->setContent('');
                        $chunk->save();
                        $chunk = $modx->getObject('modChunk', array('name' => 'debug'));
                    } else {
                        if ($clear) {
                            $content = '';
                        } else {
                            $content = $chunk->getContent();
                        }
                    }
                    $content .= $message . "\n";
                    $chunk->setContent($content);
                    $chunk->save();
                }
            }
            
            my_debug('IN PLUGIN', true);
            $tvName = 'tv4208';
            $tvId = 4208;
            $newVal = null;
            $oldVal = null;
            $resourceId = $resource->get('id');
            
            /* get new raw value of the TV */
            if (isset($scriptProperties['data']['tvs'])) {
                if (isset($scriptProperties['data'][$tvName])) {
                    $newVal = $scriptProperties['data'][$tvName];
                }
            /* get raw old value of the TV */
            $tvr = $modx->getObject('modTemplateVarResource',
                array('tmplvarid' => $tvId, 'contentid' => $resourceId));
                if ($tvr) {
                    $oldVal = $tvr->get('value');
                } else {
                    $tv = $modx->getObject('modTemplateVar', $tvId);
                    if ($tv) {
                        $oldVal = $tv->get('default_text');
                    }
                }
            
                my_debug('OLD: ' . $oldVal);
                my_debug('NEW: ' . $newVal);
                if ($newVal !== $oldVal){
                    my_debug('CHANGED');
                } else {
                    my_debug('NOT CHANGED');
                }
            }


            One quirk. If the TV has a default value and is already set to that value and the user saves it blank (which sets it to the default value), it will be reported as changed though it really hasn't been. This shouldn't happen very often, though. [ed. note: BobRay last edited this post 13 years, 1 month ago.]
              Did I help you? Buy me a beer
              Get my Book: MODX:The Official Guide
              MODX info for everyone: http://bobsguides.com/modx.html
              My MODX Extras
              Bob's Guides is now hosted at A2 MODX Hosting
            • discuss.answer
              • 3749
              • 24,544 Posts
              OK, one more time. The version above has trouble in certain situations where the TV has a default value. This should solve that and will be faster as well. It also solves the problem of the user saving a blank TV that was already set to its default value. It still won't work with @INHERIT TVs, but may work with other bindings.

              <?php
              if (!function_exists("my_debug")) {
                  function my_debug($message, $clear = false) {
                      global $modx;
                      /* @var $chunk modChunk */
                      $content = '';
              
                      $chunk = $modx->getObject('modChunk', array('name' => 'debug'));
                      if (!$chunk) {
                          $chunk = $modx->newObject('modChunk', array('name' => 'debug'));
                          $chunk->setContent('');
                          $chunk->save();
                          $chunk = $modx->getObject('modChunk', array('name' => 'debug'));
                      } else {
                          if ($clear) {
                              $content = '';
                          } else {
                              $content = $chunk->getContent();
                          }
                      }
                      $content .= $message . "\n";
                      $chunk->setContent($content);
                      $chunk->save();
                  }
              }
              
              my_debug('IN PLUGIN', true);
              $tvId = 4208;
              $tvName = 'tv' . $tvId;
              
              $newVal = null;
              $oldVal = null;
              
              /** @var $modx modX */
              /* get new raw value of the TV */
              if (isset($scriptProperties['data']['tvs'])) {
                  $resourceId = $resource->get('id');
              
                  if (isset($scriptProperties['data'][$tvName])) {
                      $tv = $modx->getObject('modTemplateVar', $tvId);
                      if (!$tv) {
                          $modx->log(modx::LOG_LEVEL_ERROR, 'Could not find TV with ID: ' . $tvId);
                          return;
                      }
                      $default = $tv->get('default_text');
                      $newVal = $scriptProperties['data'][$tvName];
                      if (empty($newVal) && (! is_numeric($newVal))) {
                          $newVal = $default;
                      }
                  } else { /* Nothing to check */
                      return;
                  }
                  /* get raw old value of the TV */
              
                  $tvr = $modx->getObject('modTemplateVarResource',
                      array('tmplvarid' => $tvId, 'contentid' => $resourceId));
                  if ($tvr) {
                      $oldVal = $tvr->get('value');
                  }
                  if (!$tvr || (empty($oldVal) && (!is_numeric($oldVal)))) {
                      $oldVal = $default;
                  }
              
                  my_debug('OLD: ' . $oldVal);
                  my_debug('NEW: ' . $newVal);
                  if ($newVal !== $oldVal){
                      my_debug('CHANGED');
                  } else {
                      my_debug('NOT CHANGED');
                  }
              }
              [ed. note: BobRay last edited this post 13 years ago.]
                Did I help you? Buy me a beer
                Get my Book: MODX:The Official Guide
                MODX info for everyone: http://bobsguides.com/modx.html
                My MODX Extras
                Bob's Guides is now hosted at A2 MODX Hosting
                • 6949 ☆ A M B ☆
                • 19 Posts
                For the curious, I might make this change to Bob's code on line 28

                $tvId = 4208;
                $tvName = 'tv' . $tvId;


                Thanks again Bob, this works great!!
                  • 3749
                  • 24,544 Posts
                  I might have made the same change if I hadn't been so sleepy. wink
                    Did I help you? Buy me a beer
                    Get my Book: MODX:The Official Guide
                    MODX info for everyone: http://bobsguides.com/modx.html
                    My MODX Extras
                    Bob's Guides is now hosted at A2 MODX Hosting