<?php

// Multiple inclusion protector
if (!defined("CLASS_ATKTREENODE_INC"))
{
  define("CLASS_ATKTREENODE_INC",1);
  /**
    * Extension on the atkNode class. Here you will find all 
    * functions for the tree view. If you want to use the treeview, you must define the atkTreeNode 
    * instead of atkNode. Example:
    * class classname extends atkTreeNode
    * {
    *      $this->atkTreeNode("nodeclass",NF_TREE|NF_COPY); 
    *
    * }
    * @author Martin Roest  (martin@ibuildings.nl) and Sandy Pleyte (sandy@achievo.com)
    */
  
  class atkTreeNode extends atkNode
  {
    var $m_groupIndex = array();

    /**
        * Constructor
        * @Param $name Node name
        * @Param $flags Node flags
        */
    function atkTreeNode($name,$flags=0)
    {
      if($this->hasFlag(NF_TREE_NO_ROOT_ADD))
      {
       //
      }
      $this->atkNode($name,$flags);    
    }  
    
    /**
          * Admin page displays records and the actions that can be performed on
          * them (edit, delete) in a Treeview
          */
    function adminPage()
    {
      global $g_securityManager,$g_layout;

      $g_layout->ui_top(text('title_'.$this->m_type.'_tree'));
      $g_layout->output('<br>');

      $adminHeader = $this->adminHeader();
      if ($adminHeader!="")
      {
        $g_layout->output($adminHeader."<br><br>");
      }

      $this->debug("Entering treeview page.");
      $this->selectDb($this->m_postvars['atkfilter'],$this->m_table.".".$this->m_parent,"",$this->m_listExcludes);

      $g_layout->output("<table border=\"1\">");

      if (!$this->hasFlag(NF_NO_ADD) && $this->hasFlag(NF_ADD_LINK) && $this->allowed("add"))
      {
        $addurl = $this->stickyUrl("dispatch.php3?atkaction=add&atkfilter=".rawurlencode($this->m_parent.".".$this->m_primaryKey[0]."='0'")."&atkreturnurl=".rawurlencode("dispatch.php3?atknodetype=".$this->m_type."&atkaction=admin"));
        $g_layout->output(url($addurl,text("clickheretoadd_prefix").text($this->m_type).text("clickheretoadd_postfix")).'<br><br>');
      }

      $this->indexGroups();

      $group = $this->treeGetGroup(0);
   //   var_dump($group);
      $this->treePrintGroup($group, 0);

      $g_layout->output("</table>");      
      $g_layout->ui_bottom();
      $this->debug("Generating treeview finished!");
    }

    function indexGroups()
    {
      $current = $this->m_records[0][$this->m_parent][$this->m_primaryKey[0]];
      if ($current=="") $current=0;
      $this->m_groupIndex[$current]["first"]=0;
      for($i=0;$i<count($this->m_records);$i++)
      {
        $walker = $this->m_records[$i][$this->m_parent][$this->m_primaryKey[0]];
        if ($walker=="") $walker = 0;
        if ($walker!=$current)
        {
          $this->m_groupIndex[$current]["last"]=$i-1;
          $current = $walker;
          $this->m_groupIndex[$current]["first"]=$i;
        } 
      }
      $this->m_groupIndex[$walker]["last"]=count($this->m_records)-1;

 //     var_dump($this->m_groupIndex);
    }

    /**
         * Get the groups with a parent ID
         * @param $parent
         * @return $group Array()
         */
    function treeGetGroup($parent)
    {
      $group = array();
      for($i=$this->m_groupIndex[$parent]["first"];$i<=$this->m_groupIndex[$parent]["last"];$i++)
      {
        if($this->m_records[$i][$this->m_parent][$this->m_primaryKey[0]] == $parent)
          $group[] = $this->m_records[$i];
      }
      return $group;
    }

    /**
          * Print the groups and subgroup
          * @param $group
          * @param $depth
          */
    function treePrintGroup($group,$depth)
    {
      $depth++;
      for($i=0;$i<count($group);$i++)
      {
        $this->treePrint($group[$i],$depth);
        $subgroup = $this->treeGetGroup($group[$i][$this->m_primaryKey[0]]);
        if ( count($subgroup) > 0 )
        {
          $this->treePrintGroup($subgroup,$depth);
        }
      }
    }

    /**
         * Print the group
         * @param $group
         * @param $depth
         */
    function treePrint($group, $depth)
    {
      global $g_layout;
       
      $tab = "";
      $depth_org = $depth;
      while (--$depth>0)              // just to make things look nice
      {
        $tab .= "--";
      }
      if(!empty($tab))
      {
        $tab.="> ";
      }
      $g_layout->output("<tr>");

      if(empty($group[$this->m_parent]))
      {
        $g_layout->td("<b>".$tab.$this->descriptor($group)."</b>");
      }
      else
      {
        $g_layout->td($tab.$this->descriptor($group));
      }
      $g_layout->output('<td>');
      $g_layout->output(url("dispatch.php3?atknodetype=".$this->m_type."&atkaction=add&&atkreturnurl=".rawurlencode('dispatch.php3?atknodetype='.$this->m_type.'&atkaction=admin')."&atkfilter=".$this->m_parent.".".$this->m_primaryKey[0].rawurlencode("='".$group[$this->m_primaryKey[0]]."'"), text("add")));
      $g_layout->output(url("dispatch.php3?atkaction=edit&atknodetype=".$this->m_type."&atkselector=".$this->primaryKey($group), text("edit")));
      if(($this->hasFlag(NF_COPY)&&$this->allowed("add")&&!$this->hasflag(NF_TREE_NO_ROOT_COPY))||$depth_org!=1)
      {    
        $g_layout->output(url("dispatch.php3?atkaction=copy&atknodetype=".$this->m_type."&atkselector=".$this->primaryKey($group), text("copy")));
      }
      if($this->hasFlag(NF_TREE_NO_DELETE)&&$depth_org!=1)
      {
        $g_layout->output( url("dispatch.php3?atkaction=delete&atknodetype=".$this->m_type."&atkselector=".$this->primaryKey($group), text("delete")));
      }
      $g_layout->output("</td></tr>");
    }
     
    /** 
          * Copies a record and the Childs if there are any
          *
          *@param $selector The 'where' clause that indicates which records to select.
          */
    function copyDb($selector)
    {
      $this->selectDb($selector);
      $tmprecs = $this->m_records;
      if(count($tmprecs)>0)
      {      
        $this->addDb();
        atkdebug("copyDb - Main Record added");
        $newparent=$this->m_records[$this->m_currentRec][$this->m_primaryKey[0]];
        atkdebug('CopyDbCopychildren('.$this->m_parent.'='.$tmprecs[0][$this->m_primaryKey[0]].','.$newparent.')');
        $this->copyChildren($this->m_table.'.'.$this->m_parent.'='.$tmprecs[0][$this->m_primaryKey[0]], $newparent);
      }
      else
      {
        atkdebug("No records found with Selector: $selector - $parent");
      }
      return "";
    }
    
    /**
        * This is a recursive function to copy the childeren from a parent.
        *
        * @param $selector Selector
        * @param $parent Parent ID
        */
    function copyChildren($selector, $parent="")
    {
      $this->selectDb($selector);
      $tmprecs = $this->m_records;
      if(count($tmprecs)>0)
      {        
        atkdebug("Loop ".count($tmprecs)." Childrecords - current ".$this->m_currentRec." - New parent id = $parent");
        for($i=0;$i<count($tmprecs);$i++)
        {  
          $tmprecs[$i][$this->m_parent] = array(""=>"",$this->m_primaryKey[0]=>$parent);
          $this->m_currentRec = 0;
          $this->m_records[0] = $tmprecs[$i];
          $this->addDb();
          $newrec = $this->m_records[0];
          atkdebug("Child Record added");
          $newparent=$newrec[$this->m_primaryKey[0]];
          atkdebug('CopyChildren('.$this->m_parent.'='.$tmprecs[$i][$this->m_primaryKey[0]].','.$newparent.')');
          $this->copyChildren($this->m_table.'.'.$this->m_parent.'='.$tmprecs[$i][$this->m_primaryKey[0]], $newparent);
        }
      }
      else
      {
        atkdebug("No records found with Selector: $selector - $parent");
      }
      return "";
    }
    
    /**
         * delete record from the database also the childrecords.
         * todo: instead of delete, set the deleted flag.
         * @param $selector Selector
         */
    function deleteDb($selector)
    {
      global $g_db;
      atkdebug("Retrieve record");
      $this->selectDb($selector);
      $tmpparentrecs = $this->m_records;
      $parent = $tmpparentrecs[0][$this->m_primaryKey[0]];
      atkdebug("Check for child records");
      $this->selectDb($this->m_table.'.'.$this->m_parent.'='.$parent);
      $tmprecs = $this->m_records;
      if(count($tmprecs)>0)
      {
        atkdebug('DeleteChilderen('.$this->m_table.'.'.$this->m_parent.'='.$parent.','.$parent.')');
        $this->deleteChilderen($this->m_table.'.'.$this->m_parent.'='.$parent,$parent);
      }
      $query = "DELETE FROM ".$this->m_table." WHERE ".$selector;
      $this->debug("deleteDb - query: ".$query);
      $g_db->query($query);
      // todo: instead of delete, set the deleted flag.
    }
    
    /**
         * Recursive function whitch deletes all the child records of a parent
         *
         * @Param $selector Selector
         * @Param $parent Parent
         */
    function deleteChilderen($selector,$parent)
    {
      global $g_db;
      atkdebug("Check for child records of the Child");
      $this->selectDb($this->m_table.'.'.$this->m_parent.'='.$parent);
      $tmprecs = $this->m_records;
      if(count($tmprecs)>0)
      {
        for($i=0;$i<count($tmprecs);$i++)
        {
          $parent = $tmprecs[$i][$this->m_primaryKey[0]];
          atkdebug('DeleteChilderen('.$this->m_table.'.'.$this->m_parent.'='.$tmprecs[$i][$this->m_primaryKey[0]].','.$parent.')');
          $this->deleteChilderen($this->m_table.'.'.$this->m_parent.'='.$tmprecs[$i][$this->m_primaryKey[0]],$parent);
        }
      }
      $query = "DELETE FROM ".$this->m_table." WHERE ".$selector;
      $this->debug("deleteChilderen - query: ".$query);
      $g_db->query($query);
      // todo: instead of delete, set the deleted flag.
    }
  }
}
 
?>
