API Docs for: WebTemplate API v2.0
Show:

File: /data/www/webtemplate/wtv2/codedoc/wtNode.php

<?php
/**
 *  WebTemplate Core
 *
 *  @version 2.0
 *  @module WebTemplate Core
 */

/**
 *  The base class representing a node in the WebTemplate database
 *
 *  @class WTNode
 */

class WTNode 
{
  var $m_guid;
  var $m_nodeIsHolderForGuid;
  var $m_createdByGuid;
  var $m_luid;
  var $m_typeGuid;
  var $m_name;
  var $m_typeName;
  var $m_attributes;
  var $m_dirty;
  var $m_parentGuid;

  /**
   *  Create a node<br/>
   *  Used internally, to create a node, use WTNode::createChild instead
   *
   *  @method create
   *  @static
   *  @private
   *  @param {int} parentGuid  The guid of the parent node
   *  @param {String} typeName The name of the type of node to create
   *  @param {Array} attributes The attributes of the node to create
   *  @return {WTNode} The object for the node created
   */
  public static function create($parentGuid, $typeName, $attributes)
  {
/*    $parentNode = $GLOBALS["WT"]->getNode($parentGuid);
    if($parentNode == NULL) {
      return NULL;
    }

    if(!$parentNode->userHasPermission("write")) {
      return NULL;
    }*/

    $typeName = trim($typeName);
    $typeGuid = 0;
    $nodeNamingRule = "";

    if($typeName != "" && $typeName != "wtNode") {
      $sql = "SELECT
                __guid, `Node Naming Rule`
              FROM
                wtType
              WHERE
                `Type Name` = '" . mysql_escape_string($typeName) . "'
                AND __active <> 0";

      $query = wtmysqlquery($sql);
      if($row = mysql_fetch_row($query)) {
        $typeGuid = $row[0];
        $nodeNamingRule = $row[1];
      } else {
        return NULL;
      }
    }

    if($typeName == "wtNode") {
      $nodeNamingRule = "[wt:Node Name]";
    }

    $nodeName = "";

    $permissions = Array();
    if($parentGuid != 0) {
      // get the permissions of the parent
      $sql = "SELECT
                __allList, __allRead, __allWrite, __groupList, __groupRead, __groupWrite, __moderationChainGuid
              FROM
                wtNode
              WHERE
                __guid = {$parentGuid}";
      $query = wtmysqlquery($sql);
      $permissions = mysql_fetch_assoc($query);
    } else {
      $permissions = Array("__allList" => 1, "__allRead" => 1, "__allWrite" => 0, "__groupList" => 0, "__groupRead" => 0, "__groupWrite" => 0, "__moderationChainGuid" => 0);    
    }

    $position = 0;
    $sql = "SELECT
              MAX(__position)
            FROM
              wtNode
            WHERE
              __parentGuid = {$parentGuid}
              AND __deleted = 0";

    if($GLOBALS["WTSITEID"] == 11380) {
      $sql = "SELECT MAX(__position) FROM wtNode";
    }
    $query = wtmysqlquery($sql);
    if($row = mysql_fetch_row($query)) {
      $position = $row[0];
    }
    $position++;

    $sql = "INSERT INTO
              wtNode
            SET
              __typeGuid = $typeGuid,
              __name = '" . mysql_escape_string($nodeName) . "',
              __created = NOW(),
              __createdByGuid = {$GLOBALS["WT"]->m_contactGuid},
              __parentGuid = {$parentGuid},
              __allList = {$permissions["__allList"]},
              __allRead = {$permissions["__allRead"]},
              __allWrite = {$permissions["__allWrite"]},
              __groupList = {$permissions["__groupList"]},
              __groupRead = {$permissions["__groupRead"]},
              __groupWrite = {$permissions["__groupWrite"]},
              __moderationChainGuid = {$permissions["__moderationChainGuid"]},
              __position = $position";

    if(!wtmysqlquery($sql)) {
      print mysql_error();
      return NULL;
    }

    $guid = mysql_insert_id();

    if($attributes != NULL) {
      $attributes["__guid"] = $guid;
      $nodeName = WTTemplate::compileAndEvaluate($nodeNamingRule, $attributes);
    }

    if($nodeName == "") {
      $nodeName = $typeName . " Node";
    }

    $uri = trim(strtolower($nodeName));
    $uri = preg_replace('/[^a-z0-9]+/','-',$uri);



    $sql = "UPDATE
              wtNode
            SET
              __nodeIsHolderForGuid = $guid,
              __name = '" . mysql_escape_string($nodeName) . "',
              __uri = '" . mysql_escape_string($uri) . "'
            WHERE
              __guid = $guid";
    if(!wtmysqlquery($sql)) {
      print mysql_error();
    }

    $item = $GLOBALS["WT"]->getNode($guid);

    if($typeName != "wtNode") {

      // set defaults if necessary
      $sql = "SELECT
                `Attribute Name`, `Attribute Default Value`
              FROM  
                wtAttribute, wtNode
              WHERE
                wtAttribute.__guid = wtNode.__guid
                AND typeGuid = $typeGuid
                AND __deleted = 0";
      $query = wtmysqlquery($sql);
      while($row = mysql_fetch_row($query)) {

        if($row[1] != "" 
           && (!array_key_exists($row[0], $attributes)) 
           && (!array_key_exists($row[0] . ' ID', $attributes) )) {

          $attributes[$row[0]] = WTTemplate::compileAndEvaluate($row[1], Array());
        }
      }
      $item->setAttributes($attributes);

     /* $attributes = $item->getAttributes();

      $attributes["__guid"] = $guid;
      $nodeName = WTTemplate::compileAndEvaluate($nodeNamingRule, $attributes);
      $sql = "UPDATE
                wtNode
              SET
                __name = '" . mysql_escape_string($nodeName) . "'
              WHERE
                __guid = $guid";
      wtmysqlquery($sql);
      */
/*
      $sql = "INSERT INTO
                `$typeName`
              SET
                __guid = $guid,
                __created = NOW()
              ";

      if(!wtmysqlquery($sql)) {
        print mysql_error();
        return NULL;
      }

      $luid = mysql_insert_id();

      // need to set defaults..
      $sql = "UPDATE
                wtNode
              SET
                __luid = $luid
              WHERE
                __guid = $guid";

      if(!wtmysqlquery($sql)) {
        print "ERROR in $sql\n";
        print mysql_error();
        return NULL;
      }
*/
    }

/*

    if($typeGuid != 0 && $attributes != NULL) {

      $item->setAttributes($attributes);
    }
*/

    $item->setNodeParents();
    return $item;
  }

  /**
   *  Hide a node, the node will only be accessible through WebTemplate::getNode
   *
   *  @method setHidden
   *  @param {boolean} [hidden=true] Set to true to hide the node
   */

  function setHidden($hidden = 1) {
    if($hidden) {
      $hidden = 1;
    } else {
      $hidden = 0;
    }
    $sql = "UPDATE
              wtNode
            SET
              __hidden = $hidden
            WHERE
              __guid = {$this->m_guid}";
    wtmysqlquery($sql);
    print mysql_error();
  
  }

  /**
   *  This function will be called whenever a node is linked to a parent<br/>
   *  It can be overridden by subclasses to provide custom functionality
   *
   *  @method linkedToParent
   *  @param {Object} parentNode The parent node this node is being linked to
   */
  function linkedToParent($parentNode) {
  }

  /**
   *  This function will be called whenever a node is unlinked from a parent<br/>
   *  It can be overridden by subclasses to provide custom functionality
   *
   *  @method unlinkedFromParent
   *  @param {Object} parentNode The parent node this node is being unlinked from
   */

  function unlinkedFromParent($parentNode) {
  }

  
  function getURI($absolute = false, $latest = false) {
    $uriPrefix = "";


/*
    if($GLOBALS["WTLANGUAGEID"] != 0) {
      $uriPrefix = "fr/";
    }
*/
    $languageID = $this->getLanguageID();
    if($languageID != 0) {
      $sql = "SELECT
                __translationOfGuid
              FROM
                wtNode 
              WHERE
                __guid = " . $this->m_guid;
      $query = mysql_query($sql);
      if($row = mysql_fetch_row($query)) {
        $guid = $row[0];
        $node = $GLOBALS["WT"]->getNode($guid);
        return $node->getURI();
      } 
    }

    $GLOBALS["WT"]->initURICache();

    $uri = "";
    $nodeGuid = $this->m_guid;
    while($nodeGuid != 0) {

      if(array_key_exists($nodeGuid, $GLOBALS["WTURICACHE"])) {
        if($GLOBALS["WTURICACHE"][$nodeGuid] != "" AND $uri != "") {
          $uri = '/' . $uri;
        }
        return $uriPrefix . $GLOBALS["WTURICACHE"][$nodeGuid] . $uri;
      }

      $sql = "SELECT
                __uri,
                __parentGuid
              FROM
                wtNode
              WHERE
                __guid = " . $nodeGuid;
      $query = mysql_query($sql);
      if($row = mysql_fetch_row($query)) {
        if($uri != "") {
          $uri = '/' . $uri;
        }
        $uri = $row[0] . $uri;
        $nodeGuid = $row[1];
      }               
    }
    $GLOBALS["WTURICACHE"][$this->m_guid] = $uri;

    return $uriPrefix . $uri;
  }



  /**
   *  Test if the node is an ancestor of another node
   *
   *  @method isAncestorOf
   *  @param {String} child The guid or path of the child node to test
   *  @return {boolean} Returns true if the node is an ancestor of the child node
   */
  function isAncestorOf($child) {
    $childNode = $GLOBALS["WT"]->getNode($child);
    if($childNode) {
      $ancestors = $childNode->getAncestors();
      return in_array($this->m_guid, $ancestors);
    }
    return false;
  }

  /**
   *  Test is a node is a descendant of another node
   *
   *  @method isDescendantOf
   *  @param {String} parent The guid or path of the parent node to test
   *  return {boolean} Returns true if the node is a descendant of the parent node
   */
  function isDescendantOf($parent) {
    $parentCheckNode = $GLOBALS["WT"]->getNode($parent);
    if($parentCheckNode == NULL) {
      return false;
    } 
    if($this->m_parentGuid == 0) {
      return false;
    }
    $parentNode = $GLOBALS["WT"]->getNode($this->m_parentGuid);
    while($parentNode != NULL) {
      if($parentCheckNode->m_guid == $parentNode->m_guid) {
        return true;
      }
      if($parentNode->m_parentGuid == 0) {
        return false;
      }
      $parentNode = $GLOBALS["WT"]->getNode($parentNode->m_parentGuid);
    }
    return false;
  }

