<?php


namespace library;

class Tree
{
    /**
     * 内容数组
     * @var array
     */
    public $data = array();

    /**
     * 节点数组
     * @var array
     */
    public $cateArray = array();

    public $res = array();

    public function __construct($arr = array())
    {
        $this->data = $arr;
        $this->res = '';
        return is_array($arr);
    }

    public function setNode($id, $value, $parent = 0)
    {
        $this->data[$id] = $value;
        $this->cateArray[$id] = $parent;
    }

    public function getAllChildrenNodes($id = 0,\Closure $compFunc = null,\Closure $retFunc = null)
    {
        $result = [];
        $children = array_keys($this->cateArray, $id);
        if ($id > 0 && $compFunc && $compFunc($this->data[$id])) {
            $result = $retFunc === null ? $id : $retFunc($this->data[$id]);
        } else if (count($children) > 0) {
            foreach ($children as $child) {
                $result = array_merge($result, $this->getAllChildrenNodes($child, $compFunc, $retFunc));
            }
        } else {
            $result = $retFunc === null ? $id: $retFunc($this->data[$id]);
        }
        return $result;
    }

    public function getChildsTree($id = 0)
    {
        $childs = array();
        foreach ($this->cateArray as $child => $parent) {
            if ($parent == $id) {
                $childs[$child] = $this->getChildsTree($child);
            }
        }
        return $childs;
    }


    public function getParentsTree($id = 0)
    {
        $parents = array();
        foreach ($this->cateArray as $child => $parent) {
            if ($child == $id) {
                $parents[$parent] = $this->getParentsTree($parent);
            }
        }
        return $parents;
    }

    public function getChilds($id = 0)
    {
        $childArray = array();
        $childs = $this->getChild($id);
        foreach ($childs as $child) {
            $childArray[] = $child;
            $childArray = array_merge($childArray, $this->getChilds($child));
        }
        return $childArray;
    }

    public function getChild($id)
    {
        $childs = array();
        foreach ($this->cateArray as $child => $parent) {
            if ($parent == $id) {
                $childs[$child] = $child;
            }
        }
        return $childs;
    }

    public function getParents($id)
    {
        $parentArray = array();
        $parents = $this->getParent($id);
        foreach ($parents as $parent) {
            $parentArray[] = $parent;
            $parentArray = array_merge($parentArray, $this->getParents($parent));
        }
        return $parentArray;
    }

    public function getParent($id)
    {
        $parents = array();
        foreach ($this->cateArray as $child => $parent) {
            if ($child == $id) {
                $parents[$parent] = $parent;
            }
        }
        return $parents;
    }

    //单线获取父节点
    public function getNodeLever($id)
    {
        $parents = array();
        if (key_exists($this->cateArray[$id], $this->cateArray)) {
            $parents[] = $this->cateArray[$id];
            $parents = array_merge($parents, $this->getNodeLever($this->cateArray[$id]));
        }
        return $parents;
    }

    public function getLayer($id, $preStr = '|-')
    {
        return str_repeat($preStr, count($this->getNodeLever($id)));
    }

    public function getValue($id)
    {
        return $this->data[$id];
    }

    //获取所有节点数据生成树
    public function getTreeShow($id = 0, $str = "|-")
    {
        if ($id != 0) {
            $str = $str . "|-";
        }
        //遍历所有数组检查parent是否有id
        foreach ($this->cateArray as $child => $parent) {
            //检查是否有相等的ID
            if ($parent == $id) {
                $showname = $this->getValue($child);
                if(is_string($showname)){
                    $this->res[$child] = $str . $showname;
                }else if(is_array($showname) && isset($showname['name'])){
                    $this->res[$child] = $str . $showname['name'];
                }else {
                    $this->res[$child] = $str . $child;
                }
                $this->getTreeShow($child, $str);
            }
        }
    }
}

