一个树形图的类(非常完整)

<?php
/***********************
约定:树型图的
   父节点:pid
   子节点:id
   名称: name
   备注:memo
auther: kevin
date: 2008-9-20
desc:
    根节点默认为0(约定).
    function get_Tree():  生成树型结构菜单。
    function get_SelectTtree($root='ROOT') : 生成树型下拉列表。 ($root: 根节点名称)。
    function get_AllCID($cid): 查询所有子节点,包含节点本身。 ($cid:被查节点id)。
    function get_AllPID($id):查询所有父节点,包含节点本身。
    function get_SqlDeptId($id,$field='id') $id:部门id. $field: 部门id字段。 返回sql语句条件。: return " and $field in ('1','2','3')"
***********************/
class Wms_Tree
{
    var $table='ot_departments';/**set default table name**/
    var $debug = false;/** debug modle**/
    var $url ='';/** url address. default "" **/
    var $target_url='';/** init target utl . it running when open window **/
    var $memo=false;/** 是否开启提示“memo“,默认不显示提示 **/
    var $target ='';/** init target name **/
    var $selectedNode = 1;
    var $otherOnclick='';/**附加单击事件**/

    function Wms_Tree($table='ot_departments',$debug=false){
         $this->table = $table;
         $this->debug = $debug;
    }
    function Set_Url($url){
        $this->url = $url;
    }
    function Has_Memo($bool=false){
        $this->memo = $bool;
    }
    function Set_Target($target){
        $this->target = $target;
    }
    function findAllData(){
        global $db;
        $tree = array();
        $rs = $db->query("select * from ".$this->table." where 1 ");
        while($data = $db->fetchNextObject($rs)){
            $tree[] = array('id'=>$data->id,'pid'=>$data->pid,'name'=>$data->name,'memo'=>$data->memo);
        }
        return $tree;
    }
    function findDeptData(){
        global $db;
        $tree = array();
        $rs = $db->query("select * from ".$this->table." where 1 and pid != '0'");
        while($data = $db->fetchNextObject($rs)){
            $tree[] = array('id'=>$data->id,'pid'=>$data->pid,'name'=>$data->name,'memo'=>$data->memo);
        }
        return $tree;
    }
    function FindApplicationData(){
        //require_once("../language/".$GLOBALS['config']['language'][$lang_select]);
        require_once("language/lang_ch.php");
        require_once("modules.php");
        $tree = array();
        $tree[] = array('id'=>1,'pid'=>0,'name'=>'首页','app1'=>'','app2'=>'','app3'=>'index');
        $i=2;
        foreach ($applications as $key=>$a){
            $tree[] = array('id'=>$i,'pid'=>1,'name'=>$app_lang[($a['name'])],'app1'=>$key,'app2'=>'','app3'=>'');
            $a_i=$i;
            $i++;
            foreach ($applicationList[$key] as $keyt=>$t){
                   $tree[] = array('id'=>$i,'pid'=>$a_i,'name'=>$app_lang[($t['name'])],'app1'=>$key,'app2'=>$keyt,'app3'=>'');
                   $t_i=$i;
                   $i++;
                   foreach($applicationBean[$keyt] as $keyb=>$b){
                       $tree[] = array('id'=>$i,'pid'=>$t_i,'name'=>$app_lang[($b['name'])],'app1'=>$key,'app2'=>$keyt,'app3'=>$keyb);
                       $i++;
                   }
            }
        }
        return $tree;
    }
    function get_Application_Tree(){
        global $app_lang;
        $str ="";
        $tree = array();
        $tree = $this->FindApplicationData();
        foreach ($tree as $t){
            $myurl='';
            if($t['app3']!='') $myurl="help.php?app1=".$t['app1']."&app2=".$t['app2']."&app3=".$t['app3'];
            $str.= "d.add(".$t['id'].",".$t['pid'].",'".$t['name']."','".$myurl."','','".$this->target."');";
        }
        return "<div class='dtree'>
            <script language='javascript' type='text/javascript' src='js/helptree.js'></script>
            <link rel='StyleSheet' href='".$GLOBALS['style']."css/dtree.css' type='text/css'>
            <p></p>
            <script language='javascript' type='text/javascript'>
              d = new dTree('d');
              d.add(0,-1,'总公司11--最高','');
              ".$str."
              document.write(d);
              </script>
            </div>";
            return $str;
    }
    function radioTree($tree,$tree_name='d',$tag='',$haveCheck=true){
        foreach($tree as $key=>$value){
            $pidarr[] = $value['pid'];
        }
        $str ="";
        if($tree_name=='d') $check_id="chk_depts[]";
        else $check_id="chk_depts_".$tree_name."[]";/**处理扩展,checkbox的id/name需要变动,保留以前**/
        foreach ($tree as $key=>$t){
            if($haveCheck){
            if($t['disabled']=='true') $disabled = 'disabled';/**处理某些节点不让选择,根据CTO要求。**/
            else $disabled='';
            if($tag=='') $check_value=$t['id'];
            else $check_value=$t[$tag];
            
            if(isset($t['chkd'])) $chkd = $t['chkd'];/**判断该选项是否已经选择。**/
            if($key != 0 )
                if(in_array($t['id'],$pidarr)){
                    $node_name='';
                }else{
                    $node_name="<input type=radio id=\'".$check_id."\' name=\'".$check_id."\' value=\'".$t['tag']."\'  ".$disabled." ".$chkd.">";
                }
                
            }
            else{
                $node_name='';
            }
        $myurl='';
            if($this->url !='') $myurl=$this->url;

            $str.= $tree_name.".add(".$t['id'].",".$t['pid'].",'".$node_name.$t['name']."','".$myurl."','".($this->memo? $t['memo'] : '')."','');";
        }
        if($this->otherOnclick !='')
                   $this->target_url=$tree_name.".selectedId";
        return "<div class='dtree'>
        <script language='javascript' type='text/javascript' src='js/dtree.js'></script>
        <link rel='StyleSheet' href='".$GLOBALS['style']."css/dtree.css' type='text/css'>
        <script language='javascript' type='text/javascript'>
        ".$tree_name." = new dTree('".$tree_name."');
              ".$tree_name.".checkname='".$check_id."';
              ".$tree_name.".otherOnclick='".$this->otherOnclick."';
        ".$tree_name.".add(0,-1,'总公司11--最高','');
        ".$str."
        document.write(".$tree_name.");
        </script>
        </div>";
        return $str;
    }
    function findReportAllData($rid){
        global $db;
        $tree = array();
        $rs = $db->query("select * from ".$this->table." where  id  not in (select depart_id from app_depart_table where report_id='".$rid."')");
        while($data = $db->fetchNextObject($rs)){
            $tree[] = array('id'=>$data->id,'pid'=>$data->pid,'name'=>$data->name,'memo'=>$data->memo);
        }
        return $tree;
    }
    function get_ReportTree($id){
        global $app_lang;
        $str ="";
        $tree = array();
        $tree = $this->findReportAllData($id);
        foreach ($tree as $t){
            if($t['id']=='1')
            $str.= "d.add(".$t['id'].",".$t['pid'].",'"."<input type=checkbox id=\'chk_depts[]\' name=\'chk_depts[]\' value=\'".$t['id']."\' disabled>".$t['name']."','".(empty($this->url)? '' : ($this->url.$t['id']))."','".($this->memo? $t['memo'] : '')."','".$this->target."');";
            else
            $str.= "d.add(".$t['id'].",".$t['pid'].",'"."<input type=checkbox id=\'chk_depts[]\' name=\'chk_depts[]\' value=\'".$t['id']."\' >".$t['name']."','".(empty($this->url)? '' : ($this->url.$t['id']))."','".($this->memo? $t['memo'] : '')."','".$this->target."');";
        }
        if($this->target !='' && $this->url !='')
                   $this->target_url="<script>window.".$this->target.".location.href = '".$this->url."'+d.selectedId;</script>";
        return "<div class='dtree'>
            <script language='javascript' type='text/javascript' src='js/dtree.js'></script>
            <link rel='StyleSheet' href='".$GLOBALS['style']."css/dtree.css' type='text/css'>
            <p><a href='javascript: d.openAll();'>".$app_lang['expand_all']."</a> | <a href='javascript: d.closeAll();'>".$app_lang['collapse_all']."</a></p>
            <script language='javascript' type='text/javascript'>
              d = new dTree('d');
              d.add(0,-1,'总公司11--最高','');
              ".$str."
              document.write(d);
              </script>
            </div>";
            return $str;
    }
    /**
    *  CheckBoxTree($tree,$tree_name='d',$tag='')
    * 描述: 生成checkbox树型结构选择。
    * 参数: $tree :符合树型结构数组。
    *           $tree_name: 树型图名称,默认为d(扩展一个页面存在多个树型图的问题)。
    *           $tag: 自定义存储id值。默认为‘’空。某前没有用到。
    *扩展:$tree_name: 树型图名称,默认为d(扩展一个页面存在多个树型图的问题)。
    *            checkbox id根据$tree_name变动。
    * 返回:html脚本。
    */
    function CheckBoxTree($tree,$tree_name='d',$tag='',$haveCheck=true){
        $str ="";
        if($tree_name=='d') $check_id="chk_depts[]";
        else $check_id="chk_depts_".$tree_name."[]";/**处理扩展,checkbox的id/name需要变动,保留以前**/
        foreach ($tree as $t){
            if($haveCheck){
            if($t['disabled']=='true') $disabled = 'disabled';/**处理某些节点不让选择,根据CTO要求。**/
            else $disabled='';
            if($tag=='') $check_value=$t['id'];
            else $check_value=$t[$tag];
            
            if(isset($t['chkd'])) $chkd = $t['chkd'];/**判断该选项是否已经选择。**/
            $node_name="<input type=checkbox id=\'".$check_id."\' name=\'".$check_id."\' value=\'".$t['id']."\'  οnclick=\'javascript:".$tree_name.".check(this);\' ".$disabled." ".$chkd.">";
            }else{
                $node_name='';
            }
            $myurl='';
            if($this->url !='') $myurl=$this->url;

            $str.= $tree_name.".add('".strtolower($t['id'])."','".$t['pid']."','".$node_name.$t['name']."','".$myurl."','".($this->memo? $t['memo'] : '')."','');";
        }
        if($this->otherOnclick !='')
                   $this->target_url=$tree_name.".selectedId";
        return "<div class='dtree'>
            <script language='javascript' type='text/javascript' src='js/dtree.js'></script>
            <link rel='StyleSheet' href='".$GLOBALS['style']."css/dtree.css' type='text/css'>
            <script language='javascript' type='text/javascript'>
              ".$tree_name." = new dTree('".$tree_name."');
              ".$tree_name.".checkname='".$check_id."';
              ".$tree_name.".otherOnclick='".$this->otherOnclick."';
              ".$tree_name.".add(0,-1,'总公司11--最高','');
              ".$str."
              document.write(".$tree_name.");
              </script>
            </div>";
            return $str;
    }
    function CheckBoxTreeDept($tree,$tree_name='d',$tag='',$haveCheck=true){
        $str ="";
        if($tree_name=='d') $check_id="chk_depts[]";
        else $check_id="chk_depts_".$tree_name."[]";/**处理扩展,checkbox的id/name需要变动,保留以前**/
        foreach ($tree as $key=>$t){
            if($haveCheck){
            if($t['disabled']=='true') $disabled = 'disabled';/**处理某些节点不让选择,根据CTO要求。**/
            else $disabled='';
            if($tag=='') $check_value=$t['id'];
            else $check_value=$t[$tag];
            
            if(isset($t['chkd'])) $chkd = $t['chkd'];/**判断该选项是否已经选择。**/
            if($key != 0)
                $node_name="<input type=checkbox id=\'".$check_id."\' name=\'".$check_id."\' value=\'".$t['id']."\'  οnclick=\'javascript:".$tree_name.".check(this);\' ".$disabled." ".$chkd.">";
            }
            else{
                $node_name='';
            }
        $myurl='';
            if($this->url !='') $myurl=$this->url;

            $str.= $tree_name.".add(".$t['id'].",".$t['pid'].",'".$node_name.$t['name']."','".$myurl."','".($this->memo? $t['memo'] : '')."','');";
        }
        if($this->otherOnclick !='')
                   $this->target_url=$tree_name.".selectedId";
        return "<div class='dtree'>
        <script language='javascript' type='text/javascript' src='js/dtree.js'></script>
        <link rel='StyleSheet' href='".$GLOBALS['style']."css/dtree.css' type='text/css'>
        <script language='javascript' type='text/javascript'>
        ".$tree_name." = new dTree('".$tree_name."');
              ".$tree_name.".checkname='".$check_id."';
              ".$tree_name.".otherOnclick='".$this->otherOnclick."';
        ".$tree_name.".add(0,-1,'总公司11--最高','');
        ".$str."
        document.write(".$tree_name.");
        </script>
        </div>";
        return $str;
    }
    function get_Tree(){
        global $app_lang;
        $str ="";
        $tree = array();
        $tree = $this->findAllData();
        foreach ($tree as $t){
            $str.= "d.add(".$t['id'].",".$t['pid'].",'".$t['name']."','".(empty($this->url)? '' : ($this->url.$t['id']))."','".($this->memo? $t['memo'] : '')."','".$this->target."');";
        }
        if($this->target !='' && $this->url !='')
                   $this->target_url="<script>window.".$this->target.".location.href = '".$this->url."'+d.selectedId;</script>";
        return "<div class='dtree'>
            <script language='javascript' type='text/javascript' src='js/dtree.js'></script>
            <link rel='StyleSheet' href='".$GLOBALS['style']."css/dtree.css' type='text/css'>
            <p><a href='javascript: d.openAll();'>".$app_lang['expand_all']."</a> | <a href='javascript: d.closeAll();'>".$app_lang['collapse_all']."</a></p>
            <script language='javascript' type='text/javascript'>
              d = new dTree('d');
              d.add(0,-1,'总公司11--最高','');
              ".$str."
              document.write(d);
              </script>
            </div>";
            return $str;
    }
    function get_Dept(){
        global $app_lang;
        $str ="";
        $tree = array();
        $tree = $this->findAllData();
        $myurl='';
            if($this->url !='') $myurl=$this->url;

        foreach ($tree as $t){
            $str.= "d.add(".$t['id'].",".$t['pid'].",'".$t['name']."','".$myurl."','','');";
        }
        if($this->otherOnclick !='')
                   $this->target_url="d.selectedId";
        return "<div class='dtree'>
            <script language='javascript' type='text/javascript' src='js/dtree.js'></script>
            <link rel='StyleSheet' href='".$GLOBALS['style']."css/dtree.css' type='text/css'>
            <script language='javascript' type='text/javascript'>
              d = new dTree('d');
              d.otherOnclick='".$this->otherOnclick."';
              d.add(0,-1,'总公司11--最高','');
              ".$str."
              document.write(d);
              </script>
            </div>";
            return $str;
    }
     function get_SelectTtree($root='ROOT',$key='0',$HasRoot=false)
    {
        $tree = array();
        $tree = $this->findAllData();
        $tree = $this->array_to_tree($tree,'id','pid');
        $tree = $this->dumpArrayTree($tree);
       
       $result =array();
       if($HasRoot) $result[$key]=$root;
       foreach ($tree as $key){
           $result[($key['id'])] = $key['levelstr']." ".$key['name'];
       }
       return $result;
    }
     function get_SelectDeptTtree($root='DEPT',$key='0',$HasRoot=false)
    {
        $tree = array();
        $tree = $this->findDeptData();
        $tree = $this->array_to_dept_tree($tree,'id','pid');
        $tree = $this->dumpArrayTree($tree);
       
       $result =array();
       if($HasRoot) $result[$key]=$root;
       foreach ($tree as $key){
           $result[($key['id'])] = $key['levelstr']." ".$key['name'];
       }
       return $result;
    }
    function get_AllCID($cid)
    {
        $depts = array();
        $depts = $this->findAllData();
        $result=array();
        $this->findsub($depts,$cid,$result);
        return $result;
    }
    function get_AllPID($id)
    {
        $depts = array();
        $depts = $this->findAllData();
        return $this->findroot($depts,$id);
    }
    function get_SqlDeptId($id,$field='id')
    {
        if($field =='') return " and 0";
        $ids = array();
        $ids = $this->get_AllCID($id);
        $result = array();
        foreach ($ids as $a){
            $result[] = "'".$a."'";
        }
        return " and  ".$field." in (".implode(',',$result).")";

    }
    /*** 下面是class内部函数  **/
    function findroot($a,$id){
         foreach ($a as $aa){
             if($aa['id'] == $id){
                $d = $aa['pid'];
                break;
             }
         }
         if(!isset($d)) return -1;
         $str = array();
         $str[]= $id;
         $str[] = $d;
         while($d >0){
             foreach($a as $aa){
                if($aa['id']==$d){
                    $d = $aa['pid'];
                    if($d !=0) $str[] = $d;
                    break;
                }
            }
         }
         return $str;
    }