  /**
   *  Change the parent of a node
   *
   *  @method setParent
   *  @param {String} parent The guid or path of the new parent node
   */
  function setParent($parent) {
    $parentNode = $GLOBALS["WT"]->getNode($parent);
    if($parentNode != NULL) {
      $sql = "UPDATE
                wtNode
              SET
                __parentGuid = {$parentNode->m_guid}
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }
      $this->setNodeParents();
    }
  }


  /**
   *  Internal function to allow quick searching of all descendants of a node
   *
   *  @method setNodeParents
   *  @private
   *
   */
  function setNodeParents() {
    $types = Array();
    $types[] = "Page";
    $types[] = "Contact";
    $types[] = "Product";
    $types[] = "wtFile";
    if(!in_array($this->m_typeName, $types)) {
      return;
    }
   
    $nodeGuids = Array();
    $nodeGuids[] = $this->m_guid;
    $parents = Array();
    $sql = "SELECT 
              __guid 
            FROM
              wtNode
            WHERE
              __nodeIsHolderForGuid = {$this->m_guid}
              AND __deleted = 0";
    $query = wtmysqlquery($sql);
    while($row = mysql_fetch_row($query)) {
      $nodeGuids[] = $row[0];
    } 

    foreach($nodeGuids as $guid) {
      while($guid != 0) {
        $sql = "SELECT
                  __parentGuid
                FROM
                  wtNode
                WHERE
                  __guid = $guid";
        $query = wtmysqlquery($sql);
        if($row = mysql_fetch_row($query)) {
          $guid = $row[0];
          if($guid != 0) {
            $parents[] = $guid;
          }
        } else {
          break;
        }
      }
    }

    $parentList = implode(",", $parents);
    $sql = "DELETE FROM
              tblNodeChildren
            WHERE
              childNodeGuid = {$this->m_guid}
              AND parentNodeGuid NOT IN ($parentList)";
    wtmysqlquery($sql);
    for($i = 0; $i < count($parents); $i++) {
      $sql = "SELECT
                COUNT(*)
              FROM
                tblNodeChildren
              WHERE
                childNodeGuid = {$this->m_guid}
                AND parentNodeGuid = {$parents[$i]}";
      $query = wtmysqlquery($sql);
      $row = mysql_fetch_row($query);
      if($row[0] == 0) {


        $sql = "INSERT INTO
                  tblNodeChildren (parentNodeGuid, childNodeGuid)
                VALUES
                  ({$parents[$i]}, {$this->m_guid})";

        if(!wtmysqlquery($sql)) {
          print $sql;
          print mysql_error();
        }
      }
    }
              
  }

  /**
   *  Get the ID of the language for this node
   *
   *  @method getLanguageID
   *  @return {int} The ID for the language of this node
   */

  function getLanguageID() {
    $sql = "SELECT
              __languageID
            FROM
              wtNode
            WHERE
              __guid = {$this->m_guid}";
    $query = mysql_query($sql);
    if($row = mysql_fetch_row($query)) {
      return $row[0];
    } 
    return 0;
  }

  /**
   *  Get the translation node for this node
   *
   *  @method getTranslationNode
   *  @param {int} languageID The id of the language to get the translation for
   *  @param {boolean} [createIfNotExist=false] Set to true to create a translation node if it doesn't exist
   *  @return {Object} Returns the node containing the translation, or NULL if there is no node
   */
  function getTranslationNode($languageID, $createIfNotExist = false) {

    if($this->getLanguageID() == $languageID) {
      return $this;
    }

    if($this->getLanguageID() != 0) {
      $sql = "SELECT
                __translationOfGuid
              FROM
                wtNode
              WHERE
                __guid = {$this->m_guid}";
      $query = mysql_query($sql);
      if($row = mysql_fetch_row($query)) {
        $translationOf = $row[0];
        if($translationOf != 0) {
          $originalNode = $GLOBALS["WT"]->getNode($translationOf);
          return $originalNode->getTranslationNode($languageID, $createIfNotExist);
        }
      }  
    }

    if(!$languageID) {
      $languageID = 0;
    }
    $translatedNodeGuid = 0;
    $sql = "SELECT
              __guid 
            FROM 
              wtNode
            WHERE
              __languageID = $languageID
              AND __translationOfGuid = {$this->m_guid}
              AND __deleted = 0";
    $query = wtmysqlquery($sql);
    print mysql_error();
    if($row = mysql_fetch_row($query)) {
      $translatedNodeGuid = $row[0];
    }
    if($translatedNodeGuid != 0) {
      return $GLOBALS["WT"]->getNode($translatedNodeGuid);
    } else {
      if($createIfNotExist) {
        return $this->createTranslationNode($languageID);
      }
      return NULL;
    }
  }


  /**
   *  Create a node containing a translation of this node
   *
   *  @method createTranslationNode
   *  @param {int} languageID The guid for the language
   *  @return {Object} The translation node object
   */
  function createTranslationNode($languageID) {
    $typeName = $this->m_typeName;
    $languageNode = $GLOBALS["WT"]->getNode($languageID);
    /*
    $languageNode = $GLOBALS["WT"]->getNode("/Translations/l$languageID");
    if(!$languageNode) {
      $translationsNode = $GLOBALS["WT"]->getNode("/Translations");
      $languageNode = $translationsNode->createChild("wtNode", Array("Node Name" => "l$languageID"));
    }
    */

    $translationNode = WTNode::create($languageNode->m_guid, $typeName, Array());
    $sql = "UPDATE
              wtNode
            SET
              __languageID = $languageID,
              __translationOfGuid = {$this->m_guid}
            WHERE
              __guid = {$translationNode->m_guid}";
    mysql_query($sql);
    print mysql_error();

    return $translationNode;
  }

  public static function setNodeUse($usedByNodeGuid, $usedByAttributeGuid, $nodeGuids) 
  {
    $fileTypeNode = $GLOBALS["WT"]->getNode("/Config/Node Types/wtFile");
    $nodeGuids = trim($nodeGuids);
    $nodesql = "";
    if($nodeGuids != "") {
      $nodesql = " AND nodeGuid NOT IN ($nodeGuids) ";
    }

    $fileTypeGuid = $fileTypeNode->m_guid;
    $changedFileNodes = Array();
    $sql = "SELECT
              __guid
            FROM
              wtNode, tblNodeUse
            WHERE
              wtNode.__typeGuid = $fileTypeGuid
              AND wtNode.__guid = tblNodeUse.nodeGuid
              AND usedByNodeGuid = $usedByNodeGuid
              AND usedByAttributeGuid = $usedByAttributeGuid
              $nodesql";
    $query = wtmysqlquery($sql);

if(!$query) {

print $sql;
}

print mysql_error();

    while($row = mysql_fetch_row($query)) {
      $changedFileNodes[] = $row[0];
    }

    $sql = "DELETE FROM
              tblNodeUse
            WHERE
              usedByNodeGuid = $usedByNodeGuid
              AND usedByAttributeGuid = $usedByAttributeGuid
              $nodesql";
    if(!wtmysqlquery($sql)) {
      //print $sql;
      print mysql_error();
    }

    $nodeArray = explode(",", $nodeGuids);
    foreach($nodeArray as $nodeGuid) {
      if($nodeGuid != "") {
        $sql = "SELECT 
                  COUNT(*) 
                FROM
                  tblNodeUse
                WHERE
                  nodeGuid = $nodeGuid
                  AND usedByAttributeGuid = $usedByAttributeGuid
                  AND usedByNodeGuid = $usedByNodeGuid";
        $query = wtmysqlquery($sql);
        $row = mysql_fetch_row($query);
        if($row[0] == 0) {
          $nodeTypeGuid = 0;
          $sql = "SELECT
                    __typeGuid 
                  FROM
                    wtNode
                  WHERE
                    __guid = $nodeGuid";

//print $sql;
          $query = wtmysqlquery($sql);
          if($row = mysql_fetch_array($query)) {
            $nodeTypeGuid = $row[0];
          }

          if($fileTypeGuid == $nodeTypeGuid) {
            $changedFileNodes[] = $nodeGuid;
          }

          $sql = "INSERT INTO 
                    tblNodeUse (usedByNodeGuid, usedByAttributeGuid, nodeGuid)
                  VALUES
                    ($usedByNodeGuid, $usedByAttributeGuid, $nodeGuid)";

          if(!wtmysqlquery($sql)) {
            //print $sql; 
            print mysql_error();
          }
        }
      }
    } 

//print "changed file nodes $changedFileNodes<br>";   
    foreach($changedFileNodes as $nodeGuid) {
      $useCount = 0;
      $sql = "SELECT
                COUNT(*) 
              FROM 
                tblNodeUse
              WHERE
                nodeGuid = $nodeGuid";
      $query = wtmysqlquery($sql);
      if($row = mysql_fetch_row($query)) {
        $useCount = $row[0];
      }
      $sql = "UPDATE
                wtFile
              SET 
                `Times Used` = $useCount
              WHERE
                __guid = $nodeGuid";
      wtmysqlquery($sql);
    }
  }

  function getNodeUse() {
    $uses = Array();
    $sql = "SELECT
              usedByNodeGuid, usedByAttributeGuid
            FROM 
              tblNodeUse
            WHERE
              nodeGuid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    while($row = mysql_fetch_row($query)) {
      $uses[$row[0]] = $row[1];
    }

    return $uses;
  }


  /**
   *  Delete a node along with child nodes. Delete will fail if the node is being used by another node
   *
   *  @method deleteNode
   *  @param {boolean} [forceDelete=false] If set the true, the node will be deleted even if it is in use
   */
  function deleteNode($forceDelete = false) 
  {
    if($this->m_guid == 0) {
      return false;
    }
    $moderationChainGuid = 0;
    if($GLOBALS["WT"]->getModerationEnabled()) {
      $sql = "SELECT
                __moderationChainGuid
              FROM
                wtNode
              WHERE
                __guid = {$this->m_guid}";
      $query = wtmysqlquery($sql);
      if($row = mysql_fetch_row($query)) {
        $moderationChainGuid = $row[0];
      }
    }

    // is it the moderator or the global admin making the changes?
    if($moderationChainGuid != 0) {
      $currentUser = $GLOBALS["WT"]->getCurrentUser();

      if($currentUser->isMemberOf($moderationChainGuid) || $GLOBALS["WT"]->m_contactIsAdministrator) {
        $moderationChainGuid = 0;
      }

    }



    $this->logEvent(3, $moderationChainGuid, "");

    if($moderationChainGuid != 0) {
      // don't actually do the delete as it needs to be moderated
      return false;
    }



/*
    $node = $this;
    $typeName = $this->m_typeName;
    while($typeName != 'Page') {

      $parentGuid = $node->m_parentGuid;

      if($parentGuid == 0) {
        break;
      }
      $node = $GLOBALS["WT"]->getNode($parentGuid);
      $typeName = $node->m_typeName;
    }

    if($typeName == 'Page') {
      $node->logEvent('Node Deleted', "'" . $this->m_name . "' Deleted");
    }

*/


    if(!$forceDelete) {
    // TODO: check if the node is used as a file, image or as an option
    $sql = "SELECT
              COUNT(*)
            FROM
              tblNodeUse 
            WHERE
              nodeGuid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    $row = mysql_fetch_row($query);
    if($row[0] > 0) {
      // cant delete this node, as its being used!!
      //print "CANT DELETE NODE IN USE FOR OPTIONS!!";
      return false;
    }
    }

    $sql = "DELETE FROM
              tblNodeChildren
            WHERE
              childNodeGuid = {$this->m_guid}";
    wtmysqlquery($sql);
              
           
    // delete the children 
    $sql = "SELECT 
              __guid
            FROM
              wtNode
            WHERE
              __parentGuid = {$this->m_guid}
              AND __deleted = 0";
    $query = wtmysqlquery($sql);
    while($row = mysql_fetch_row($query)) {
      if((int)$row[0] != 0) {
        $childNode = $GLOBALS["WT"]->getNode($row[0]);
        if($childNode != NULL) {
          $childNode->deleteNode();
        }
      }
    }

    //TODO delete from actual table

    // if this is a holder node, need to tell the original node it is unlinked
    $sql = "SELECT
              __nodeIsHolderForGuid,
              __parentGuid
            FROM
              wtNode
            WHERE
              __guid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    if($row = mysql_fetch_row($query)) {
      if($row[0] != $this->m_guid) {
        $originalNode = $GLOBALS["WT"]->getNode($row[0]);
        $parentNode = $GLOBALS["WT"]->getNode($row[1]);
        if($originalNode) {
          $originalNode->unlinkedFromParent($parentNode);
        }
      }
    }

    $sql = "UPDATE 
              wtNode
            SET
              __deleted = 1
            WHERE
              __guid = {$this->m_guid}
              OR __nodeIsHolderForGuid = {$this->m_guid}";
    if(!wtmysqlquery($sql)) {
      print $sql;
      print mysql_error();
    }       


    // update times used for files
    $fileTypeNode = $GLOBALS["WT"]->getNode("/Config/Node Types/wtFile");
    $fileTypeGuid = $fileTypeNode->m_guid;
    $changedFileNodes = Array();
    $sql = "SELECT 
              __guid          
            FROM 
              wtNode, tblNodeUse
            WHERE
              tblNodeUse.nodeGuid = wtNode.__guid
              AND wtNode.__typeGuid = $fileTypeGuid
              AND usedByNodeGuid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    while($row = mysql_fetch_row($query)) {
      $changedFileNodes[] = $row[0];
    }

    $sql = "DELETE FROM
              tblNodeUse
            WHERE
              usedByNodeGuid = {$this->m_guid}";
    if(!wtmysqlquery($sql)) {
      print $sql;
      print mysql_error();
    }

    foreach($changedFileNodes as $nodeGuid) {
      $useCount = 0;
      $sql = "SELECT
                COUNT(*) 
              FROM 
                tblNodeUse
              WHERE
                nodeGuid = $nodeGuid";
      $query = wtmysqlquery($sql);
      if($row = mysql_fetch_row($query)) {
        $useCount = $row[0];
      }
      $sql = "UPDATE
                wtFile
              SET 
                `Times Used` = $useCount
              WHERE
                __guid = $nodeGuid";
      wtmysqlquery($sql);
    }

    return true;

  }


  /**
   *  Get the parent node
   *
   *  @method getParent
   *  @return {Object} The parent node's object
   */
  function getParent() {
    return $GLOBALS["WT"]->getNode($this->m_parentGuid);  
  }


  /**
   *  Get all the ancestors of a node as their guid's in an array
   *
   *  @method getAncestors
   *  @param {Array} args Possible keys are "directAncestors", "type", "useCache"
   *  @return {Array} An array of the guid's of the ancestors
   */
  function getAncestors($args = Array()) { //$useCache = true, $guid = 0) {

    $guid = 0;
    if(array_key_exists("guid", $args)) {
      $guid = $args["guid"];
    } 

    $useCache = true;
    if(array_key_exists("useCache", $args)) {
      $useCache = $args["useCache"];
    }

    $directAncestors = false;
    if(array_key_exists("directAncestors", $args)) {
      $directAncestors = $args["directAncestors"];
    }

    $type = "";
    if(array_key_exists("type", $args)) {
      $type = $args["type"];
    }

    if(!array_key_exists("WTANCESTORS", $GLOBALS)) {
      $GLOBALS["WTANCESTORS"] = Array();
    }

    if($useCache && array_key_exists($guid, $GLOBALS["WTANCESTORS"])) {
      return $GLOBALS["WTANCESTORS"][$guid];
    }

    if($guid == 0) {
      $guid = $this->m_guid;
    }

    if($sql == "") {
      if($type != "") {
        $typeGuid = $GLOBALS["WT"]->getGuid("/Config/Node Types/$type");
        $sql = "SELECT
                  wtNode.__parentGuid
                FROM
                  wtNode
                JOIN 
                  wtNode AS wtParentNode ON wtNode.__parentGuid = wtParentNode.__guid
                WHERE
                  wtParentNode.__typeGuid = $typeGuid
                  AND (wtNode.__guid = {$guid}
                  OR wtNode.__nodeIsHolderForGuid = {$guid})
                  AND wtNode.__deleted = 0";
      } else {
        $sql = "SELECT
                  __parentGuid
                FROM
                  wtNode
                WHERE
                  (__guid = {$guid}
                  OR __nodeIsHolderForGuid = {$guid})
                  AND __deleted = 0";
      }
    }

    $parents = Array();
    $query = wtmysqlquery($sql);
    while($row = mysql_fetch_row($query)) {
      if($row[0] != 0) {
        $parents[] = $row[0];
      }
    }

    $ancestors = Array();
    $ancestors = array_merge($ancestors, $parents);

    if(!$directAncestors) {
      foreach($parents as $parentGuid) {
        $result = $this->getAncestors(Array("useCache" => true, "guid" => $parentGuid));
        $ancestors = array_merge($ancestors, $result);
      }
    }

    $GLOBALS["WTANCESTORS"][$guid] = $ancestors;

    return $ancestors;
 
  }


  /**
   *  Get the parents of the node as an array of guids<br/>
   *  A node may have more than one parent if it has been linked
   *
   *  @method getParents
   *  @param {String} [type=""] Limit the parents to a certain type
   *  @return {Array} An array of the nodes parents
   */
  function getParents($type = "") {
    $typeSql = "";
    if($type != "") {
      $sql = "SELECT
                __parentGuid
              FROM 
                wtNode, `$type`
              WHERE
                (wtNode.__guid = {$this->m_guid}
                 OR __nodeIsHolderForGuid = {$this->m_guid})
                 AND `$type`.__guid = wtNode.__parentGuid";
    }
    $parents = Array();
    if($sql == "") {
      $sql = "SELECT
                __parentGuid
              FROM
                wtNode
              WHERE
                __guid = {$this->m_guid}
                OR __nodeIsHolderForGuid = {$this->m_guid}";
    }

    $query = wtmysqlquery($sql);
    while($row = mysql_fetch_row($query)) {
      $parents[] = $row[0];
    }
    return $parents;
  }
  
  function WTNode($guid) 
  {
    $this->m_guid = $guid;
    $this->m_typeGuid = 0;
    $this->m_typeName = "wtNode";
    $this->m_attributes = Array();
    $this->m_dirty = true;
    $this->m_parentGuid = 0;
    $this->m_nodeIsHolderForGuid = -1;
    $this->m_createdByGuid = 0;
    $this->m_languageID = 0;
   
    $sql = "SELECT 
              wtNode.*,
              wtType.`Type Name`
            FROM 
              wtNode
            LEFT JOIN
              wtType
            ON
              wtNode.__typeGuid = wtType.__guid
            WHERE
              wtNode.__guid = $this->m_guid";

    $query = wtmysqlquery($sql);
    if($row = mysql_fetch_array($query)) {
      $this->m_luid = $row["__luid"];
      $this->m_name = $row["__name"];
      $this->m_typeGuid = $row["__typeGuid"];
      $this->m_createdByGuid = $row["__createdByGuid"];
      if($row["Type Name"] != NULL) {
        $this->m_typeName = $row["Type Name"];
      } else {
        $this->m_typeName = "wtNode";
      }
      $this->m_parentGuid = $row["__parentGuid"];
      $this->m_nodeIsHolderForGuid = $row["__nodeIsHolderForGuid"];
      $this->m_languageID = $row["__languageID"];
    }
  }


  /**
   *  Set the moderation chain for the node
   *
   *  @method setModerationChain
   *  @param {int} moderationChain The guid, path, or object for the moderation chain
   */
  function setModerationChain($moderationChain) 
  {
    if(is_object($moderationChain)) {
      $moderationChainNode = $moderationChain;
    } else {
      $moderationChainNode = $GLOBALS["WT"]->getNode($moderationChain);
    }
    if($moderationChainNode != NULL) {
      $sql = "UPDATE
                wtNode
              SET
                __moderationChainGuid = {$moderationChainNode->m_guid}
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }
    }
  }

  /**
   *  Get the guid of the Moderation Chain for the node
   *
   *  @method getModerationChainGuid
   *  @return {int} The guid of the moderation chain for the node (0 if none)
   */
  function getModerationChainGuid() 
  {
    $sql = "SELECT
              __moderationChainGuid
            FROM
              wtNode
            WHERE
              __guid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    if($row = mysql_fetch_array($query)) {
      return $row[0];
    }

    return 0;

  }

  /**
   *  Remove the moderation chain from a node
   *
   *  @method removeModerationChain
   */
  function removeModerationChain() 
  {
    $sql = "UPDATE
              wtNode
            SET
              __moderationChainGuid = 0
            WHERE
              __guid = {$this->m_guid}";
    if(!wtmysqlquery($sql)) {
      print $sql;
      print mysql_error();
    }
  }


  /**
   *  Insert the node above or below another node
   *
   *  @method insert
   *  @param {String} placeNode The node to place the node in relation to (may be guid, path or object)
   *  @param {int} relation 0 for above, 1 for below
   */
  function insert($placeNode, $relation) 
  {
    $nodeGuid = 0;
    if(is_object($placeNode)) {
      $nodeGuid = $placeNode->m_guid;
    } else {
      $nodeGuid = $placeNode;
      if($nodeGuid != 0) {
        $placeNode = $GLOBALS["WT"]->getNode($nodeGuid);
      } else {
        $placeNode = null;
      }
    }

    if($relation == 0) {
      $position = 0;
      $sql = "SELECT
                MAX(__position)
              FROM
                wtNode
              WHERE
                __parentGuid = {$placeNode->m_guid}";
      $query = wtmysqlquery($sql);
      if($row = mysql_fetch_row($query)) {
        $position = $row[0];
      }
      $position++;
      $sql = "UPDATE
                wtNode
              SET
                __parentGuid = {$placeNode->m_guid},
                __position = $position
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print mysql_error();
      }

    } else {
      $newParentGuid = $placeNode->m_parentGuid;
      $newPosition = 1;
      if($nodeGuid != 0) {
        $sql = "SELECT
                  __position
                FROM
                  wtNode
                WHERE
                  __guid = {$nodeGuid}";
        $query = wtmysqlquery($sql);
        if($row = mysql_fetch_row($query)) {
          $newPosition = $row[0];
          if($relation == 1) {
            $newPosition++;
          }
        }
      }

      $sql = "UPDATE
                wtNode
              SET
                __position = __position + 1
              WHERE
                __position >= $newPosition
                AND  __parentGuid = {$newParentGuid}";
      if(!wtmysqlquery($sql)) {
        print mysql_error();
      }
//    print $sql . "\n";


      $sql = "UPDATE
                wtNode
              SET
                __position = $newPosition,
                __parentGuid = $newParentGuid
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print mysql_error();
      }  

      $this->m_parentGuid = $newParentGuid;
    }