//class Tree
//{
//    /**
//     * 生成树型结构所需要的2维数组
//     * @var array
//     */
//    public $arr = array();
//
//    /**
//     * 生成树型结构所需修饰符号,可以换成图片
//     * @var array
//     */
//    public $icon = array('│', '├', '└');
//    public $nbsp = " ";
//
//    /**
//     * @access private
//     */
//    public $ret = '';
//
//    /**
//     * 构造函数,初始化类
//     * @param array 2维数组,例如:
//     * array(
//     *      1 => array('id'=>'1','parentid'=>0,'name'=>'一级栏目一'),
//     *      2 => array('id'=>'2','parentid'=>0,'name'=>'一级栏目二'),
//     *      3 => array('id'=>'3','parentid'=>1,'name'=>'二级栏目一'),
//     *      4 => array('id'=>'4','parentid'=>1,'name'=>'二级栏目二'),
//     *      5 => array('id'=>'5','parentid'=>2,'name'=>'二级栏目三'),
//     *      6 => array('id'=>'6','parentid'=>3,'name'=>'三级栏目一'),
//     *      7 => array('id'=>'7','parentid'=>3,'name'=>'三级栏目二')
//     *      )
//     */
//    public function init($arr = array())
//    {
//        $this->arr = $arr;
//        $this->ret = '';
//        return is_array($arr);
//    }
//
//    /**
//     * 得到父级数组
//     * @param int
//     * @return array
//     */
//    public function get_parent($myid)
//    {
//        $newarr = array();
//        if (!isset($this->arr[$myid])) return false;
//        $pid = $this->arr[$myid]['parentid'];
//        $pid = $this->arr[$pid]['parentid'];
//        if (is_array($this->arr)) {
//            foreach ($this->arr as $id => $a) {
//                if ($a['parentid'] == $pid) $newarr[$id] = $a;
//            }
//        }
//        return $newarr;
//    }
//
//    /**
//     * 得到子级数组
//     * @param int
//     * @return array
//     */
//    public function get_child($myid)
//    {
//        $a = $newarr = array();
//        if (is_array($this->arr)) {
//            foreach ($this->arr as $id => $a) {
//                if ($a['parentid'] == $myid) $newarr[$id] = $a;
//            }
//        }
//        return $newarr ? $newarr : false;
//    }
//
//    /**
//     * 得到当前位置数组
//     * @param int
//     * @return array
//     */
//    public function get_pos($myid, &$newarr)
//    {
//        $a = array();
//        if (!isset($this->arr[$myid])) return false;
//        $newarr[] = $this->arr[$myid];
//        $pid = $this->arr[$myid]['parentid'];
//        if (isset($this->arr[$pid])) {
//            $this->get_pos($pid, $newarr);
//        }
//        if (is_array($newarr)) {
//            krsort($newarr);
//            foreach ($newarr as $v) {
//                $a[$v['id']] = $v;
//            }
//        }
//        return $a;
//    }
//
//    /**
//     * 得到树型结构
//     * @param int ID,表示获得这个ID下的所有子级
//     * @param string 生成树型结构的基本代码,例如:"<option value=\$id \$selected>\$spacer\$name</option>"
//     * @param int 被选中的ID,比如在做树型下拉框的时候需要用到
//     * @return string
//     */
//    public function get_tree($myid, $str, $sid = 0, $adds = '', $str_group = '')
//    {
//        $number = 1;
//        $child = $this->get_child($myid);
//        if (is_array($child)) {
//            $total = count($child);
//            foreach ($child as $id => $value) {
//                $j = $k = '';
//                if ($number == $total) {
//                    $j .= $this->icon[2];
//                } else {
//                    $j .= $this->icon[1];
//                    $k = $adds ? $this->icon[0] : '';
//                }
//                $spacer = $adds ? $adds . $j : '';
//                $selected = $id == $sid ? 'selected' : '';
//                @extract($value);
//                $parentid == 0 && $str_group ? eval("\$nstr = \"$str_group\";") : eval("\$nstr = \"$str\";");
//                $this->ret .= $nstr;
//                $nbsp = $this->nbsp;
//                $this->get_tree($id, $str, $sid, $adds . $k . $nbsp, $str_group);
//                $number++;
//            }
//        }
//        return $this->ret;
//    }
//
//    /**
//     * 同上一方法类似,但允许多选
//     */
//    public function get_tree_multi($myid, $str, $sid = 0, $adds = '')
//    {
//        $number = 1;
//        $child = $this->get_child($myid);
//        if (is_array($child)) {
//            $total = count($child);
//            foreach ($child as $id => $a) {
//                $j = $k = '';
//                if ($number == $total) {
//                    $j .= $this->icon[2];
//                } else {
//                    $j .= $this->icon[1];
//                    $k = $adds ? $this->icon[0] : '';
//                }
//                $spacer = $adds ? $adds . $j : '';
//
//                $selected = $this->have($sid, $id) ? 'selected' : '';
//                @extract($a);
//                eval("\$nstr = \"$str\";");
//                $this->ret .= $nstr;
//                $this->get_tree_multi($id, $str, $sid, $adds . $k . ' ');
//                $number++;
//            }
//        }
//        return $this->ret;
//    }
//
//    /**
//     * @param integer $myid 要查询的ID
//     * @param string $str 第一种HTML代码方式
//     * @param string $str2 第二种HTML代码方式
//     * @param integer $sid 默认选中
//     * @param integer $adds 前缀
//     */
//    public function get_tree_category($myid, $str, $str2, $sid = 0, $adds = '')
//    {
//        $number = 1;
//        $child = $this->get_child($myid);
//        if (is_array($child)) {
//            $total = count($child);
//            foreach ($child as $id => $a) {
//                $j = $k = '';
//                if ($number == $total) {
//                    $j .= $this->icon[2];
//                } else {
//                    $j .= $this->icon[1];
//                    $k = $adds ? $this->icon[0] : '';
//                }
//                $spacer = $adds ? $adds . $j : '';
//
//                $selected = $this->have($sid, $id) ? 'selected' : '';
//                @extract($a);
//                if (empty($html_disabled)) {
//                    eval("\$nstr = \"$str\";");
//                } else {
//                    eval("\$nstr = \"$str2\";");
//                }
//                $this->ret .= $nstr;
//                $this->get_tree_category($id, $str, $str2, $sid, $adds . $k . ' ');
//                $number++;
//            }
//        }
//        return $this->ret;
//    }
//
//    /**
//     * 同上一类方法,jquery treeview 风格,可伸缩样式(需要treeview插件支持)
//     * @param $myid 表示获得这个ID下的所有子级
//     * @param $effected_id 需要生成treeview目录数的id
//     * @param $str 末级样式
//     * @param $str2 目录级别样式
//     * @param $showlevel 直接显示层级数,其余为异步显示,0为全部限制
//     * @param $style 目录样式 默认 filetree 可增加其他样式如'filetree treeview-famfamfam'
//     * @param $currentlevel 计算当前层级,递归使用 适用改函数时不需要用该参数
//     * @param $recursion 递归使用 外部调用时为FALSE
//     */
//    function get_treeview($myid, $effected_id = 'example', $str = "<span class='file'>\$name</span>", $str2 = "<span class='folder'>\$name</span>", $showlevel = 0, $style = 'filetree ', $currentlevel = 1, $recursion = FALSE)
//    {
//        $child = $this->get_child($myid);
//        if (!defined('EFFECTED_INIT')) {
//            $effected = ' id="' . $effected_id . '"';
//            define('EFFECTED_INIT', 1);
//        } else {
//            $effected = '';
//        }
//        $placeholder = '<ul><li><span class="placeholder"></span></li></ul>';
//        if (!$recursion) $this->str .= '<ul' . $effected . '  class="' . $style . '">';
//        foreach ($child as $id => $a) {
//
//            @extract($a);
//            if ($showlevel > 0 && $showlevel == $currentlevel && $this->get_child($id)) $folder = 'hasChildren'; //如设置显示层级模式@2011.07.01
//            $floder_status = isset($folder) ? ' class="' . $folder . '"' : '';
//            $this->str .= $recursion ? '<ul><li' . $floder_status . ' id=\'' . $id . '\'>' : '<li' . $floder_status . ' id=\'' . $id . '\'>';
//            $recursion = FALSE;
//            if ($this->get_child($id)) {
//                eval("\$nstr = \"$str2\";");
//                $this->str .= $nstr;
//                if ($showlevel == 0 || ($showlevel > 0 && $showlevel > $currentlevel)) {
//                    $this->get_treeview($id, $effected_id, $str, $str2, $showlevel, $style, $currentlevel + 1, TRUE);
//                } elseif ($showlevel > 0 && $showlevel == $currentlevel) {
//                    $this->str .= $placeholder;
//                }
//            } else {
//                eval("\$nstr = \"$str\";");
//                $this->str .= $nstr;
//            }
//            $this->str .= $recursion ? '</li></ul>' : '</li>';
//        }
//        if (!$recursion) $this->str .= '</ul>';
//        return $this->str;
//    }
//
//    /**
//     * 获取子栏目json
//     * Enter description here ...
//     * @param unknown_type $myid
//     */
//    public function creat_sub_json($myid, $str = '')
//    {
//        $sub_cats = $this->get_child($myid);
//        $n = 0;
//        if (is_array($sub_cats)) foreach ($sub_cats as $c) {
//            $data[$n]['id'] = iconv(CHARSET, 'utf-8', $c['catid']);
//            if ($this->get_child($c['catid'])) {
//                $data[$n]['liclass'] = 'hasChildren';
//                $data[$n]['children'] = array(array('text' => ' ', 'classes' => 'placeholder'));
//                $data[$n]['classes'] = 'folder';
//                $data[$n]['text'] = iconv(CHARSET, 'utf-8', $c['catname']);
//            } else {
//                if ($str) {
//                    @extract(array_iconv($c, CHARSET, 'utf-8'));
//                    eval("\$data[$n]['text'] = \"$str\";");
//                } else {
//                    $data[$n]['text'] = iconv(CHARSET, 'utf-8', $c['catname']);
//                }
//            }
//            $n++;
//        }
//        return json_encode($data);
//    }
//
//    private function have($list, $item)
//    {
//        return (strpos(',,' . $list . ',', ',' . $item . ','));
//    }
//}