    function findsub($a,$ids,&$result){
       if(!is_array($ids))  $ids=array($ids);
       foreach ($ids as $d){
         $result[] = $d;
       }
       $dds =array();
       foreach ($ids as $d){
        foreach($a as $aa){
            if($aa['pid']==$d){
                $dds[] = $aa['id'];
            }
        }
       }
       if(empty($dds)) return $result;
       else $this->findsub($a,$dds,$result);
    }

    function array_to_tree($arr, $fid, $fparent = 'parent_id',$fchildrens = 'childrens', $returnReferences = false)
    {
      $pkvRefs = array();
      foreach ($arr as $offset => $row) {
         $pkvRefs[$row[$fid]] =&$arr[$offset];
     }
 
     $tree = array();
      foreach ($arr as $offset => $row) {
          $parentId = $row[$fparent];
          if ($parentId) {
              if (!isset($pkvRefs[$parentId])) { continue; }
             $parent =&$pkvRefs[$parentId];
              $parent[$fchildrens][] =& $arr[$offset];
          } else {
              $tree[] =&$arr[$offset];
         }
     }
      if ($returnReferences) {
          return array('tree' => $tree, 'refs' => $pkvRefs);
     } else {
          return $tree;
     }
  }
  function array_to_dept_tree($arr, $fid, $fparent = 'parent_id',$fchildrens = 'childrens', $returnReferences = false)
    {
      $pkvRefs = array();
        /*
        *    Yao edit (2009-12-23)
        *    $row[$fid]:    id;
        *    $offset:    数组指针
        *    $parentId:    pid值
        *    $this->set_logs($row[$fid].' and '.$offset)
        *    2009-10-29 22:10:07     100000 and 195
        *    2009-10-29 22:10:07     100001 and 196
        */
      foreach ($arr as $offset => $row) {
         $pkvRefs[$row[$fid]] =&$arr[$offset];
      }
 
    $tree = array();
      foreach ($arr as $offset => $row) {
            $parentId = $row[$fparent];
            if ($parentId) {
                if (isset($pkvRefs[$parentId])) {
                $parent =&$pkvRefs[$parentId];
                /*
                *    取出子节点放入数组
                *    2009-10-29 22:10:50     2 and 1 and Default
                */
                $parent[$fchildrens][] =& $arr[$offset];
                }else {
                /*
                *    取出子节点放入数组
                *    2009-10-29 23:10:09     1 and 0 and Company
                */
                $tree[] =&$arr[$offset];
                }
            }
     }
     if ($returnReferences) {
            return array('tree' => $tree, 'refs' => $pkvRefs);
     } else {
            return $tree;
     }
  }
    /**
 * 把一个Tree形数组转换成一个一维数组,用于方便地显示
 *
 * @param array  $tree 原始Tree形数组
 * @param array  $arr 二维数组
 * @param string $level 目录深度
 * @param string $T 上下均有项目的符号,可以是图片路径
 * @param string $L 这一级别中最末尾项目的符号,可以是图片路径
 * @param string $I 上级连接符,可以是图片路径
 * @param string $S 占位的空白符号,可以是图片路径
 *
 * 类似下面的效果
 * ├- 1
 * │  ├- 1.1
 * │  └- 1.2
 * └- 2
 */
    function dumpArrayTree($tree, $level=0, $T='├', $L='└', $I='│', $S=' ')
    {
       return $this->_makeLevelstr($this->_dumpArrayTree($tree, array(), $level, $T, $L, $I, $S), $T, $L, $I, $S);
    }