//    print $sql . "\n";

  }


  /**
   *  Insert this node after another node, keeping the same parent
   *
   *  @method insertAfter
   *  @param {String} node The node to insert this node after (may be guid, path or object)
   */
  function insertAfter($node) 
  {
    $nodeGuid = 0;
    if(is_object($node)) {
      $nodeGuid = $node->m_guid;
    } else {
      $nodeGuid = $node;
      if($nodeGuid != 0) {
        $node = $GLOBALS["WT"]->getNode($nodeGuid);
      } else {
        $node = null;
      }
    }

    $newPosition = 1;

    if($nodeGuid != 0) {
      $sql = "SELECT
                __position
              FROM 
                wtNode
              WHERE
                __guid = {$nodeGuid}";
      $query = wtmysqlquery($sql);
      if($row = mysql_fetch_row($query)) {
        $newPosition = $row[0] + 1;
      }
    }

    $sql = "UPDATE
              wtNode
            SET
              __position = __position + 1
            WHERE
              __position >= $newPosition
              AND  __parentGuid = {$this->m_parentGuid}";
    if(!wtmysqlquery($sql)) {
      print mysql_error();
    }


    $sql = "UPDATE
              wtNode
            SET
              __position = $newPosition
            WHERE
              __guid = {$this->m_guid}";
    if(!wtmysqlquery($sql)) {
      print mysql_error();
    }
  }

  /**
   *  Move this node to the top of its siblings
   *
   *  @method moveToTop
   *
   */
  function moveToTop() {
    $sql = "SELECT 
              MIN(__position)
            FROM
              wtNode
            WHERE
              __parentGuid = {$this->m_parentGuid}
              AND __deleted = 0";
    $query = wtmysqlquery($sql);
    if($row = mysql_fetch_row($query)) {
      $minPosition = $row[0];
      $sql = "UPDATE
                wtNode
              SET
                __position = __position + 1
              WHERE
                __parentGuid = {$this->m_parentGuid}
                AND __deleted = 0";
      $query = wtmysqlquery($sql);
      print mysql_error();
      $sql = "UPDATE
                wtNode
              SET
                __position = $minPosition
              WHERE
                __guid = {$this->m_guid}";
      wtmysqlquery($sql);
      print mysql_error();  
    }
  }

  /**
   *  Move this node up or down within its siblings
   *
   *  @method move
   *  @param {int} [direction=1] 1 for down, -1 for up
   *  @param {boolean} [moveWithinType=false] Set to true to move in relation to its siblings of the same node type
   */
  function move($direction = 1, $moveWithinType = false) 
  {
    $position = 0;
    $sql = "SELECT
              __position
            FROM
              wtNode
            WHERE
              __guid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    if($row = mysql_fetch_array($query)) {
      $position = $row[0];
    } else {
      print $sql;
      print mysql_error();
    }

    $swapWithPosition = 0;
    $swapWithGuid = 0;
    if($direction == -1) {
      $sql = "SELECT
                __position, __guid
              FROM
                wtNode
              WHERE
                __parentGuid = {$this->m_parentGuid}
                AND __position < $position
                AND __deleted = 0
              ORDER BY
                __position DESC
              LIMIT 1"; 
    } else if($direction == 1) {
      $sql = "SELECT
                __position, __guid
              FROM
                wtNode
              WHERE
                __parentGuid = {$this->m_parentGuid}
                AND __position > $position
                AND __deleted = 0
              ORDER BY
                __position 
              LIMIT 1";
    }
    $query = wtmysqlquery($sql);
    if($row = mysql_fetch_array($query)) {
      $sql = "UPDATE
                wtNode
              SET
                __position = {$row[0]}
              WHERE
                __guid = {$this->m_guid}";
      wtmysqlquery($sql);
      $sql = "UPDATE
                wtNode
              SET
                __position = $position
              WHERE
                __guid = {$row[1]}";
      wtmysqlquery($sql);
    }
  }

  /**
   *  Get the contact who created this node
   *
   *  @method getCreator
   *  @return {Object} The object for the creator contact
   */
  function &getCreator() {
    return $GLOBALS["WT"]->getNode($this->m_createdByGuid);
  }

  /**
   *  Set the creator of the node
   *
   *  @method setCreatedBy {int} creatorGuid The guid of the contact
   *
   */
  function setCreatedBy($creatorGuid) {
    $sql = "UPDATE
              wtNode
            SET
              __createdByGuid = $creatorGuid
            WHERE
              __nodeIsHolderForGuid = " . $this->m_guid;
    wtmysqlquery($sql);
  }

  /**
   *  Get the depth of a node above a path
   *
   *  @method getDepth
   *  @param [stopPath=""] The path to find the depth from
   *  @return {int} The depth of the node
   */
  function getDepth($stopPath = "") 
  {
    $stopNode = NULL;
    if($stopPath != "") {
      $stopNode = $GLOBALS["WT"]->getNode($stopPath);
    }
    $guid = $this->m_guid;
    $count = 0;
    while($guid != 0 && $count < 100) {
      $count++;
      $sql = "SELECT
                __parentGuid, __name
              FROM
                wtNode
              WHERE
                __guid = $guid";
      $query = wtmysqlquery($sql);
      if($row = mysql_fetch_row($query)) {
        $guid = $row[0];
        if($stopNode != NULL && $guid == $stopNode->m_guid) {
          break;
        }
      } else {
        break;
      }
    }
    return $count;
  }

  /**
   *  Return the path to the object as a string<br/>
   *  Optionally stop at a node instead of the root
   *
   *  @method getPath
   *  @param {String} [separator=/] The separator to use to construct the path
   *  @param {String} [template] If set, the template to use to construct each element in the path
   *  @param {String} [stopPath] The node to stop at when constructing the path
   *  @param {bool} [includeSelf=true] Set to true to include the node in the path
   *  @return {String}  The path to the node as a string
   */ 
  function getPath($separator = "/", $template = "", $stopPath = "", $includeSelf = true) 
  {
    $stopNode = NULL;
    if($stopPath != "") {
      $stopNode = $GLOBALS["WT"]->getNode($stopPath);
    }
    $guid = $this->m_guid;
    $path = "";
    $count = 0;
    while($guid != 0 && $count < 100) {
      $count++;
      $sql = "SELECT
                __parentGuid, __name
              FROM
                wtNode
              WHERE
                __guid = $guid";
      $query = wtmysqlquery($sql);
      if($row = mysql_fetch_row($query)) {
        if($includeSelf) {
          if($template == "") {
            $path = $separator . $row[1] . $path;
          } else {
            $node = $GLOBALS["WT"]->getNode($guid);
            $attributes = $node->getAttributes();
            $path = $separator . WTTemplate::compileAndEvaluate($template, $attributes) . $path;
          }
        }
        $includeSelf = true;
        $guid = $row[0];
        if($stopNode != NULL && $guid == $stopNode->m_guid) {
          break;
        }
      } else {
        break;
      }
    }
    return $path;
  }

  /**
   *  Get the type of the node as a string
   *
   *  @method getType
   *  @return {String} The type of the node as a string
   */
  function getType() 
  {
    return $this->m_typeName;
  }


  /**
   *  Get the name of the node
   *
   *  @method getName
   *  @return {String} The name of the node
   */
  function getName() 
  {
    return $this->m_name;
  }

  /**
   *  Set the name of the node
   *
   *  @method setName
   *  @return {String} Set the Name of the node
   */
  function setName($name) 
  {
    if($this->m_name == $name) {
      return;
    }

    $uri = trim(strtolower($name));
    $uri = preg_replace('/[^a-z0-9]+/','-',$uri);

    $sql = "UPDATE
              wtNode
            SET
              __name = '" . mysql_escape_string($name) . "',
              __uri = '" . mysql_escape_string($uri) . "'
            WHERE 
              __guid = {$this->m_guid}
              OR __nodeIsHolderForGuid = {$this->m_guid}";
    if(!wtmysqlquery($sql)) {
      return false;
    }


    // need to update tables that are using this node as an option

/*
    $sql = "SELECT
              attributeGuid, `Attribute Name`, `Type Name`
            FROM
              tblSingleOptionUse, wtAttribute, wtType
            WHERE 
              tblSingleOptionUse.attributeGuid = wtAttribute.__guid
              AND wtAttribute.typeGuid = wtType.__guid
              AND optionParentGuid = {$this->m_parentGuid}";
    $query = wtmysqlquery($sql);
    $guid = $this->m_guid;
    if($this->m_nodeIsHolderForGuid > 0) {
      $guid = $this->m_nodeIsHolderForGuid;
    }
    while($row = mysql_fetch_row($query)) {
      
      $sql = "UPDATE
                `{$row[2]}`
              SET
                `{$row[1]}` = '" . mysql_escape_string($name) . "'
              WHERE
                `{$row[1]} ID` = $guid";
      if(!wtmysqlquery($sql)) { 
        print $sql;
        print mysql_error();
      }
    }
*/

    // update the linked nodes
/*
    $sql = "SELECT
              __guid
            FROM 
              wtNode
            WHERE
              __nodeIsHolderForGuid = {$this->m_guid}
              AND __nodeIsHolderForGuid <> __guid	
              AND __deleted = 0";
    $query = wtmysqlquery($sql);
    while($row = mysql_fetch_row($query)) {
      $holderNode = $GLOBALS["WT"]->getNode($row[0]);
      $holderNode->setName($name);
    }
*/
    $this->m_name = $name;
  }

  /**
   *  Get an attribute of the node
   *
   *  @method getAttribute
   *  @param {String} attributeName The name of the attribute
   *  @param {boolean} [latest=false] Set to true to get the latest version (possibly draft or unapproved version)
   */
  function getAttribute($attributeName, $latest = false) 
  {
    if($this->m_typeGuid == 0) {
      return false;
    }
    if($this->m_dirty) {
      $this->getAttributes($latest);
    }
    if(array_key_exists($attributeName, $this->m_attributes)) {
      return $this->m_attributes[$attributeName];
    }
    return false;
  }

  function getFormValuesAsJSON() {
    $nodeAttributes = Array();
    $query = Array("Node Type" => "wtAttribute", "Path" => $this->m_typeGuid . "/*", "Results Array" => &$nodeAttributes);
    $GLOBALS["WT"]->query($query);
    $data = Array();
    $data["guid"] = $this->m_guid;
    $attributes = $this->getAttributes();
    foreach($nodeAttributes as $nodeAttribute) {
      switch($nodeAttribute["Attribute Type"]) {
        case 'Single Choice Options':
          $value = $attributes[$nodeAttribute["Attribute Name"] . " ID"];
          break;
        case 'Multiple Choice Options':
          $value = $attributes[$nodeAttribute["Attribute Name"] . " IDs"];
          break;
        default:
          $value = $attributes[$nodeAttribute["Attribute Name"]];
          break;
      }
      $data["attr" . $nodeAttribute["__guid"]] = $value;
    }
    print json_encode($data);

  }


  /**
   *  Get the HTML of a form for the node, used by the office
   *
   *  @method getFormHTML
   *  @private
   *  @param {String} typeName The type to get the form for
   *  @param {Array} values Values to use in the form
   *  @param {Array} args Extra arguments to create the form with
   *  @return {String} The HTML for the form
   */
  function getFormHTML($typeName, $values = NULL, $args = NULL)
  {
   
    $browser = $GLOBALS["WT"]->getWTValue("wt.browser"); 
    $html .= '<script type="text/javascript" src="' . $GLOBALS["WTINCLUDEURL"] . 'js/wtForm.js"></script>';
    if(WTConfig::get("Content Manager/CKEditor") == "Yes" || $browser == "chrome") {
      $html .= '<script type="text/javascript" src="' .$GLOBALS["WTCKEDITORURL"] . 'ckeditor.js"></script>';
    } else {
      $html .= '<script type="text/javascript" src="' .$GLOBALS["WTFCKEDITORURL"] . 'fckeditor.js"></script>';
    }
    $html .= '<script type="text/javascript" src="' . $GLOBALS["WTEXTERNALURL"] . 'yui/build/yahoo/yahoo-min.js"></script>';
    $html .= '<script type="text/javascript" src="' . $GLOBALS["WTEXTERNALURL"] . 'yui/build/yahoo-dom-event/yahoo-dom-event.js"></script>';
    $html .= '<link type="text/css" rel="stylesheet" href="' . $GLOBALS["WTEXTERNALURL"] . 'yui/build/autocomplete/assets/skins/sam/autocomplete.css"/>';
    $html .= '<script type="text/javascript" src="' . $GLOBALS["WTEXTERNALURL"] . 'yui/build/autocomplete/autocomplete.js"></script>';



    $noteditable = Array();
    if($args != NULL && array_key_exists("noteditable", $args)) {
      $noteditable = explode(",", $args["noteditable"]);
      $noteditable = array_map("trim", $noteditable);
    }

    $controls = Array();
    if($args != NULL && array_key_exists("control", $args)) {
      parse_str($args["control"], $controls);
//      $controls = array_map("trim", $controls);
    }

    $hidden = Array();
    if($args != NULL && array_key_exists("hidden", $args)) {
      $hidden = explode(",", $args["hidden"]);
      $hidden = array_map("trim", $hidden);
    }
    $hiddenFieldHTML = '';

    if($args != NULL && array_key_exists("language", $args)) {
      if($args["language"]) {
        $hiddenFieldHTML .= '<input type="hidden" name="wtlanguageid" value="' . $args["language"] . '"/>'; 
      }
    }

    $forceeditable = Array();
    if($args != NULL && array_key_exists("forceeditable", $args)) {
      $forceeditable = explode(",", $args["forceeditable"]);
      $forceeditable = array_map("trim", $forceeditable);
    }


    $class = "wtform";
    if($args != NULL && array_key_exists("class", $args)) {
      $class = $args["class"];
    }
    $jsFormDefinition = "var g_formFields = Array();\n"; 
    $jsFieldConditions = "var g_fieldConditions = Array();\n";
    $jsFieldDependencies = "var g_fieldDependencies = Array();\n";
    $jsStateFields = "";//var g_stateFields = Array();\n";

    $checkedFields = Array();
    $html .= '<table class="' . $class . '">';
    if($typeName == "wtNode") {
      if($values != NULL && array_key_exists("Node Name", $values)) {
        $value = $values["Node Name"];
      }
      $html .= '<tr>';
      $html .= '<td align="right"><label for="nodeName">Name:</label></td>';
      $html .= '<td><input name="nodeName" id="nodeName" value="' . htmlentities($value) . '"></td>';
      $html .= '</td>';
      $jsFormDefinition .= "g_formFields[g_formFields.length] = new WTFormField('nodeName', 1, 'Node Name', 1)\n";
    } else {
      $sql = "SELECT
                wtAttribute.*
              FROM 
                wtAttribute, wtType, wtNode
              WHERE
                wtNode.__guid = wtAttribute.__guid
                AND wtNode.__deleted = 0
                AND wtNode.__hidden = 0
                AND wtAttribute.typeGuid = wtType.__guid
                AND wtType.`Type Name` = '" . mysql_escape_string($typeName) . "'
              ORDER BY 
                __position";
      $query = wtmysqlquery($sql);
      print mysql_error();

      while($row = mysql_fetch_assoc($query)) {

        $attributeSettings = Array();
        parse_str($row["Attribute Settings"], $attributeSettings);
        if(get_magic_quotes_gpc()) {
          $attributeSettings = array_map("stripslashes", $attributeSettings);
        }

        $fieldName = "attr" . $row["__guid"];
        $fieldLabel = $row["Attribute Name"];

        if(in_array($fieldLabel, $noteditable)) {
          continue;
        }

//        if($row["Attribute Required ID"] == 1) {
        if(in_array($fieldLabel, $hidden)) {
          $jsFormDefinition .= "g_formFields[g_formFields.length] = new WTFormField('$fieldName', 1,'" . str_replace("'", "\\'", $fieldLabel) . "', " . $row["Attribute Required ID"] . ");\n";
          $v = '';
          if($values) {
            $v = htmlEntities($values[$fieldLabel]);
          }
          if(array_key_exists($fieldLabel . " IDs", $values)) {
//            print "ids = " . $values[$fieldLabel . " IDs"];
            $cbv = $values[$fieldLabel . " IDs"];
            $checkboxes = explode(",", $cbv);
            foreach($checkboxes as $checkboxvalue) {
              $checkboxvalue = trim($checkboxvalue);
              if($checkboxvalue) {
                $checkboxname = $fieldName . '_' . $checkboxvalue;
                $hiddenFieldHTML .= '<input type="hidden" name="' . $checkboxname . '" id="' . $checkboxname . '" value="' . $checkboxvalue . '"/>';
              }
            }
          }

          
          $hiddenFieldHTML .= '<input type="hidden" name="' . $fieldName . '" id="' . $fieldName . '" value="' . $v . '"/>';
          continue;
        } else {          
          $jsFormDefinition .= "g_formFields[g_formFields.length] = new WTFormField('$fieldName', " . $row["Attribute Type ID"] . ",'" . str_replace("'", "\\'", $fieldLabel) . "', " . $row["Attribute Required ID"] . ");\n";
        }

        if(in_array($fieldLabel, $forceeditable)) {
          $row["Attribute Editable ID"] = 1;
          $row["Attribute Editable"] = "Yes";
        }
 //       }

        if(array_key_exists("statefield", $attributeSettings)) {
          $attribute = $attributeSettings["statefield"];
          $attributeNode = $GLOBALS["WT"]->getNode("/Config/Node Types/$typeName/$attribute");
          if($attributeNode != NULL) {
            $jsStateFields .= "g_stateFields['" . $fieldName . "'] = 'attr" . $attributeNode->m_guid . "';\n";
          }
        }
        if($row["Attribute Editable ID"] == 2) {
//          print $row["Editable Condition"];
          $condition = $row["Editable Condition"];
          $conditionLength = strlen($condition);
          $conditionStr = "";
          $i = 0;
          while($i < $conditionLength) {
            if($i + 3 < $conditionLength 
               && $condition[$i] == '[' 
               && $condition[$i + 1] == 'w'
               && $condition[$i + 2] == 't'
               && $condition[$i + 3] == ':') {
              $i += 4;
              $attribute = "";
              while($i < $conditionLength && $condition[$i] != ']') {
                $attribute .= $condition[$i];
                $i++;
              }
              $attributeNode = $GLOBALS["WT"]->getNode("/Config/Node Types/$typeName/$attribute");
              if($attributeNode != NULL) {         
                $attribute = "attr" . $attributeNode->m_guid;
                $conditionStr .= "wtFormValue('$attribute')";

                if(!in_array($attribute, $checkedFields)) {
                  $jsFieldDependencies .= "g_fieldDependencies['$attribute'] = new Array()\n";
                  $checkedFields[] = $attribute;
                }

                $jsFieldDependencies .= "g_fieldDependencies['$attribute'][g_fieldDependencies['$attribute'].length] = '$fieldName';\n";
              }
            } else {
              $conditionStr .= $condition[$i];
            }
            $i++;
          }
          $jsFieldConditions .= "g_fieldConditions['{$fieldName}'] = '" . str_replace("'", "\\'", $conditionStr) . "';\n";
        }

        if(array_key_exists($fieldLabel, $controls)) {
          $row["Attribute Type"] = $controls[$fieldLabel];
          $row["Attribute Settings"]= "";
        }
        $html .= $GLOBALS["WT"]->getFormAttributeHTML($typeName, $row, $values);
      }
    }


    if($args != NULL && array_key_exists("buttons", $args)) {
      $buttons = explode(",", $args["buttons"]);
      $html .= '<tr><td>&nbsp;</td><td align="right">';
      foreach($buttons as $button) {
        switch($button) {
          case 'Cancel':
            $html .= '&nbsp;<input type="button" value="Cancel" onclick="' . $args["oncancel"] . '">&nbsp;';
          break;
          
          default:
            $oneventname = "on" . strtolower($button);
            if(array_key_exists($oneventname, $args)) {
              $html .= '&nbsp;<input type="button" onclick="' . $args[$oneventname] . '" value="' . $button . '">';
            } else {
              $html .= '&nbsp;<input type="submit" onclick="return wtCheckForm(this.form, g_formFields)" value="' . $button . '">';
            }
            break;
        }
      }
      $html .= '</td></tr>';
    } else if( $args == NULL || (!array_key_exists("submit", $args)) || $args["submit"] != "") {
      $html .= '<tr><td>&nbsp;</td><td align="right">';

      $html .= '<input type="submit" name="formaction" onclick="return wtCheckForm(this.form, g_formFields)" value="Submit">';

      if($args != NULL && array_key_exists("draft", $args)) {
        $html .= '&nbsp;<input type="submit" name="formaction" value="Save Draft">&nbsp;';
      }

      if($args != NULL && array_key_exists("oncancel", $args)) {
        $html .= '&nbsp;<input type="button" value="Cancel" onclick="' . $args["oncancel"] . '">&nbsp;';
      }

      $html .= '</td></tr>';
    }
    $html .= '</table>' . "\n";

    if($jsStateFields) {
      $jsStateFields = "var g_stateFields = Array();\n $jsStateFields";
    }

    $html .= $hiddenFieldHTML;
    $html .= '<script language="javascript">' . "\n";
    $html .= $jsFormDefinition;
    $html .= $jsFieldConditions;
    $html .= $jsFieldDependencies;
    $html .= $jsStateFields;
    if($jsStateFields) {
      $html .= 'var g_wtStates = new Array();';
      $html .= 'g_wtStates[10] = new Array();';
      $query = mysql_query("SELECT * FROM dbCountries.tblRegion WHERE countryID = 10");
      while($row = mysql_fetch_array($query)) {
        $html .= 'g_wtStates[10][g_wtStates[10].length] = "' . $row["region"] . '";';
      }
      $html .= 'g_wtStates[215] = new Array();';
      $query = mysql_query("SELECT * FROM dbCountries.tblRegion WHERE countryID = 215");
      while($row = mysql_fetch_array($query)) {
        $html .= 'g_wtStates[215][g_wtStates[215].length] = "' . $row["region"] . '";';
      }
    }
    $html .= "wtSetFieldVisibility();\n";
    if($jsStateFields) {
      $html .= "wtSetStates();\n";
    }
    $html .= '</script>' . "\n";
    return $html;
  }

  function getFormRowHTML($label, $control, $id = "") 
  {
    $html = '<tr';
    if($id != "") {
      $html .= ' id="' . $id . '"';
    }
    $html .= '>';
    $html .= '<th align="right">' . $label . '</th>';
    $html .= '<td id="' . $id . 'control">' . $control . '</td>';
    $html .= '</tr>';
    return $html;
  }

  function getFormAttributeHTML($attributeInfo, $values) 
  {
    $attributeSettings = Array();
    parse_str($attributeInfo["Attribute Settings"], $attributeSettings);
    if($attributeInfo["Attribute Editable ID"] == 0) {
      return;
    }
    if(array_key_exists("hidden", $attributeSettings)) {
      return;
    }
    
    $value = NULL;
    if($values != NULL && (array_key_exists($attributeInfo["Attribute Name"], $values) || array_key_exists($attributeInfo["Attribute Name"] . " ID", $values)) ) {
       if($attributeInfo["Attribute Type ID"] == 8) {        
         $value = $values[$attributeInfo["Attribute Name"] . " ID"];
       } else if($attributeInfo["Attribute Type ID"] == 9) {
         $value = $values[$attributeInfo["Attribute Name"] . " IDs"];
       } else {
         $value = $values[$attributeInfo["Attribute Name"]];
       }

   
       
    }

    if($value == NULL) {
      $value = WTTemplate::compileAndEvaluate($attributeInfo["Attribute Default Value"], Array());
    }

    $fieldName = "attr" . $attributeInfo["__guid"];
    if($GLOBALS["WT"]->requestValueExists($fieldName)) {
      $value = $GLOBALS["WT"]->getRequestValue($fieldName);
    }

    $label = '<label for="' . $fieldName . '">' . $attributeInfo["Attribute Name"];
    if($attributeInfo["Attribute Required ID"] == 1) {
      $label .= "*";
    }
    $label .= ':';
    $label .= '</label>';

    if($attributeInfo["Attribute Type"] == "Static") {
      $label = "&nbsp;";
    }
    $control = $GLOBALS["WT"]->getControlHTML($fieldName, $attributeInfo, $value);
    return WTNode::getFormRowHTML($label, $control, "attr" . $attributeInfo["__guid"] . "row");
/*
    $html = '<tr>';
    $html .= '<td align="right">' . $attributeInfo["Attribute Name"];
    if($attributeInfo["Attribute Required"] == 1) {
      $html .= "*";    
    }
    $html .= ':</td>';
    $html .= '<td>';

    $fieldName = "attr" . $attributeInfo["__guid"];
    $html .= $GLOBALS["WT"]->getControlHTML($fieldName, $attributeInfo, $value);

    $html .= '</td>';
    $html .= '</tr>';

    return $html;
*/
  }


  /**
   *  Test if the node is locked for moderation
   *
   *  @method isLockedForModeration
   *  @return {boolean} returns true if the node is locked for moderation
   */
  function isLockedForModeration() 
  {
    $sql = "SELECT
              __lockedForModeration
            FROM 
              wtNode
            WHERE
              __guid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    $row = mysql_fetch_row($query);
    return $row[0];
  }

  /**
   *  Test if the current user has a permission for the node
   *
   *  @method userHasPermission
   *  @param {String} permissionType Can be "read", "write", "list"
   *  @return {boolean} Returns true if the user has the permission specified
   */
  function userHasPermission($permissionType) {
    if($GLOBALS["WT"]->m_contactIsAdministrator) {
      return true;
    }
   
    $permissionName = "";
    switch(strtolower($permissionType)) {
      case "read":
        $permissionName = "Read";
        break;
      case "write":
        $permissionName = "Write";
        break;
      case "list":
        $permissionName = "List";
        break;
      default:
        return false;
    }

    $userGroupSql = "";
    $userGroups = trim(implode(",", $GLOBALS["WT"]->m_contactGroups)); 
    if($userGroups != "") {
      $userGroupSql = "OR __group$permissionName IN ($userGroups)";
    }


    $sql = "SELECT
              COUNT(*) 
            FROM 
              wtNode 
            WHERE
              __guid = {$this->m_guid}
              AND (__all$permissionName = 1
              $userGroupSql)";

    $query = wtmysqlquery($sql);
    $row = mysql_fetch_array($query);
    return $row[0] != 0;
  }

  /**
   *  Test if a group has a certain permission for the node
   *
   *  @method hasPermission
   *  @param {String} group The guid or name of the Group (or "__all" to test for public permission)
   *  @param {String} permissionType The type of permission to test for "read", "write" or "list"
   *  @return {boolean} Returns true if the group has permission
   */
  function hasPermission($group, $permissionType)
  {
    $permissionName = "";
    switch(strtolower($permissionType)) {
      case "read":
        $permissionName = "Read";
	break;
      case "write":
        $permissionName = "Write";
	break;
      case "list":
        $permissionName = "List";
        break;
      default: 
        return false;      
    }

    if($group == "__all") {
      $sql = "SELECT
                __all{$permissionName}
              FROM
                wtNode
              WHERE
                __guid = {$this->m_guid}";
      $query = wtmysqlquery($sql);
      if($row = mysql_fetch_row($query)) {
        return $row[0] == 1;      
      } else {      
        return false;      
      }        		
    } else {
      $groupGuid = 0;
      if(is_numeric($group)) {
        $groupGuid = $group;
      } else {
        $sql = "SELECT
                  __guid
                FROM
                  `Group`
                WHERE
                  __active <> 0 AND 
                  Name = '" . mysql_escape_string($group) . "'";
        $query = wtmysqlquery($sql);
        if($row = mysql_fetch_row($query)) {
          $groupGuid = $row[0];
        } else {
          return false;
        }       	
      }	

      $currentGroups = Array();
      $sql = "SELECT
                `Group`.__guid, `Group`.__groupIsInternal, `Group`.Name
              FROM
                wtNode, `Group`
              WHERE
                wtNode.__guid = {$this->m_guid}
                AND `Group`.__guid = wtNode.__group{$permissionName}";
      $query = wtmysqlquery($sql);
      if($row = mysql_fetch_row($query)) {
      if($row[1] == 1) {
          $currentGroups = explode(",", $row[2]);
        } else {
          $currentGroups[] = $row[0];
        }
        return in_array($groupGuid, $currentGroups);
      } else {
        return false;
      }       
    }
  }



  /**
   *  Copy the node's moderation settings to its children
   *
   *  @method copyModerationToChildren
   *  @param {String} excludeTypes A comma separated list of types to exclude from the copy
   */
  function copyModerationToChildren($excludeTypes = "") {
    $excludeSql = "";
    if($excludeTypes != "") {
      $types = explode(",", $excludeTypes);
      $types = array_map("trim", $types);
      foreach($types as $type) {
        if($type != NULL) {
          $typeNode = $GLOBALS["WT"]->getNode("/Config/Node Types/$type");
          if($typeNode != NULL) {
            if($excludeSql != "") {
              $excludeSql .= ",";
            }
            $excludeSql .= $typeNode->m_guid;
          }
        }
      }
      if($excludeSql != "") {
        $excludeSql = " AND __typeGuid NOT IN ($excludeSql)";
      }
    }
    $sql = "SELECT
              __guid
            FROM
              wtNode
            WHERE
              __parentGuid = {$this->m_guid}
              AND __deleted = 0
              $excludeSql";
    $query = wtmysqlquery($sql);
    print mysql_error();
    while($row = mysql_fetch_row($query)) {
      $node = $GLOBALS["WT"]->getNode($row[0]);
      if($node) {
        $node->copyModerationFrom($this->m_guid);
        $node->copyModerationToChildren($excludeTypes);
      }
    }

  }

  /**
   *  Copy the moderation settings from a node
   *
   *  @method copyModerationFrom
   *  @param {String} copyFrom The guid, path or object to copy the moderation from
   */
  function copyModerationFrom($copyFrom) {
    $copyFromGuid = 0;
    if(is_object($copyFrom)) {
      $copyFromGuid = $copyFrom->m_guid;
    } else if(is_numeric($copyFrom)) {
      $copyFromGuid = $copyFrom;
    } else {
      $copyFrom = $GLOBALS["WT"]->getNode($copyFrom);
      if($copyFrom != NULL) {
        $copyFromGuid = $copyFrom->m_guid;
      }
    }

    $sql = "SELECT
              *
            FROM
              wtNode
            WHERE
              __guid = $copyFromGuid";
    $query = wtmysqlquery($sql);
    if($row = mysql_fetch_array($query)) {
      $sql = "UPDATE
                wtNode
              SET
                __moderationChainGuid = {$row["__moderationChainGuid"]}
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print mysql_error();
      }
    }
  }


  /**
   *  Copy the node's permissions to its children
   *
   *  @method copyPermissionsToChildren
   *  @param {String} [excludeTypes=""] A comma seperated list of type to exclude from the copy
   */
  function copyPermissionsToChildren($excludeTypes = "") {
    $excludeSql = "";
    if($excludeTypes != "") {
      $types = explode(",", $excludeTypes);
      $types = array_map("trim", $types);
      foreach($types as $type) {
        if($type != NULL) {
          $typeNode = $GLOBALS["WT"]->getNode("/Config/Node Types/$type");
          if($typeNode != NULL) {
            if($excludeSql != "") {
              $excludeSql .= ",";
            }
            $excludeSql .= $typeNode->m_guid;
          }
        }
      }
      if($excludeSql != "") {
        $excludeSql = " AND __typeGuid NOT IN ($excludeSql)";
      }
    }
    $sql = "SELECT 
              __guid
            FROM
              wtNode
            WHERE
              __parentGuid = {$this->m_guid}
              AND __deleted = 0
              $excludeSql";
    $query = wtmysqlquery($sql);
    print mysql_error();
    while($row = mysql_fetch_row($query)) {
      $node = $GLOBALS["WT"]->getNode($row[0]);
      if($node) {
        $node->copyPermissionsFrom($this->m_guid);
        $node->copyPermissionsToChildren($excludeTypes);
      }
    }    
  }

  /**
   *  Copy the permissions from a node
   *
   *  @method copyPermissionsFrom 
   *  @param {String} copyFrom The guid, path or object of the node to copy permissions from
   */
  function copyPermissionsFrom($copyFrom) {
    $copyFromGuid = 0;
    if(is_object($copyFrom)) {
      $copyFromGuid = $copyFrom->m_guid;
    } else if(is_numeric($copyFrom)) {
      $copyFromGuid = $copyFrom;
    } else {
      $copyFrom = $GLOBALS["WT"]->getNode($copyFrom);
      if($copyFrom != NULL) {
        $copyFromGuid = $copyFrom->m_guid;
      }
    }

    $sql = "SELECT
              *  
            FROM 
              wtNode
            WHERE
              __guid = $copyFromGuid";
    $query = wtmysqlquery($sql);
    if($row = mysql_fetch_array($query)) {
      $sql = "UPDATE
                wtNode
              SET
                __allList = {$row["__allList"]},
                __allRead = {$row["__allRead"]},
                __allWrite = {$row["__allWrite"]},
                __groupList = {$row["__groupList"]},
                __groupRead = {$row["__groupRead"]},
                __groupWrite = {$row["__groupWrite"]}
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print mysql_error();
      }
    }
  }

  /**
   *  Set the permissions on the node for a group
   *
   *  @method setPermission
   *  @param {String} group The guid or name of the group (or "__all" for public)
   *  @param {String} permissionType Either "read", "write" or "list"
   *  @param {int} [set=1] Set to 1 to add the permission, set to 0 to remove it
   *  @param {boolean} [overwritecurrent=false] Set to true to remove all permissions on the node of the permissionType apart from the one being set
   */
  function setPermission($group, $permissionType, $set = 1, $overwritecurrent = false) 
  {

    $permissionName = "";              
    switch(strtolower($permissionType)) {
      case "read":
        $permissionName = "Read";
        break;
      case "write":
        $permissionName = "Write";          
        break;
      case "list":
        $permissionName = "List";          
        break;  
      default:
        return NULL;
        break;          
    }              

    if($group == "__all") {

      $sql = "UPDATE 
                wtNode 
              SET __all{$permissionName} = ";
              
      if($set == 1) {
        $sql .= " 1 ";
      } else {
        $sql .= " 0 ";
      }

      $sql .= " WHERE __guid = {$this->m_guid} ";
      if(!wtmysqlquery($sql)) {
      } else {
        return false;
      }

    } else {

      // get the guid of the group
      $groupGuid = 0;
      if(is_numeric($group)) {      
        $groupGuid = $group;      
      } else {      
        $sql = "SELECT
                  `Group`.__guid
                FROM
                  `Group`, wtNode
                WHERE
                  `Group`.__guid = wtNode.__guid
                  AND `Group`.__active <> 0
                  AND wtNode.__deleted = 0
                  AND Name = '" . mysql_escape_string($group) . "'";
        $query = wtmysqlquery($sql);
        if($row = mysql_fetch_row($query)) {
          $groupGuid = $row[0];
        } else {
          return NULL;
        }                
      }	

      // get the current group
      $sql = "SELECT 
                __group{$permissionName}, Name, __groupIsInternal
              FROM 
                wtNode, `Group`
              WHERE
                wtNode.__group{$permissionName} = `Group`.__guid
                AND `Group`.__active <> 0
                AND wtNode.__deleted = 0
                AND wtNode.__guid = {$this->m_guid}";
                
      $currentGroupGuid = 0;                
      $currentGroupIsGroupSet = false;
      $currentGroups = Array();                

      $query = wtmysqlquery($sql);
      print mysql_error();
      if($row = mysql_fetch_row($query)) {
        $currentGroupGuid = $row[0];
        if($row[2] == 1) {       
          // group is a group set
          $currentGroupIsGroupSet = true;
          $currentGroups = explode(",", $row[1]);        
        } else {
          $currentGroups[] = $currentGroupGuid;
        }
      }                       

      if($overwritecurrent) {
        $currentGroups = Array();
      }
      if($set == 1) {
        // add the group to the array
        if(in_array($groupGuid, $currentGroups)) {
          // permission already set..
          return true;
        }
        $currentGroups[] = $groupGuid;
      } else {
        // remove the group from the array
        if(!in_array($groupGuid, $currentGroups)) {
          return true;
        }
        $temp = Array();
        foreach($currentGroups as $currentGroup) {
          if($currentGroup != $groupGuid) {
            $temp[] = $currentGroup;
          }
        }
        $currentGroups = $temp;
        
      }
      // check if need a group set or not
      if(count($currentGroups) <= 1) {
        if(count($currentGroups) == 0) {
          $currentGroups[] = 0;
        }
        $sql = "UPDATE
                  wtNode
                SET
                  __group{$permissionName} = {$currentGroups[0]}
                WHERE
                  __guid = {$this->m_guid}";
 
        if(!wtmysqlquery($sql)) {
          print mysql_error();
        }
        
        if($currentGroupIsGroupSet) {
          // is a group set, now find if anything is using it..
          $sql = "SELECT 
                    COUNT(__guid) 
                  FROM 
                    wtNode
                  WHERE
                    (__groupRead = $currentGroupGuid
                     OR __groupWrite = $currentGroupGuid
                     OR __groupList = $currentGroupGuid)
                    AND __deleted = 0 ";
          $query = wtmysqlquery($sql);
          print mysql_error();
          
          if($row = mysql_fetch_row($query)) {
            if($row[0] == 0) {
              $sql = "DELETE FROM
                        wtNode
                      WHERE
                        __guid = $currentGroupGuid";
              if(!wtmysqlquery($sql)) {
                print mysql_error();
              }
              $sql = "DELETE FROM 
                        `Group`
                      WHERE
                        __guid = $currentGroupGuid";
              if(!wtmysqlquery($sql)) {
                print mysql_error();
              }
              $sql = "SELECT
                        __guid
                      FROM
                        wtNode
                      WHERE
                        __parentGuid = $currentGroupGuid";
              $query = wtmysqlquery($sql);
              while($row = mysql_fetch_row($query)) {
                $GLOBALS["WT"]->unlinkNodes($currentGroupGuid, $row[0]);
              }
            }
          }

        }
      } else {
        sort($currentGroups);
        $groupSet = implode(",", $currentGroups);

        
        $newGroupGuid = 0;
        
        // see if this set of groups exists
        $sql = "SELECT
                  __guid
                FROM
                  `Group`
                WHERE
                  Name = '$groupSet'
                  AND __groupIsInternal = 1";
       
        $query = wtmysqlquery($sql);
        print mysql_error();
        if($row = mysql_fetch_row($query)) {
          $newGroupGuid = $row[0];
          $sql = "UPDATE
                    wtNode
                  SET
                    __group{$permissionName} = $newGroupGuid
                  WHERE
                    __guid = {$this->m_guid}";
          if(!wtmysqlquery($sql)) {
            print mysql_error();
          }

          // need to delete old group set if not being used
          if($currentGroupIsGroupSet) {
            // is a group set, now find if anything is using it..
            $sql = "SELECT
                      COUNT(__guid)
                    FROM
                      wtNode
                    WHERE
                      (__groupRead = $currentGroupGuid
                       OR __groupWrite = $currentGroupGuid
                       OR __groupList = $currentGroupGuid)
                      AND __deleted = 0";
            $query = wtmysqlquery($sql);
            print mysql_error();

            if($row = mysql_fetch_row($query)) {
              if($row[0] == 0) {
                $sql = "DELETE FROM
                          wtNode
                        WHERE
                          __guid = $currentGroupGuid";
                if(!wtmysqlquery($sql)) {
                  print mysql_error();
                }
                $sql = "DELETE FROM
                          `Group`
                        WHERE
                          __guid = $currentGroupGuid";
                if(!wtmysqlquery($sql)) {
                  print mysql_error();
                }
                $sql = "SELECT
                          __guid
                        FROM
                          wtNode
                        WHERE
                          __parentGuid = $currentGroupGuid";
                $query = wtmysqlquery($sql);
                while($row = mysql_fetch_row($query)) {
                  $GLOBALS["WT"]->unlinkNodes($currentGroupGuid, $row[0]);
                }
              }
            }
          }

	  
        } else {
          // doesn't exist         

          // need to find out if we can modify the current group set 
          // or if we need to create a new group set
          $canOverwrite = $currentGroupIsGroupSet;
          
          if($canOverwrite) {
            // is any other node using the current group set?
            $sql = "SELECT 
                      COUNT(__guid) 
                    FROM
                      wtNode
                    WHERE
                      (__groupList = $currentGroupGuid
                       OR __groupRead = $currentGroupGuid
                       OR __groupWrite = $currentGroupGuid)
                      AND __guid <> {$this->m_guid}
                      AND __deleted = 0";
            $query = wtmysqlquery($sql);
            print mysql_error();
            if($row = mysql_fetch_array($query)) {
              $canOverwrite = $row[0] == 0;
            }                    
          }
          
          if($canOverwrite) {
            // can just update the group set
            $sql = "UPDATE
                      `Group`
                    SET
                      Name = '$groupSet'
                    WHERE
                      __guid = $currentGroupGuid";
            if(!wtmysqlquery($sql)) {
            }
            $sql = "DELETE FROM
                      wtNode
                    WHERE
                      __parentGuid = $currentGroupGuid
                      AND __guid NOT IN ($groupSet)";
            if(!wtmysqlquery($sql)) {
              print $sql;
              print mysql_error();
            }

            $groupSetArray = explode(",", $groupSet);
            foreach($groupSetArray as $childGroupGuid) {
              $GLOBALS["WT"]->linkNodes($currentGroupGuid, $childGroupGuid);
            }
          } else {
            // need to create a new group
            $groups = $GLOBALS["WT"]->getNode("/Groups");
            if($groups == NULL) {
              return false;
            }
            $newGroup = $groups->createChild("Group", Array("Name" => $groupSet));
            $newGroupGuid = $newGroup->m_guid;
          
            // need to set group as hidden.
            $sql = "UPDATE 
                      wtNode
                    SET
                      __hidden = 1
                    WHERE
                      __guid = $newGroupGuid";
            if(!wtmysqlquery($sql)) {
            }
            // need to set it as an internal group
            $sql = "UPDATE
                      `Group`
                    SET
                      __groupIsInternal = 1
                    WHERE
                      __guid = $newGroupGuid";
            if(!wtmysqlquery($sql)) {
            }

            $groupSetArray = explode(",", $groupSet);
            foreach($groupSetArray as $childGroupGuid) {
              $GLOBALS["WT"]->linkNodes($newGroupGuid, $childGroupGuid);              
            }
            
            // set the new group..
            $sql = "UPDATE
                      wtNode
                    SET
                      __group{$permissionName} = $newGroupGuid
                    WHERE 
                      __guid = {$this->m_guid}";
            if(!wtmysqlquery($sql)) {
              print mysql_error();
            }
          }            
        }
      }                                           
    }
  }

  /**
   *  Get the attributes of the node as an associative array
   *
   *  @method getAttributes
   *  @param {boolean} [latest=false] Set to true to get the latest version (could be a draft or unapproved version)
   *  @return {Array} returns the attributes of the node
   */
  function getAttributes($latest = false) 
  {
    if($GLOBALS["WT"]->getMode() == "edit") {
      $latest = true;
    }
    

    if($this->m_typeName == "wtNode") {
      $sql = "SELECT
                *, wtNode.__name AS `Node Name`
              FROM
                `wtNode`
              WHERE
                `{$this->m_typeName}`.__guid = {$this->m_guid}";

    } else {
      $activeSql = " AND `{$this->m_typeName}`.__active = 1";
      if($latest) {
        $activeSql = " AND `{$this->m_typeName}`.__latest = 1";
      }
      $sql = "SELECT
                *
              FROM 
                `{$this->m_typeName}`, wtNode
              WHERE
                `{$this->m_typeName}`.__guid = {$this->m_guid}
                AND wtNode.__guid = `{$this->m_typeName}`.__guid
                $activeSql";
    }

    $query = wtmysqlquery($sql);
    print mysql_error(); 
    if($row = mysql_fetch_assoc($query)) {
      $this->m_dirty = false;
      $this->m_attributes = $row;
      return $this->m_attributes;
    }
    return false;              
  }

  /**
   *  Create a node from a form submission in the office
   *
   *  @method createChildFromForm
   *  @private
   *  @param {String} typeName The name of the type to create
   *  @param {Array} attributes The attributes from the form
   *  @return {Object} The object for the node
   */
  function createChildFromForm($typeName, $attributes) 
  {
    if($typeName == "wtNode") {
//      if($this->m_typeName == "wtNode") {
        if(array_key_exists("nodeName", $attributes)) {
          $attributes["Node Name"] = $attributes["nodeName"];
        }
//      }
    }
    $sql = "SELECT
              *
            FROM
              wtType, wtAttribute, wtNode
            WHERE
              wtNode.__guid = wtAttribute.__guid
              AND wtNode.__deleted = 0
              AND wtAttribute.typeGuid = wtType.__guid
              AND wtType.__active <> 0
              AND wtType.`Type Name` = '" . mysql_escape_string($typeName) . "'";
    $query = wtmysqlquery($sql);
    print mysql_error();
    while($row = mysql_fetch_array($query)) {
      $value = $GLOBALS["WT"]->getControlFormValue("attr" . $row["__guid"], $row, $attributes);

      if($value !== false) {
        if($row["Attribute Type ID"] == 8) {
          $attributes[$row["Attribute Name"] . " ID"] = $value;
        } else if($row["Attribute Type ID"] == 9) {
          $attributes[$row["Attribute Name"] . " IDs"] = $value;
        } else {
          $attributes[$row["Attribute Name"]] = $value;
        }
      } else {
//        print "VALUE is false!!<br>";
      }
    }

    return $this->createChild($typeName, $attributes);

  }

  /**
   *  Send the email informing the editor the edit has been approved by the moderators
   *
   *  @method sendModerationApprovedEmail
   *  @param {int} eventID The id of the moderation event
   */
  function sendModerationApprovedEmail($eventID) {
    $event = WTEvent::getEvent($eventID);
    if($event) {
      // get all the editors/moderators
      $emailAddresses = ""; 
      $sql = "SELECT
                *
              FROM
                wtEvent 
              WHERE
                __luid = $eventID
                OR `Event ID` = $eventID";
      $query = mysql_query($sql);
      while($row = mysql_fetch_array($query)) {
        $contactID = $row["Contact ID"];
        if($contactID) {
          $contact = $GLOBALS["WT"]->getNode($contactID);
          if($contact) {
            $emailAddress = $contact->getAttribute("Email Address");
            if($emailAddress) {
              if($emailAddresses) {
                $emailAddresses .= ",";
              }
              $emailAddresses .= $emailAddress;
            }
          }
        }
      } 

      $notifyGroup = WTConfig::get("Content Manager/Moderation Enabled/Notify Group");
      if($notifyGroup) {
        $results = Array();
        $q["Node Type"] = "Contact";
        $q["Path"] = "/Groups/$notifyGroup/*";
        $q["Results Array"] = &$results;
        $GLOBALS["WT"]->query($q);
        foreach($results as $result) {
          $emailAddress = trim($result["Email Address"]);
          if($emailAddress) {
            if($emailAddresses) {
              $emailAddresses .= ",";
            }
            $emailAddresses .= $emailAddress;
          }
        }
      }
      if($emailAddresses) {
          $description = $event->getAttribute("Description");
          $changes = $event->getChangesAsHTML();
          $moderationType = $event->getAttribute("Event Type");
          $date = $event->getAttribute("__created");

          $currentUser = $GLOBALS["WT"]->getCurrentUser();
          $moderator = $currentUser->getAttribute("First Name") . " " . $currentUser->getAttribute("Last Name");
          if(trim($moderator) == "") {
            $moderator = $currentUser->getAttribute("Username");
          }
          $reason = nl2br($reason);
          $subject = "WebTemplate edit approved";
          $message = "<html><body>";
          $message .= "Your edit was approved.";
          $message .= "<table class=\"moderationchanges\">";
          $message .= "<tr><th>Edit Date:</th><td>$date</td></tr>";
          $message .= "<tr><th>Description:</th><td>$description</td></tr>";
          $message .= "<tr><th>Moderator:</th><td>$moderator</td></tr>";
          $message .= "</table>";

          if($moderationType == 2) {
            $message .= "<br/><br/>Changes:<br/><br/>";
            $message .= $changes;
          }
          $message .= "</body></html>";

          $mail = new WTMail();
          $mail->setTo($emailAddresses);
          $mail->setFrom("content@webtemplate.com.au", "WebTemplate");
          $mail->setContent($subject, $message, true);
          $mail->send();
      }

    }

  }

  /**
   *  Send the email informing the editor their edit was rejected by the moderator
   *
   *  @method sendModerationRejectedEmail
   *  @param {int} eventID The id related to the moderation event
   *  @param {String} [reason=""] The reason for the rejection
   */
  function sendModerationRejectedEmail($eventID, $reason = "") {
    $event = WTEvent::getEvent($eventID);
    if($event) {
      // get all the editors/moderators
      $emailAddresses = "";
      $sql = "SELECT
                *
              FROM
                wtEvent
              WHERE
                __luid = $eventID
                OR `Event ID` = $eventID
              ORDER BY __created
              LIMIT 1";
      $query = mysql_query($sql);
      while($row = mysql_fetch_array($query)) {
        $contactID = $row["Contact ID"];
        if($contactID) {
          $contact = $GLOBALS["WT"]->getNode($contactID);
          if($contact) {
            $emailAddress = $contact->getAttribute("Email Address");
            if($emailAddress) {
              if($emailAddresses) {
                $emailAddresses .= ",";
              }
              $emailAddresses .= $emailAddress;
            }
          }
        }
      }

      if($emailAddresses) {

          $description = $event->getAttribute("Description");
          $changes = $event->getChangesAsHTML();
          $moderationType = $event->getAttribute("Event Type");
          $date = $event->getAttribute("__created");

          $currentUser = $GLOBALS["WT"]->getCurrentUser();
          $moderator = $currentUser->getAttribute("First Name") . " " . $currentUser->getAttribute("Last Name");
          if(trim($moderator) == "") {
            $moderator = $currentUser->getAttribute("Username");
          }
          $reason = nl2br($reason);
          $subject = "WebTemplate edit not approved";
          $message = "<html><body>";
          $message .= "Your edit was not approved";
          $message .= "<table class=\"moderationchanges\">";
          $message .= "<tr><th>Edit Date:</th><td>$date</td></tr>";
          $message .= "<tr><th>Description:</th><td>$description</td></tr>";
          $message .= "<tr><th>Moderator:</th><td>$moderator</td></tr>";
          $message .= "<tr><th>Reason:</th><td>$reason</td></tr>";
          $message .= "</table>";

          if($moderationType == 2) {
            $message .= "<br/><br/>Changes:<br/><br/>";
            $message .= $changes;
          }
          $message .= "</body></html>";

          $mail = new WTMail();
          $mail->setTo($emailAddresses);
          $mail->setFrom("content@webtemplate.com.au", "WebTemplate");
          $mail->setContent($subject, $message, true);
          $mail->send();


      }


    }
  }

  /**
   *  Send an email to a moderator informing them moderation is required
   *
   *  @method sendModerationRequiredEmail
   *  @param {int} eventID The moderation event
   */
  function sendModerationRequiredEmail($eventID) {


    $groupGuid = 0;
    $description = "";

    $sql = "SELECT
              *
            FROM
              wtEvent
            WHERE
              __luid = $eventID";
    $query = mysql_query($sql);
    if($row = mysql_fetch_array($query)) {
      $description = $row["Description"];
      $groupGuid = $row["Moderation Group ID"]; 
    }

    $results = Array();
    $q = Array();
    $q["Path"] = "$groupGuid/*";
    $q["Node Type"] = "Contact";
    $q["Results Array"] = &$results;
    $GLOBALS["WT"]->query($q);

    $subject = "Content Requires Moderation";
    $message = "<html><body>";
    $message .= "The following changes require moderation:<br/><br/>";
    $message .= $description . "<br/><br/>";
    $message .= '<a href="http://www.webtemplate.com.au">http://www.webtemplate.com.au</a>';
    $message .= "</body></html>";

    $emailList = "";
    foreach($results as $result) {
      if($emailList != "") {
        $emailList .= ",";
      }
      $emailList .= $result["Email Address"];
    }
    $mail = new WTMail();
    $mail->setTo($emailList);
    $mail->setFrom("content@webtemplate.com.au", "WebTemplate");
    $mail->setContent($subject, $message, true);
    $mail->send();
  }

  /**
   *  Log an event
   *
   *  @method logEvent
   *  @private
   *  @param {int} eventType The type of event: 1 create, 2 edit, 3 delete
   *  @param {int} [moderationChainGuid=0] The id of the moderation chain for the node
   *  @param {String} changes The changes made
   */

  function logEvent($eventType, $moderationChainGuid = 0, $changes = "") {


    $nodeID = $this->m_guid;
    $pageID = 0;

    $eventName = "";
    $description = "";
    $nodeName = $this->m_name;
    $nodeTypeName = $this->m_typeName;

    // find if there is a page that owns this node
    $node = $this;
    $typeName = $this->m_typeName;
    while($typeName != 'Page') {

      $parentGuid = $node->m_parentGuid;
      if($parentGuid == 0) {
        break;
      }
      $node = $GLOBALS["WT"]->getNode($parentGuid);
      $typeName = $node->m_typeName;
    }


    // get the description of the event
    if($typeName == 'Page') {
      $pageID = $node->m_guid;
      $pageName = $node->m_name;
      $pageURI = $node->getAttribute("URI", true);

      if($node->m_guid == $this->m_guid) {
        // the changed node is a page
        switch($eventType) {
          case 1:
            $description = "Page '$pageName' created";
            break;
          case 2:
            $description = "Page '$pageName' settings changed";
            break;
          case 3:
            $description = "Page '$pageName' deleted";
            break;
        }
        $description .= "<br>$pageURI";
      } else {
        // the changed node exists on a page
        switch($eventType) {
          case 1:
            $description = "'$nodeName' added to page '$pageName'";
            break;
          case 2:
            $description = "'$nodeName' changed on page '$pageName'";
            break;
          case 3:
            $description = "'$nodeName' deleted on page '$pageName'";
            break;
        }
        $description .= "<br>$pageURI";
      }
    } else {
      // the changed node doesn't belong to a page
      switch($eventType) {
        case 1:
          $description = "$nodeTypeName '$nodeName' created";
          break;
        case 2:
          $description = "$nodeTypeName '$nodeName' changed";
          break;
        case 3:
          $description = "$nodeTypeName '$nodeName' deleted";
          break;
      }
    }

    $eventName = $description;



    $events = $GLOBALS["WT"]->getNode("/Events");
    if($events != NULL) {
//      $event = $events->createChild("wtEvent", Array("Event" => $eventName, "Description" => $description, "Contact ID" => $GLOBALS["WT"]->m_contactGuid, "Node ID" => $this->m_guid, "Page ID" => $pageID, "Event Type" => $eventType, "Changes" => $changes) );

      $versionDir = $GLOBALS["WTSITEDIRECTORY"] . $GLOBALS["WT"]->getSiteSetting("Site Directory") . "files/versions/";
      if(!file_exists($versionDir)) {
        mkdir($versionDir);
      }


      $contact = $GLOBALS["WT"]->getWTValue("wt.currentuser.Username");

      $description .= " by $contact";
      $sql = "INSERT INTO wtEvent (
                 __created,
                 Event,
                 Description,
                 `Contact`,
                 `Contact ID`,
                 `Node ID`,
                 `Page ID`,
                 `Event Type`,
                 Changes
               ) VALUES (
                 NOW(),
                 '" . mysql_escape_string($eventName) . "',
                 '" . mysql_escape_string($description) . "',
                 '" . mysql_escape_string($contact) . "',
                 " . $GLOBALS["WT"]->m_contactGuid . ",
                 " . $this->m_guid . ",
                 " . $pageID . ",
                 " . $eventType . ",
                 '')";
      mysql_query($sql);
      print mysql_error();
      $eventID = mysql_insert_id();
//      $eventGuid = $event->m_guid;

      if(strlen($changes) > 0 && ($GLOBALS["WT"]->getModerationEnabled() || WTConfig::get("Content Manager/Version Control Enabled") == 'Yes') ) {
        $fd = @fopen($versionDir . $eventID . ".changes", "w");
        if($fd) {
          fwrite($fd, $changes);
          fclose($fd);
        }
      }


      // if version control is enabled, save a version
      if(WTConfig::get("Content Manager/Version Control Enabled") == "Yes") {
        $versionDir = $GLOBALS["WTSITEDIRECTORY"] . $GLOBALS["WT"]->getSiteSetting("Site Directory") . "files/versions/";
        if(!file_exists($versionDir)) {
          mkdir($versionDir);
        }

        if($pageID != 0) {
          $page = $GLOBALS["WT"]->getNode($pageID);

          if($page) {
            $mode = $GLOBALS["WT"]->getMode();
            $GLOBALS["WT"]->setMode("view");
            $pathMode = $GLOBALS["WT"]->getSiteSetting("Path Mode");
            $GLOBALS["WT"]->m_siteSettings["Path Mode"] = "rewrite";

            $contents = $page->render();
            $GLOBALS["WT"]->setMode($mode);
            $GLOBALS["WT"]->m_siteSettings["Path Mode"] = $pathMode;

            $fd = fopen($versionDir . $eventID . ".html", "w");
            fwrite($fd, $contents);
            fclose($fd);

            $nodeData = $page->export($page->m_typeGuid);
            $fd = fopen($versionDir . $eventID . ".node", "w");
            fwrite($fd, serialize($nodeData));
            fclose($fd);
//            $event->setAttributes(Array("Version ID" => $eventGuid));
            $sql = "UPDATE
                      wtEvent
                    SET
                      `Version ID` = $eventID
                    WHERE
                      __luid = $eventID";
            mysql_query($sql);
            print mysql_error();
          }
        }
      }

      //$moderationGuid = $this->getModerationChainGuid();


      if($moderationChainGuid) {
        $moderationChainNode = $GLOBALS["WT"]->getNode($moderationChainGuid);
        if($moderationChainNode) {

          $sql = "UPDATE
                    wtNode
                  SET
                    __lockedForModeration = $eventType
                  WHERE
                    __guid = {$this->m_guid}";

          if(!wtmysqlquery($sql)) {
            print $sql;
            print mysql_error();
          }

          $groupGuid = 0;
          if($moderationChainNode->m_typeName == "Moderation Chain") {
            // get the first moderation group
//            $q = Array("Node Type" => "Group", "Path" => "$moderationChainGuid/*", "Limit" => 1, "Select" => "`Group`.__guid");
//            $groupGuid = $GLOBALS["WT"]->query($q, "singleValueCallback");
            $groupGuid = $this->getNextModerationGroupID();

          } else {
            $groupGuid = $moderationChainGuid;
          }



          $sql = "UPDATE
                    wtEvent
                  SET
                    `Status` = 0,
                    `Event ID` = $eventID,
                    `Moderation Group ID` = $groupGuid
                  WHERE
                    __luid = $eventID";
          mysql_query($sql);
          print $sql;
          print mysql_error();

          $sql = "UPDATE
                    wtNode
                  SET
                    __lockedForModeration = $eventType
                  WHERE
                    __guid = {$this->m_guid}";

          if(!wtmysqlquery($sql)) {
            print $sql;
            print mysql_error();
          }

          $this->sendModerationRequiredEmail($eventID);
/*
          // email the moderators
          $results = Array();
          $q = Array();
          $q["Path"] = "$groupGuid/*";
          $q["Node Type"] = "Contact";
          $q["Results Array"] = &$results;
          $GLOBALS["WT"]->query($q);

          $subject = "Content Requires Moderation";
          $message = "<html><body>";
          $message .= "The following changes require moderation:<br/><br/>";
          $message .= $description . "<br/><br/>";
          $message .= '<a href="http://www.webtemplate.com.au">http://www.webtemplate.com.au</a>';
          $message .= "</body></html>";

          $emailList = "";
          foreach($results as $result) {
            if($emailList != "") {
              $emailList .= ",";
            }
            $emailList .= $result["Email Address"];
          }
          $mail = new WTMail();
          $mail->setTo($emailList);
          $mail->setFrom("content@webtemplate.com.au", "WebTemplate");
          $mail->setContent($subject, $message, true);
          $mail->send();
*/

        }

      } else {
//        $event->setAttributes(Array("Status" => 1));
        $sql = "UPDATE
                  wtEvent
                SET
                  `Status` = 1
                WHERE
                  __luid = $eventID";
        mysql_query($sql);
        print mysql_error();
      }
    }
  }



/*
  function logEvent($eventType, $moderationChainGuid = 0, $changes = "") {


    $nodeID = $this->m_guid;
    $pageID = 0;

    $eventName = "";
    $description = "";
    $nodeName = $this->m_name;
    $nodeTypeName = $this->m_typeName;


    // find if there is a page that owns this node
    $node = $this;
    $typeName = $this->m_typeName;
    while($typeName != 'Page') {

      $parentGuid = $node->m_parentGuid;
      if($parentGuid == 0) {
        break;
      }
      $node = $GLOBALS["WT"]->getNode($parentGuid);
      $typeName = $node->m_typeName;
    }


    // get the description of the event
    if($typeName == 'Page') {
      $pageID = $node->m_guid;
      $pageName = $node->m_name;
      $pageURI = $node->getAttribute("URI", true);

      if($node->m_guid == $this->m_guid) {
        // the changed node is a page
        switch($eventType) {
          case 1:
            $description = "Page '$pageName' created";
            break;
          case 2:
            $description = "Page '$pageName' settings changed";
            break;
          case 3:
            $description = "Page '$pageName' deleted";
            break;
        }
        $description .= "<br>$pageURI";
      } else {
        // the changed node exists on a page
        switch($eventType) {
          case 1:
            $description = "'$nodeName' added to page '$pageName'";
            break;
          case 2:
            $description = "'$nodeName' changed on page '$pageName'";
            break;
          case 3:
            $description = "'$nodeName' deleted on page '$pageName'";
            break;
        }
        $description .= "<br>$pageURI";
      }
    } else {
      // the changed node doesn't belong to a page
      switch($eventType) {
        case 1:
          $description = "$nodeTypeName '$nodeName' created";
          break;
        case 2:
          $description = "$nodeTypeName '$nodeName' changed";
          break;
        case 3:
          $description = "$nodeTypeName '$nodeName' deleted";
          break;
      }
    }

    $eventName = $description;



    $events = $GLOBALS["WT"]->getNode("/Events");
    if($events != NULL) {
//      $event = $events->createChild("wtEvent", Array("Event" => $eventName, "Description" => $description, "Contact ID" => $GLOBALS["WT"]->m_contactGuid, "Node ID" => $this->m_guid, "Page ID" => $pageID, "Event Type" => $eventType, "Changes" => $changes) );

      $versionDir = $GLOBALS["WTSITEDIRECTORY"] . $GLOBALS["WT"]->getSiteSetting("Site Directory") . "files/versions/";
      if(!file_exists($versionDir)) {
        mkdir($versionDir);
      }


      $contact = $GLOBALS["WT"]->getWTValue("wt.currentuser.Username");
      $sql = "INSERT INTO wtEvent (
                 __created,
                 Event,
                 Description,
                 `Contact`,
                 `Contact ID`,
                 `Node ID`,
                 `Page ID`,
                 `Event Type`,
                 Changes
               ) VALUES (
                 NOW(),
                 '" . mysql_escape_string($eventName) . "',
                 '" . mysql_escape_string($description) . "',
                 '" . mysql_escape_string($contact) . "',
                 " . $GLOBALS["WT"]->m_contactGuid . ",
                 " . $this->m_guid . ",
                 " . $pageID . ",
                 " . $eventType . ",
                 '')";
      mysql_query($sql);
      print mysql_error();
      $eventID = mysql_insert_id();
//      $eventGuid = $event->m_guid;

      if(strlen($changes) > 0 && ($GLOBALS["WT"]->getModerationEnabled() || WTConfig::get("Content Manager/Version Control Enabled") == 'Yes') ) {

        $fd = @fopen($versionDir . $eventID . ".changes", "w");
        if($fd) {
          fwrite($fd, $changes);
          fclose($fd);
        }
      }


      // if version control is enabled, save a version
      if(WTConfig::get("Content Manager/Version Control Enabled") == "Yes") {
        $versionDir = $GLOBALS["WTSITEDIRECTORY"] . $GLOBALS["WT"]->getSiteSetting("Site Directory") . "files/versions/";
        if(!file_exists($versionDir)) {
          mkdir($versionDir);
        }

        if($pageID != 0) {
          $page = $GLOBALS["WT"]->getNode($pageID);

          if($page) {
            $mode = $GLOBALS["WT"]->getMode();
            $GLOBALS["WT"]->setMode("view");
            $pathMode = $GLOBALS["WT"]->getSiteSetting("Path Mode");
            $GLOBALS["WT"]->m_siteSettings["Path Mode"] = "rewrite";

            $contents = $page->render();
            $GLOBALS["WT"]->setMode($mode);
            $GLOBALS["WT"]->m_siteSettings["Path Mode"] = $pathMode;

            $fd = fopen($versionDir . $eventID . ".html", "w");
            fwrite($fd, $contents);
            fclose($fd);

            $nodeData = $page->export($page->m_typeGuid);
            $fd = fopen($versionDir . $eventID . ".node", "w");
            fwrite($fd, serialize($nodeData));
            fclose($fd);
//            $event->setAttributes(Array("Version ID" => $eventGuid));
            $sql = "UPDATE
                      wtEvent
                    SET
                      `Version ID` = $eventID
                    WHERE
                      __luid = $eventID";
            mysql_query($sql);
            print mysql_error(); 
          }
        }
      }

      //$moderationGuid = $this->getModerationChainGuid();



      if($moderationChainGuid) {

//        $event->setAttributes(Array("Status" => 0, "Moderation Group ID" => $moderationChainGuid));

        $sql = "UPDATE
                  wtEvent
                SET
                  `Status` = 0,
                  `Moderation Group ID` = $moderationChainGuid
                WHERE
                  __luid = $eventID";
        mysql_query($sql);
        print mysql_error();

        $sql = "UPDATE
                  wtNode
                SET
                  __lockedForModeration = $eventType
                WHERE
                  __guid = {$this->m_guid}";

        if(!wtmysqlquery($sql)) {
          print $sql;
          print mysql_error();
        }
        // email the moderators
        $results = Array();
        $q = Array();
        $q["Path"] = "$moderationChainGuid/*";
        $q["Node Type"] = "Contact";
        $q["Results Array"] = &$results;
        $GLOBALS["WT"]->query($q);

        $subject = "Content Requires Moderation";
        $message = "<html><body>";
        $message .= "The following changes require moderation:<br/><br/>";
        $message .= $description . "<br/><br/>";
        $message .= '<a href="http://www.webtemplate.com.au">http://www.webtemplate.com.au</a>';
        $message .= "</body></html>";

        $emailList = "";
        foreach($results as $result) {
          if($emailList != "") {
            $emailList .= ",";
          }
          $emailList .= $result["Email Address"];
        }

        $mail = new WTMail();
        $mail->setTo($emailList);
        $mail->setFrom("content@webtemplate.com.au", "WebTemplate");
        $mail->setContent($subject, $message, true);
        $mail->send();
      } else {
//        $event->setAttributes(Array("Status" => 1));
        $sql = "UPDATE
                  wtEvent
                SET
                  `Status` = 1
                WHERE
                  __luid = $eventID";
        mysql_query($sql);
        print mysql_error();
      }
    }




  }
*/

  // unused function, replaced by logEvent
  function logModerationEvent($moderationType, $changes = "")
  {  

    // find if there is a page that owns this node
    $node = $this;
    $typeName = $this->m_typeName;
    while($typeName != 'Page') {

      $parentGuid = $node->m_parentGuid;

      if($parentGuid == 0) {
        break;
      }
      $node = $GLOBALS["WT"]->getNode($parentGuid);
      $typeName = $node->m_typeName;
    }


    $name = "";
    $description = "";
    $nodeID = $this->m_guid;
    $pageID = 0;
    $nodeName = $this->m_name;
    $nodeTypeName = $this->m_typeName;
    if($typeName == 'Page') {
      $pageID = $node->m_guid;
      $pageName = $node->m_name;
      $pageURI = $node->getAttribute("URI", true);

      if($node->m_guid == $this->m_guid) {
        // the changed node is a page
        switch($moderationType) {
          case 1:
            $description = "Page '$pageName' created";
            break;
          case 2:
            $description = "Page '$pageName' settings changed";
            break;
          case 3:
            $description = "Page '$pageName' deleted";
            break;
        }
        $description .= "<br>$pageURI";
      } else {
        // the changed node exists on a page
        switch($moderationType) {
          case 1:
            $description = "'$nodeName' added to page '$pageName'";
            break;
          case 2:
            $description = "'$nodeName' changed on page '$pageName'";
            break;
          case 3:
            $description = "'$nodeName' deleted on page '$pageName'";
            break;
        }
        $description .= "<br>$pageURI";
      }
    } else {
      // the changed node doesn't belong to a page
      switch($moderationType) {
        case 1:
          $description = "$nodeTypeName '$nodeName' created";
          break;
        case 2:
          $description = "$nodeTypeName '$nodeName' changed";
          break;
        case 3:
          $description = "$nodeTypeName '$nodeName' deleted";
          break;
      }
    }

    $name = $description;


    $moderationEvents = $GLOBALS["WT"]->getNode("/Moderation Events");
    if($moderationEvents == NULL) {
      $root = $GLOBALS["WT"]->getNode(0);
      $moderationEvents = $root->createChild("wtNode", "Moderation Events");
      $moderationEvents->setPermission("__all", "write");
    }

    $moderationGuid = $this->getModerationChainGuid();

    if($moderationEvents) {
      $currentUser = $GLOBALS["WT"]->getCurrentUser();
      $moderationEvents->createChild("wtModerationEvent", Array("Name" => $name, "Description" => $description, "Node ID" => $nodeID, "Page ID" => $pageID, "Status" => 0, "Changes" => $changes, "Contact ID" => $currentUser->m_guid, "Moderation Group ID" => $moderationGuid, "Moderation Event Type" => $moderationType));
    }
    $sql = "UPDATE
              wtNode
            SET
              __lockedForModeration = $moderationType
            WHERE
              __guid = {$this->m_guid}";
    if(!wtmysqlquery($sql)) {
      print $sql;
      print mysql_error();
    }

    // email the moderators
    $results = Array();
    $q = Array();
    $q["Path"] = "$moderationGuid/*";
    $q["Node Type"] = "Contact";
    $q["Results Array"] = &$results;
    $GLOBALS["WT"]->query($q);

    $subject = "Content Requires Moderation";
    $message = "<html><body>";
    $message .= "The following changes require moderation:<br/><br/>";
    $message .= $description . "<br/><br/>";
    $message .= '<a href="http://www.webtemplate.com.au">http://www.webtemplate.com.au</a>';
    $message .= "</body></html>";

    $emailList = "";
    foreach($results as $result) {
      if($emailList != "") {
        $emailList .= ",";
      }
      $emailList .= $result["Email Address"];
    }
    
    $mail = new WTMail();
    $mail->setTo($emailList);
    $mail->setFrom("content@webtemplate.com.au", "WebTemplate");
    $mail->setContent($subject, $message, true);
    $mail->send();

  }


  /**
   *  Set the attributes from form submission in the office
   *
   *  @method setAttributesFromForm
   *  @private
   *  @param {Array} attributes
   */

  function setAttributesFromForm($attributes) 
  {


    $saveAsDraft = false;
    if($_REQUEST["formaction"] == "Save Draft") {
      $saveAsDraft = true;
    }

    if($this->m_typeName == "wtNode") {
      if(array_key_exists("nodeName", $attributes)) {
        $attributes["Node Name"] = $attributes["nodeName"];
        if(get_magic_quotes_gpc()) {
          $attributes["Node Name"] = stripslashes($attributes["Node Name"]);
        }
      }
    }
    $sql = "SELECT
              wtAttribute.*
            FROM
              wtType, wtAttribute, wtNode
            WHERE
              wtNode.__guid = wtAttribute.__guid
              AND wtNode.__deleted = 0
              AND wtAttribute.typeGuid = wtType.__guid
              AND wtType.`Type Name` = '" . mysql_escape_string($this->m_typeName) . "'
              AND wtType.__active <> 0";
    $query = wtmysqlquery($sql);
    print mysql_error();
    while($row = mysql_fetch_array($query)) {
      $value = $GLOBALS["WT"]->getControlFormValue("attr" . $row["__guid"], $row, $attributes);

      if($value !== false) {
        if($row["Attribute Type ID"] == 8) {
          $attributes[$row["Attribute Name"] . " ID"] = $value;
        } else if($row["Attribute Type ID"] == 9) {
          $attributes[$row["Attribute Name"] . " IDs"] = $value;
        } else {
          $attributes[$row["Attribute Name"]] = $value;
        }
      } else {
      }
    }


    return $this->setAttributes($attributes, true, $saveAsDraft);
  }



  /**
   *  Set the attributes of a node
   *
   *  @method setAttributes
   *  @param {Array} attributes An associative array of attributes
   *  @param {boolean} [log=true] Log the event
   *  @param {boolean} [saveAsDraft] Save as draft rather than making the changes immediately
   */
  function setAttributes($attributes, $log = true, $saveAsDraft = false) 
  {
    if($GLOBALS["WTSITEID"] == 11227 || $GLOBALS["WTSITEID"] == 11238) {
      if($this->m_typeName != "wtModule") {
//        $GLOBALS["WT"]->debugMessage($this->m_typeName . " " . $this->m_guid);
        WTCache::clearCache();
      }
    }
    if(!$this->userHasPermission("write")) {
      return false;
    }



    // test if already locked, should prob test if its the same user modifying the record
    $alreadyLockedForModeration = false;

    // if moderation is enabled, find the moderation chain responsible for this node
    $moderationChainGuid = 0;
    if($GLOBALS["WT"]->getModerationEnabled()) {
      $moderationChainGuid = $this->getModerationChainGuid();
      $alreadyLockedForModeration = $this->isLockedForModeration() != 0;
      if($alreadyLockedForModeration) {
        $moderationChainGuid = 0;
      }
    }

    // is it the moderator or the global admin making the changes?
    if($moderationChainGuid != 0) {
      $currentUser = $GLOBALS["WT"]->getCurrentUser();

      if($currentUser->isMemberOf($moderationChainGuid) || $GLOBALS["WT"]->m_contactIsAdministrator) {
        $moderationChainGuid = 0;
      }

    }


    $currentAttributes = Array();
    if($this->m_typeName != 'wtNode') 
    {
      $sql = "SELECT
                *
              FROM
                `{$this->m_typeName}`
              WHERE
                __guid = {$this->m_guid}
                AND __active = 1";
      $query = wtmysqlquery($sql);
      $currentAttributes = mysql_fetch_assoc($query);
    }

   
    $sql = "SELECT
              wtAttribute.*
            FROM 
              wtAttribute, wtNode
            WHERE
              wtAttribute.__guid = wtNode.__guid
              AND wtNode.__deleted = 0
              AND typeGuid = {$this->m_typeGuid}";


    $attributesChanged = true;
    $changes = '';
    $oldValues = Array();
    $newValues = Array();

    // need to check if any attributes have actually changed, also if moderation is enabled need to copy attributes that haven't been set
    if(true) { //$moderationChainGuid != 0 && !$alreadyLockedForModeration) {
      $attributesChanged = false;
      $query = wtmysqlquery($sql);
      while($row = mysql_fetch_array($query)) {
        $attributeName = $row["Attribute Name"];
        $attributeTypeID = $row["Attribute Type ID"];

        if($attributeTypeID == WTSINGLECHOICEOPTIONS) {
          if($moderationChainGuid != 0 && !array_key_exists($attributeName, $attributes) && !array_key_exists($attributeName . " ID", $attributes)) {
            $attributes[$attributeName . " ID"] = $currentAttributes[$attributeName . " ID"];
          }

          if(array_key_exists($attributeName, $attributes) && $attributes[$attributeName] != $currentAttributes[$attributeName]) {
            $attributesChanged = true;
            $changes .= $attributeName . " Changed<br>";
            $oldValues[$attributeName] = $currentAttributes[$attributeName];
          } else if(array_key_exists($attributeName . " ID", $attributes) && $attributes[$attributeName . " ID"] != $currentAttributes[$attributeName . " ID"]) {
            $attributesChanged = true;
            $changed .= $attributeName . " Changed<br>";
            $oldValues[$attributeName] = $currentAttributes[$attributeName];
          }

        } else if($attributeTypeID == WTMULTIPLECHOICEOPTIONS) {
          if($moderationChainGuid != 0 && !array_key_exists($attributeName, $attributes) && !array_key_exists($attributeName . " IDs", $attributes)) {
            $attributes[$attributeName . " IDs"] = $currentAttributes[$attributeName . " IDs"];
          }

          if(array_key_exists($attributeName, $attributes) && $attributes[$attributeName] != $currentAttributes[$attributeName]) {
            $attributesChanged = true;
            $changes .= $attributeName . " Changed<br>";
            $oldValues[$attributeName] = $currentAttributes[$attributeName];
          } else if(array_key_exists($attributeName . " IDs", $attributes) && $attributes[$attributeName . " IDs"] != $currentAttributes[$attributeName . " IDs"]) {
            $attributesChanged = true;
            $changes .= $attributeName . " Changed<br>";
            $oldValues[$attributeName] = $currentAttributes[$attributeName];
          }

        } else if($attributeTypeID == WTDATE) {
          if($moderationChainGuid != 0 && !array_key_exists($attributeName, $attributes)) {
            $attributes[$attributeName] = $currentAttributes[$attributeName];
          }

          if(array_key_exists($attributeName, $attributes) && strtotime($attributes[$attributeName]) != strtotime($currentAttributes[$attributeName])) {
            $attributesChanged = true;
            $changes .= $attributeName . " Changed<br>";
            $oldValues[$attributeName] = $currentAttributes[$attributeName];

          }

        } else {
          if($moderationChainGuid != 0 && !array_key_exists($attributeName, $attributes)) {
            $attributes[$attributeName] = $currentAttributes[$attributeName];
          }

          if(array_key_exists($attributeName, $attributes) && $attributes[$attributeName] !== $currentAttributes[$attributeName]) {
            $attributesChanged = true;
            $changes .= $attributeName . " Changed<br>";
            $oldValues[$attributeName] = $currentAttributes[$attributeName];
          }
        }
      }
      if(!$attributesChanged) {

        $create = false;
        $createSql = "SELECT
                        COUNT(*)
                      FROM
                        `{$this->m_typeName}`
                      WHERE
                        __guid = {$this->m_guid}
                        AND __latest = 1";
        $createQuery = wtmysqlquery($createSql);
        $createRow = mysql_fetch_array($createQuery);
        if($createRow[0] == 0) {
          $create = true;
        }

        if(!$create) {
          return true;
        }
      }
    }

//exit("");


    $query = wtmysqlquery($sql);
    $sql = "";
    
    $siteDirectory = WTConfig::get("Site Details/Site Directory");

    while($row = mysql_fetch_array($query)) {
      $attributeSettings = Array();
      $attributeName = $row["Attribute Name"];
      parse_str($row["Attribute Settings"], $attributeSettings);


      if($row["Attribute Type ID"] == WTFILE || $row["Attribute Type ID"] == WTIMAGE) {
        // File or Image
        if(array_key_exists($row["Attribute Name"], $attributes)) {
          if($sql != "") {
            $sql .= ",";
          }
          $sql .= "`{$row["Attribute Name"]}` = '" . mysql_escape_string($attributes[$row["Attribute Name"]]) . "'";
          WTNode::setNodeUse($this->m_guid, $row["__guid"], $attributes[$row["Attribute Name"]]);
          if(array_key_exists($attributeName, $oldValues)) {
            $newValues[$attributeName] = $attributes[$attributeName];
          }
        }

      } else if($row["Attribute Type ID"] == WTSINGLECHOICEOPTIONS && (array_key_exists($row["Attribute Name"], $attributes) || array_key_exists($row["Attribute Name"] . " ID", $attributes))) {
        // Single Choise Options

        $options = "";
        if(array_key_exists("options", $attributeSettings)) {
          $options = $attributeSettings["options"];
        }

        $extraOptions = Array();
        if(array_key_exists("extraOptions", $attributeSettings)) {
          $extraOptions = $GLOBALS["WT"]->getOptionsFromString($attributeSettings["extraOptions"]);
        }

        $optionValue = "";
        $optionID = 0;
        if(isset($attributes[$row["Attribute Name"]])) {
          $optionValue = $attributes[$row["Attribute Name"]];
          $optionID = $GLOBALS["WT"]->getOptionID($options, $optionValue);
          if(in_array($optionValue, $extraOptions)) {
            foreach($extraOptions as $k => $v) {
              if($v == $optionValue) {
                $optionID = $k;
                break;
              }
            }
          }
        } else if(isset($attributes[$row["Attribute Name"] . " ID"])) {
          $optionID = $attributes[$row["Attribute Name"] . " ID"];
          $optionValue = $GLOBALS["WT"]->getOptionValue($options, $optionID);
          if(array_key_exists($optionID, $extraOptions)) {
            $optionValue = $extraOptions[$optionID];
          }
        }


        if($options != "" && !array_key_exists($options, $GLOBALS["WTBUILTINOPTIONS"])) {
          WTNode::setNodeUse($this->m_guid, $row["__guid"], $optionID);
        }

        if($sql != "") {
          $sql .= ",";
        }
        $sql .= "`{$row["Attribute Name"]} ID` = '" . mysql_escape_string($optionID) . "',";
        $sql .= "`{$row["Attribute Name"]}` = '" . mysql_escape_string($optionValue) . "'";   
        if(array_key_exists($attributeName, $oldValues)) {
          $newValues[$attributeName] = $optionValue;
        }     
      } else if($row["Attribute Type ID"] == WTMULTIPLECHOICEOPTIONS && array_key_exists($row["Attribute Name"] . " IDs", $attributes)) {
        // multiple choice options
        $values = trim($attributes[$row["Attribute Name"] . " IDs"]);
        $optionValues = "";
        if(array_key_exists("options", $attributeSettings)) {
          $options = $attributeSettings["options"];
        }

        $extraOptions = Array();
        if(array_key_exists("extraOptions", $attributeSettings)) {
          $extraOptions = $GLOBALS["WT"]->getOptionsFromString($attributeSettings["extraOptions"]);
        }


        $nodeOptionGuids = "";
        $valuesArray = explode(",", $values);
        foreach($valuesArray as $value) {
          if(trim($value) != "") {
            if($optionValues != "") {
              $optionValues .= ", ";
            }

            if(array_key_exists($value, $extraOptions)) {
              $optionValues .= $extraOptions[$value];
            } else {
              if($nodeOptionGuids != "") {
                $nodeOptionGuids .= ",";
              }
              $nodeOptionGuids .= $value;
              $optionValues .= $GLOBALS["WT"]->getOptionValue($options, $value);
            }
          }
        }
       
        if($options != "" && !array_key_exists($options, $GLOBALS["WTBUILTINOPTIONS"])) { 
          WTNode::setNodeUse($this->m_guid, $row["__guid"], $nodeOptionGuids);
        }

        if($sql != "") {
          $sql .= ",";
        }

        $sql .= "`{$row["Attribute Name"]} IDs` = '" . mysql_escape_string($values) . "', `{$row["Attribute Name"]}` = '" . mysql_escape_string($optionValues) . "'";
        if(array_key_exists($attributeName, $oldValues)) {
          $newValues[$attributeName] = $optionValues;
        }
      } else {
        if(isset($attributes[$row["Attribute Name"]]) && $row["Attribute Type"] != "Static" ) {
          if($sql != "") {
            $sql .= ",";
          }
          $attributeValue = $attributes[$row["Attribute Name"]];
          $attributeValue = str_replace($siteDirectory . "__files", "__files", $attributeValue);
          $sql .= "`{$row["Attribute Name"]}` = '" . mysql_escape_string($attributeValue) . "'";
          if(array_key_exists($attributeName, $oldValues)) {
            $newValues[$attributeName] = $attributes[$attributeName];
          }
        }
      }

    }

  

    if($this->m_typeName != "wtNode" && ($this->m_luid == 0 || $moderationChainGuid != 0 || $saveAsDraft)) {
      if($sql != "") {
        $sql .= ",";
      }        
      $sql .= " __created = NOW(), __guid = {$this->m_guid}";
      if($moderationChainGuid != 0 || $saveAsDraft) {
        $sql .= ", __active = 0";
      }
    }

    
   
    if($sql != "") {
      $create = false;
      $createSql = "SELECT
                      COUNT(*) 
                    FROM
                      `{$this->m_typeName}`
                    WHERE
                      __guid = {$this->m_guid}
                      AND __latest = 1";
      $createQuery = wtmysqlquery($createSql);
      $createRow = mysql_fetch_array($createQuery);
      if($createRow[0] == 0) {
        $create = true;
      }

      if($create || ($moderationChainGuid != 0 ) || $saveAsDraft) {
        $sql = "INSERT INTO `{$this->m_typeName}` SET $sql";

      } else {
//        $sql = "UPDATE `{$this->m_typeName}` SET $sql WHERE __luid = {$this->m_luid}";
        $sql = "UPDATE `{$this->m_typeName}` SET $sql WHERE __guid = {$this->m_guid} AND __latest = 1";
      }



      if(!wtmysqlquery($sql)) {
        print "ERROR in $sql\n";
        print mysql_error();
        print "\n";
        return false;
      }


/*      $changes = "";
      $changes = '<table class="moderationchanges">';
      $changes .= '<tr>';
      $changes .= '<th>Attribute</th><th>Old Value</th><th>New Value</th>';
      $changes .= '</tr>';
      foreach($oldValues as $key => $value) {
        $changes .= '<tr>';
        $changes .= '<td>' . $key . '</td>';
        $changes .= '<td>' . $oldValues[$key] . '</td>';
        $changes .= '<td>' . $newValues[$key] . '</td>';
        $changes .= '</tr>';
      }
      $changes .= '</table>';
*/
      $valueChanges = Array();
      $valueChanges["old"] = $oldValues;
      $valueChanges["new"] = $newValues;
      $changes = serialize($valueChanges);



      if($moderationChainGuid != 0 || $saveAsDraft) {// && !$alreadyLockedForModeration) {

        $luid = mysql_insert_id();

        $sql = "UPDATE
                  `{$this->m_typeName}`
                SET
                  __latest = 0
                WHERE
                  __guid = {$this->m_guid}
                  AND __luid <> {$luid}";
        if(!wtmysqlquery($sql)) {
          print $sql;
          print mysql_error();
        }

        // 1 == create, 2 = edit, 3 = delete
        $lockedForModeration = 1;
        if(!$create) {
          $lockedForModeration = 2;
        }

/*
        $changes = '<table class="moderationchanges">';
        $changes .= '<tr>';
        $changes .= '<th>Attribute</th><th>Old Value</th><th>New Value</th>';
        $changes .= '</tr>';
        foreach($oldValues as $key => $value) {
          $changes .= '<tr>';
          $changes .= '<td>' . $key . '</td>';
          $changes .= '<td>' . $oldValues[$key] . '</td>';
          $changes .= '<td>' . $newValues[$key] . '</td>';
          $changes .= '</tr>';
        }
        $changes .= '</table>';
*/
       
        //$this->logModerationEvent($lockedForModeration, $changes);
      }

      if($this->m_typeName != "wtEvent") {
        $eventType = 1;
        if(!$create) {
          $eventType = 2;
        }

        if($saveAsDraft) {
          $eventType = -$eventType;
        }
        if($log) {
          $this->logEvent($eventType, $moderationChainGuid, $changes);
        }
      }

      if($this->m_luid == 0) {
        $this->m_luid = mysql_insert_id();
        $sql = "UPDATE 
                  wtNode
                SET
                  __luid = {$this->m_luid}
                WHERE
                  __guid = {$this->m_guid}";
         if(!wtmysqlquery($sql)) {
           print $sql;
           print mysql_error();
         }
      }
      
    }


    if(array_key_exists("Node Name", $attributes)) {
      $this->setName($attributes["Node Name"]);
    } else {
      $attributes = $this->getAttributes();
      $sql = "SELECT
                `Node Naming Rule`
              FROM
                wtType
              WHERE
                wtType.__guid = {$this->m_typeGuid}";
      $query = wtmysqlquery($sql);
      if($row = mysql_fetch_row($query)) {


        $attributes["__guid"] = $this->m_guid;
        $nodeName = WTTemplate::compileAndEvaluate($row[0], $attributes);

        if(trim($nodeName) != "") {
          $this->setName($nodeName);
        }
/*        if(array_key_exists($row[0], $attributes)) {
          $this->setName($attributes[$row[0]]);
        }
*/
      }
    }

    
/*
    $keywords = mysql_escape_string($this->getKeywords());
    $sql = "SELECT 
              COUNT(nodeKeywordsID)
            FROM
              tblNodeKeywords
            WHERE
              nodeGuid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    $row = mysql_fetch_row($query);
    if($row[0] == 0) {
      $sql = "INSERT INTO
                tblNodeKeywords (nodeGuid, nodeKeywords)
              VALUES
                ($this->m_guid, '$keywords')";
    } else {
      $sql = "UPDATE
                tblNodeKeywords
              SET  
                nodeKeywords = '$keywords'
              WHERE
                nodeGuid = {$this->m_guid}";
    }
    wtmysqlquery($sql);
    print mysql_error();
*/    
    //DEH:20080401: __modified... tad naughty in implementation... ;)
    @wtmysqlquery('update wtNode set __modified=NOW() where __guid='.$this->m_guid);

    $this->setKeywords();
    return true;
  
  }

  /**
   *  Set the keywords for the node. Used for search
   *
   *  @method setKeywords
   *
   */

  function setKeywords() 
  {
    $keywords = mysql_escape_string($this->getKeywords());
    $sql = "SELECT
              COUNT(nodeKeywordsID)
            FROM
              tblNodeKeywords
            WHERE
              nodeGuid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    $row = mysql_fetch_row($query);
    if($row[0] == 0) {
      $sql = "INSERT INTO
                tblNodeKeywords (nodeGuid, nodeKeywords)
              VALUES
                ($this->m_guid, '$keywords')";
    } else {
      $sql = "UPDATE
                tblNodeKeywords
              SET
                nodeKeywords = '$keywords'
              WHERE
                nodeGuid = {$this->m_guid}";
    }
    wtmysqlquery($sql);
    print mysql_error();
  }


  /**
   *  If the node is being moderated, get the next group in the moderation chain
   *
   *  @method getNextModerationGroupID
   *  @return {int} The guid of the next moderation group
   */
  function getNextModerationGroupID() {

    if($GLOBALS["WT"]->m_contactIsAdministrator) {
      // all changes are approved by global admin
      return 0;
    }

    $currentUser = $GLOBALS["WT"]->getCurrentUser();
    $currentUserGroups = explode(",", $currentUser->getGroups("Admin Group"));

    $moderationChainGuid = 0;
    $sql = "SELECT
              __moderationChainGuid
            FROM
              wtNode
            WHERE
              __guid = " . $this->m_guid;
    $query = mysql_query($sql);
    if($row = mysql_fetch_array($query)) {
      $moderationChainGuid = $row["__moderationChainGuid"];
    }

    $currentModerationGroup = 0;
    // get the current moderation group
    $sql = "SELECT
              `Moderation Group ID`
            FROM
              wtEvent
            WHERE
              `Node ID` = " . $this->m_guid . "
              AND Status = 0";
    $query = mysql_query($sql);
    if($row = mysql_fetch_array($query)) {
      $currentModerationGroup = $row["Moderation Group ID"];
    }

    $moderationChainNode = $GLOBALS["WT"]->getNode($moderationChainGuid);
    if($moderationChainNode->m_typeName == "Moderation Chain") {

      $moderationGroups = Array();
      $query = Array("Node Type" => "Group", "Path" => "$moderationChainGuid/*", "Results Array" => &$moderationGroups);
      $GLOBALS["WT"]->query($query);
      $lastModerationGroupID = 0;
      $nextModerationGroupID = false;
      foreach($moderationGroups as $moderationGroup) {

        /*
        if($lastModerationGroupID == $currentModerationGroup) {
          return $moderationGroup["__guid"];
        }
        */
        if($nextModerationGroupID == 0) {
          $nextModerationGroupID = $moderationGroup["__guid"];
        }
        if($lastModerationGroupID != 0 && in_array($lastModerationGroupID, $currentUserGroups)) {
          $nextModerationGroupID = $moderationGroup["__guid"];
        }

        $lastModerationGroupID = $moderationGroup["__guid"];
      }

      if(in_array($lastModerationGroupID, $currentUserGroups)) {
        $nextModerationGroupID = 0;
      }


      return $nextModerationGroupID;
/*
      if($lastModerationGroupID == $currentModerationGroup) {
        return 0;
      }
*/
//      return false;

    } else {
      if($currentModerationGroup == $moderationChainGuid) {
        return 0;
      }
      return $moderationChainGuid;
    }
  }



  /**
   *  Reject the changes
   *  
   *  @method rejectChanges
   *  @param {String} [reason] The reason for the rejection
   *  @param {boolean} [sendEmail=false] Set to true to send the moderation email
   */
  function rejectChanges($reason = "", $sendEmail = false)
  {
    //create the event
    $sql = "SELECT
              *
            FROM
              wtEvent
            WHERE
              Status = 0
              AND `Node ID` = " . $this->m_guid;
    $query = mysql_query($sql);

    if($row = mysql_fetch_array($query)) {

      // create a new event
      $moderationGroupID = $row["Moderation Group ID"];
      $moderationGroup = $GLOBALS["WT"]->getNode($moderationGroupID);

      $currentUser = $GLOBALS["WT"]->getCurrentUser();
      $contact = mysql_escape_string($currentUser->getAttribute("Username"));
      $contactID = $currentUser->m_guid;
      $event = mysql_escape_string($row["Event"]);
      $description = $row["Description"];

      $description .= "<br/>Rejected by " . $currentUser->getAttribute("Username") . " (" . $moderationGroup->getName() . ") " . date("j/M/Y H:i");
      $description .= "<br/>Reason: $reason";

      $description = mysql_escape_string($description);
      $nodeID = $row["Node ID"];
      $eventID = $row["Event ID"];
      $eventType = $row["Event Type"];
      $pageID = $row["Page ID"];

      $status = 1;

      $sql = "INSERT INTO wtEvent (
                `Event`,
                `Event ID`,
                `Description`,
                `Contact`,
                `Contact ID`,
                `Node ID`,
                `Page ID`,
                `Event Type`,
                `Status`,
                `Moderation Group ID`,
                __created
              ) VALUES (
                '$event',
                $eventID,
                '$description',
                '$contact',
                '$contactID',
                $nodeID,
                $pageID,
                $eventType,
                $status,
                $moderationGroupID,
                NOW()
              )";
      mysql_query($sql);
      print mysql_error();
    }


    $lockedForModeration = 0;
    $sql = "SELECT
              __lockedForModeration
            FROM
              wtNode
            WHERE
              __guid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    if($row = mysql_fetch_row($query)) {
      $lockedForModeration = $row[0];
    }