   function _dumpArrayTree($tree, $arr=array(), $level=0, $T='├', $L='└', $I='│', $S=' '){    
     foreach ($tree as $node) {
        $arr[] = $node;
        $arr[count($arr)-1]['level'] = $level;
        //如果存在下级类目,则去掉该键值,并加深一层类目深度
        if(isset($arr[count($arr)-1]['childrens'])) {
            unset($arr[count($arr)-1]['childrens']);
            $level = $level + 1;
        }
        //如果childrens仍有数据则递归一下
        if (isset($node['childrens'])) {
            $arr = $this->_dumpArrayTree($node['childrens'], $arr, $level, $T, $L, $I, $S);
            $level = $level - 1;
        }

    }
    
    return $arr;
    }

function _makeLevelstr($arr, $T, $L, $I, $S){    
    foreach ($arr as $key=>$value) {
        $arr[$key]['levelstr'] = '';
        
        //向下循环到数组尾部,寻找层特征
        $k = 0;
        $haveBrother = false;
        for($k=$key; $k<count($arr); $k++){
            
            if(isset($arr[$k+1])) {
            
                //有平级目录
                if($arr[$key]['level'] == $arr[$k+1]['level']){
                    $haveBrother = true;
                }
                //本级别结束
                if($arr[$key]['level'] > $arr[$k+1]['level']) {
                    break;
                }
            }
                    
        }

        if ($haveBrother) {            $arr[$key]['levelstr'] = $T;
            $arr[$key]['isend'] = false;        }else {
            $arr[$key]['levelstr'] = $L;
            // isend 为 true 意味着这个节点是本级最后一个节点
            $arr[$key]['isend'] = true;
        }
        
        
        // $spaceHere 用来记录连接线的形态,表示当前行第几级是空白
        $spaceHere = array();
        
        // 逐级向上循环
        for($k=$key-1;$k>=0;$k=$k-1){

            //如果$k是同级尾部isend=true
            if($arr[$k]['isend']){
                $spaceHere[$key][$arr[$k]['level']] = true;
            }
            // 判断到根后中断循环
            if($arr[$k]['level']==0){
                break;
            }
            
        }
        
        //根据级别判定显示连接线的显示
        $frontLine = '';
        for($j=0; $j<$value['level']; $j++){
            if(isset($spaceHere[$key][$j])){
                $frontLine .= $S . $S;
            }else{
                $frontLine .= $I . $S;
            }
        }
        $arr[$key]['levelstr'] = $frontLine . $arr[$key]['levelstr'];
        
        
    }
        return $arr;}

/**
 * 将一个数组的所有元素变为小写字母
 * @param array $arrin
 * @param array $arrout
 * @return $arrout
 */
function array_to_lower($arrin, $arrout = array())
{
    foreach ($arrin as $key=>$value) {
        if(is_array($value)){
            $arrout[$key] = $this->array_to_lower($arrin[$key], $arrout);
        }
        $arrout[$key] = strtolower($value);
    }
    return $arrout;
}

/**
 * 判断一个字符串是否是数组中的值
 *
 * @param string $find
 * @param arr $inarr
 */
function find_in_array($find, $inarr)
{
    return in_array($find, $this->_expArray($inarr));
}

/**
 * 返回一个多维数组的所有值组成的二维数组
 *
 * @param array $arrin
 * @param array $arrout
 * @return $arrout
 */
function _expArray($arrin, $arrout = array() )
{
    foreach ($arrin as $value) {
        if(is_array($value)){
            $arrout = $this->_expArray($value, $arrout);
        }else{            $arrout[] = $value;
        }    }
    return $arrout;    
}
}
?>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值