// TODO: if moderation reason is create, prob should just delete the node
    if($lockedForModeration == 1 || $lockedForModeration == 2) {
      $sql = "DELETE FROM
                `{$this->m_typeName}`
              WHERE
                __guid = {$this->m_guid}
                AND __active = 0
                AND __latest = 1";
      if(!wtmysqlquery($sql)) {
        print $sql;
      }
      $sql = "UPDATE
                `{$this->m_typeName}`
              SET
                __latest = 1
              WHERE
                __guid = {$this->m_guid}
                AND __active = 1";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }
      $sql = "UPDATE
                wtNode
              SET
                __lockedForModeration = 0
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }


    }
    if($lockedForModeration == 3) {
      $sql = "UPDATE
                wtNode
              SET
                __lockedForModeration = 0
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }
    }

    $sql = "UPDATE
              wtEvent
            SET
              Status = 1
            WHERE
              Status = 0
              AND `Node ID` = " . $this->m_guid;
    wtmysqlquery($sql);
    print mysql_error();

    if($sendEmail) {
      $this->sendModerationRejectedEmail($eventID, $reason);
    }

  }

  /**
   *  Approve changes made
   *
   *  @method approveChanges
   *  @param {boolean} [sendEmail=false]
   */
  function approveChanges($sendEmail = false)
  {
    $eventID = 0;
    $lockedForModeration = 0;
    $sql = "SELECT
              __lockedForModeration
            FROM
              wtNode
            WHERE
              __guid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    if($row = mysql_fetch_row($query)) {
      $lockedForModeration = $row[0];
    }

    // is there another moderation group?
    $nextModerationGroup = $this->getNextModerationGroupID();
//    if($nextModerationGroup !== false && $nextModerationGroup != 0) {
      // get the current event

    $sql = "SELECT
              *
            FROM
              wtEvent
            WHERE
              Status = 0
              AND `Node ID` = " . $this->m_guid;
    $query = mysql_query($sql);
    if($row = mysql_fetch_array($query)) {

      // create a new event
      $moderationGroupID = $row["Moderation Group ID"];
      $moderationGroup = $GLOBALS["WT"]->getNode($moderationGroupID);

      $currentUser = $GLOBALS["WT"]->getCurrentUser();
      $contact = mysql_escape_string($currentUser->getAttribute("Username"));
      $contactID = $currentUser->m_guid;
      $event = mysql_escape_string($row["Event"]);
      $description = $row["Description"];

      $description .= "<br>Approved by " . $currentUser->getAttribute("Username") . " (" . $moderationGroup->getName() . ") " . date("j/M/Y H:i");
      $description = mysql_escape_string($description);
      $nodeID = $row["Node ID"];
      $eventID = $row["Event ID"];
      $eventType = $row["Event Type"];
      $pageID = $row["Page ID"];

      $status = 1;
      if($nextModerationGroup !== false && $nextModerationGroup != 0) {
        $status = 0;
      }

      $sql = "INSERT INTO wtEvent (
                `Event`,
                `Event ID`,
                `Description`,
                `Contact`,
                `Contact ID`,
                `Node ID`,
                `Page ID`,
                `Event Type`,
                `Status`,
                `Moderation Group ID`,
                __created
              ) VALUES (
                '$event',
                $eventID,
                '$description',
                '$contact',
                '$contactID',
                $nodeID,
                $pageID,
                $eventType,
                $status,
                $nextModerationGroup,
                NOW()
              )";
      mysql_query($sql);
      print mysql_error();
      $newEventID = mysql_insert_id();


      if($nextModerationGroup !== false && $nextModerationGroup != 0) {
        $sql = "UPDATE
                  wtEvent
                SET
                  Status = 1
                WHERE
                  __luid = " . $row["__luid"];

        wtmysqlquery($sql);
        print mysql_error();


        $this->sendModerationRequiredEmail($newEventID);

        return;

      }

    }

    if($lockedForModeration == 1 || $lockedForModeration == 2) {
      $newLuid = 0;
      $sql = "SELECT
                __luid
              FROM
                `{$this->m_typeName}`
              WHERE
                __guid = {$this->m_guid}
                AND __latest = 1";
      $query = wtmysqlquery($sql);
      if($row = mysql_fetch_row($query)) {
        $newLuid = $row[0];
      }
      $sql = "UPDATE
                `{$this->m_typeName}`
              SET
                __active = 1
              WHERE
                __luid = $newLuid";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }
      $sql = "UPDATE
                `{$this->m_typeName}`
              SET
                __active = 0
              WHERE
                __guid = {$this->m_guid}
                AND __luid <> $newLuid";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }
      $sql = "UPDATE
                wtNode
              SET
                __luid = $newLuid,
                __lockedForModeration = 0
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }
    }

    if($lockedForModeration == 3) {
      $moderationEnabled = $GLOBALS["WT"]->getModerationEnabled();
      $GLOBALS["WT"]->setModerationEnabled(false);
      $this->deleteNode();
      $GLOBALS["WT"]->setModerationEnabled($moderationEnabled);
      $sql = "UPDATE
                wtNode
              SET
                __lockedForModeration = 0
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }

    }

    $sql = "UPDATE
              wtEvent
            SET
              Status = 1
            WHERE
              Status = 0
              AND `Node ID` = " . $this->m_guid;
    wtmysqlquery($sql);
    print mysql_error();

    if($sendEmail) {
       
      $this->sendModerationApprovedEmail($eventID);
    }

  }


/*

  function rejectChanges($reason = "") 
  {
    $lockedForModeration = 0;
    $sql = "SELECT
              __lockedForModeration
            FROM
              wtNode
            WHERE
              __guid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    if($row = mysql_fetch_row($query)) {
      $lockedForModeration = $row[0];
    }

// TODO: if moderation reason is create, prob should just delete the node
    if($lockedForModeration == 1 || $lockedForModeration == 2) {
      $sql = "DELETE FROM
                `{$this->m_typeName}`
              WHERE
                __guid = {$this->m_guid}
                AND __active = 0
                AND __latest = 1";
      if(!wtmysqlquery($sql)) {
        print $sql;
      }
      $sql = "UPDATE
                `{$this->m_typeName}`
              SET
                __latest = 1
              WHERE
                __guid = {$this->m_guid}
                AND __active = 1";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }
      $sql = "UPDATE
                wtNode
              SET
                __lockedForModeration = 0
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }  
      

    }

    if($lockedForModeration == 3) {
      $sql = "UPDATE
                wtNode
              SET
                __lockedForModeration = 0
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }
    }    

    $sql = "UPDATE
              wtEvent
            SET
              Status = 1
            WHERE
              Status = 0
              AND `Node ID` = " . $this->m_guid;
    wtmysqlquery($sql);
    print mysql_error();

  }

  function approveChanges() 
  {
    $lockedForModeration = 0;
    $sql = "SELECT
              __lockedForModeration
            FROM 
              wtNode
            WHERE
              __guid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    if($row = mysql_fetch_row($query)) {
      $lockedForModeration = $row[0];
    }

    if($lockedForModeration == 1 || $lockedForModeration == 2) {
      $newLuid = 0;
      $sql = "SELECT
                __luid 
              FROM
                `{$this->m_typeName}`
              WHERE
                __guid = {$this->m_guid}
                AND __latest = 1";
      $query = wtmysqlquery($sql);
      if($row = mysql_fetch_row($query)) {
        $newLuid = $row[0];
      } 
      $sql = "UPDATE
                `{$this->m_typeName}`
              SET
                __active = 1
              WHERE
                __luid = $newLuid";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }
      $sql = "UPDATE
                `{$this->m_typeName}`
              SET
                __active = 0
              WHERE
                __guid = {$this->m_guid}   
                AND __luid <> $newLuid";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }  
      $sql = "UPDATE 
                wtNode
              SET
                __luid = $newLuid,
                __lockedForModeration = 0
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }




      }  


    }

    if($lockedForModeration == 3) {
      $moderationEnabled = $GLOBALS["WT"]->getModerationEnabled();
      $GLOBALS["WT"]->setModerationEnabled(false);
      $this->deleteNode();
      $GLOBALS["WT"]->setModerationEnabled($moderationEnabled);
      $sql = "UPDATE
                wtNode
              SET
                __lockedForModeration = 0
              WHERE
                __guid = {$this->m_guid}";
      if(!wtmysqlquery($sql)) {
        print $sql;
        print mysql_error();
      }

    }
    
    $sql = "UPDATE
              wtEvent
            SET
              Status = 1
            WHERE
              Status = 0 
              AND `Node ID` = " . $this->m_guid;
    wtmysqlquery($sql);
    print mysql_error();
     
  }
*/


  /**
   *  Create a child node
   *
   *  @method createChild
   *  @param {String} typeName
   *  @param {Array} [attributes=NULL] The attributes of the child node
   *  @return {Object} The child node
   *
   */
  function createChild($typeName, $attributes = NULL) 
  {
    return $GLOBALS["WT"]->createNode($this->m_guid, $typeName, $attributes);
  }

  /**
   *  Get the keywords for the node to be used in searches
   *
   *  @method getKeywords
   *  @return {String} keywords
   */
  function getKeywords() 
  { 
    $attributes = $this->getAttributes();

    $keywords = "";
    $sql = "SELECT
              wtAttribute.*
            FROM
              wtAttribute, wtNode
            WHERE
              wtAttribute.__guid = wtNode.__guid
              AND wtNode.__deleted = 0
              AND typeGuid = {$this->m_typeGuid}";
    $query = wtmysqlquery($sql);
    while($row = mysql_fetch_array($query)) {
      $attributeType = $GLOBALS["WTBUILTINOPTIONS"]["wtAttributeTypes"][$row["Attribute Type ID"]];
      switch($attributeType) {
        default:
          $keywords .= " " . $attributes[$row["Attribute Name"]];
          break;
        case 'Rich Text':
          $keywords .= " " . strip_tags($attributes[$row["Attribute Name"]]);
          break;
      }
      
    }
    return $keywords;
  }

  function setPossibleChildTypes($childTypes) 
  {
    $sql = "UPDATE
              wtNode
            SET
              __possibleChildTypes = '" . mysql_escape_string(trim($childTypes)) . "'
            WHERE
              __guid = {$this->m_guid}";
    if(!wtmysqlquery($sql)) {
      print $sql . "\n";
      print mysql_error();
    }
  }

  function getPossibleChildTypes() 
  {
    $sql = "SELECT
              __possibleChildTypes
            FROM 
              wtNode
            WHERE
              __guid = {$this->m_guid}";
    $query = wtmysqlquery($sql);
    $row = mysql_fetch_row($query);
    if($row[0] != "" && $row[0] != "Default") {
      $childTypes = $row[0];
      if($childTypes != "None" && $childTypes != "All") {
        $childTypeArray = explode(",", $childTypes);
        $childTypeGuids = "";
        foreach($childTypeArray as $childType) {
          $childType = trim($childType);
          if($childType != "") {
            if($childType == "wtNode") {
              if($childTypeGuids != "") {
                $childTypeGuids .= ",";
              }
              $childTypeGuids .= "0";
            } else {
              $childTypeNode = $GLOBALS["WT"]->getNode("/Config/Node Types/$childType");
              if($childTypeNode != NULL) {
                if($childTypeGuids != "") {
                  $childTypeGuids .= ",";
                }
                $childTypeGuids .= $childTypeNode->m_guid;
              }
            }
          }
        }
      }
    } else {
      if($this->m_typeGuid == 0) {
        $childTypes = "All";
      } else {
        $typeNode = $GLOBALS["WT"]->getNode($this->m_typeGuid);
        $childTypes = $typeNode->getAttribute("Child Types");
      }
    }

  
    if($childTypes == "All") {
      $childTypeGuids = $GLOBALS["WT"]->query(Array("Path" => "/Config/Node Types/*", "Order By" => "__name", "Node Type" => "wtType"), "guidListCallback");
      $childTypeGuids = "0," . $childTypeGuids;
   } else if($childTypes == "None") {
      $childTypeGuids = "";
    } else if($childTypes == "Custom") {
      $childTypeGuids = $typeNode->getAttribute("Custom Child Types IDs");
    }

    $childTypeArray = Array();
    $childTypes = explode(",", $childTypeGuids);
    foreach($childTypes as $childTypeGuid) {
      if(trim($childTypeGuid) != "") {
        if($childTypeGuid == 0) {
          $typeNode = $GLOBALS["WT"]->getNode("/Config/Node Types/wtType");
          $typeNode->m_name = "wtNode";
          $typeNode->m_guid = 0;
        } else {
          $typeNode = $GLOBALS["WT"]->getNode($childTypeGuid);
        }
        $childTypeArray[$typeNode->m_name] = $typeNode;
      }
    }    
    ksort($childTypeArray);
    return $childTypeArray;
  }


  /**
   *  Create an associative array of a nodes properties and its childrens properties<br/>
   *  Useful for saving the state of a page
   *
   *  @method export
   *  @return {Array} The node and its children as a structure of arrays
   */

  function export($ignore = "", $guid = 0)
  {
    if($guid == 0) {
      $guid = $this->m_guid;
    }
    $nodeProperties = Array();

    $node = $GLOBALS["WT"]->getNode($guid);
    $attributes = $node->getAttributes();

    $nodeProperties["__guid"] = $node->m_guid;
    $nodeProperties["Attributes"] = $attributes;

    $nodeChildren = Array();
    $sql = "SELECT
              *
            FROM
              wtNode
            WHERE
              __deleted = 0
              AND __parentGuid = $guid";
    if($ignore != "") {
      $sql .= " AND __typeGuid <> $ignore";
    }
    $query = mysql_query($sql);
    while($row = mysql_fetch_array($query)) {
      $nodeChildren[] = $this->export($ignore, $row["__guid"]);
    }

    $nodeProperties["Children"] = $nodeChildren;

    return $nodeProperties;
  }


  /**
   * restore a node to a previous version from its exported node
   *
   *  @method restoreNode
   *  @param {Array} node The data structure representing an exported node
   *  
   */
function restoreNode($node, $ignore = 0) {
  $attributes = $node["Attributes"];
  $guid = $attributes["__guid"];

  $nodeExists = false;
  // see if the node still exists
  $sql = "SELECT
            *
          FROM
            wtNode
          WHERE
            __guid = $guid";
  $query = mysql_query($sql);
  if($row = mysql_fetch_array($query)) {
    $nodeExists = true;
  }

  if($nodeExists) {
    $sql = "UPDATE
              wtNode
            SET
              __nodeIsHolderForGuid = " . $attributes["__nodeIsHolderForGuid"] . ",
              __parentGuid = " . $attributes["__parentGuid"] . ",
              __typeGuid = " . $attributes["__typeGuid"] . ",
              __name = '" . mysql_escape_string($attributes["__name"]) . "',
              __uri = '" . mysql_escape_string($uri) . "',
              __hidden = " . $attributes["__hidden"] . ",
              __deleted = " . $attributes["__deleted"] . "
            WHERE
              __guid = $guid";

    if(!mysql_query($sql)) {
      print $sql;
      print mysql_error();
    }
  }

  $thenode = $GLOBALS["WT"]->getNode($guid);

  $typeName = $thenode->m_typeName;


  if($typeName != 'wtNode') {

    $sql = "DESCRIBE `$typeName`";
    $query = mysql_query($sql);

    $typeAttributes = Array();
    while($row = mysql_fetch_row($query)) {
      if($row[0] != "__luid" && $row[0] != "__latest" && $row[0] != "__deleted") {
        $typeAttributes[] = $row[0];
      }
    }


    $sql = "__latest = 1, __active = 1";
    foreach($attributes as $key => $value) {
      if($key[0] != '_' && $key[1] != '_') {
        if(in_array($key, $typeAttributes)) {
          $sql .= ",";
          $sql .= "`$key` = '" . mysql_escape_string($value) . "'";
        }
      }
    }

    $sql = "UPDATE `$typeName` SET $sql WHERE __active = 1 AND __guid = $guid";

    if(!mysql_query($sql)) {
      print $sql;
      print mysql_error();
    }
  }


  // get the node
  $thenode = $GLOBALS["WT"]->getNode($guid);


  $children = $node["Children"];

  $childrenGuidList = "0";
  foreach($children as $child) {
    $childrenGuidList .= "," . $child["Attributes"]["__guid"];
    $this->restoreNode($child, $ignore);
  }

  // need to delete children that weren't originally children
  $sql = "SELECT
            *
          FROM
            wtNode
          WHERE
            __parentGuid = $guid
            AND __guid NOT IN ($childrenGuidList)
            AND __deleted = 0
            AND __typeGuid <> $ignore";

  $query = mysql_query($sql);
  while($row = mysql_fetch_array($query)) {
    $sql = "UPDATE
              wtNode
            SET
              __deleted = 1
            WHERE
              __guid = {$row["__guid"]}";
    if(!mysql_query($sql)) {
      print $sql;
      print mysql_error();
    }
  }
}








}

?>