<?php

/**
 * @link      http://www.u-bo.com
 * @copyright 南京友博网络科技有限公司
 * @license   http://www.u-bo.com/license/
 */

namespace common\components;

use Yii;

/**
 * 树操作类
 *
 * @author legendjw http://blog.u-bo.com
 * @since 0.1
 */
class Tree {

	public $arr = array();
	public $icon = array('│', '├─ ', '└─ ');
	public $nbsp = "&nbsp;";
	public $ret = '';
	public $level = 0;

	//初始化构造函数
	public function __construct($arr = array()) {
		$this->arr = $arr;
		$this->ret = '';
		return is_array($arr);
	}

	public function getchild($bid) {
		$a = $newarr = array();
		if (is_array($this->arr)) {
			foreach ($this->arr as $id => $a) {
				if ($a['pid'] == $bid)
					$newarr[$id] = $a;
			}
		}
		return $newarr ? $newarr : false;
	}

	/**
	 *   20141121
	 *
	 * @param type $bid          父级
	 * @param type $str          生成树型结构的基本代码，例如："
	 * @param type $sid          被选中的ID
	 * @param type $disabled_id  禁选数据默认0,如果多个禁选，以数组形式传递，[1,2,3]
	 * @param type $adds         每行前面的补充
	 * @param type $strgroup     一级菜单的替换，存在的时候，格式是和法的php代码的情况下会吧pid==0的替换了
	 * @return type
	 */
	function get_tree($bid, $str, $sid = 0, $disabled_id = 0, $adds = '', $strgroup = '') {
		$number = 1;
		$child = $this->getchild($bid);
		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 : '';

				@extract($a);
				if (empty($a['selected'])) {
					$selected = $id == $sid ? 'selected' : '';
				}
				if (is_array($disabled_id)) {
					$disabled = in_array($id, $disabled_id) ? 'disabled' : '';
				} else {
					$disabled = $id == $disabled_id ? 'disabled' : '';
				}
				$pid == 0 && $strgroup ? eval("\$newstr = \"$strgroup\";") : eval("\$newstr = \"$str\";");
				$this->ret .= $newstr;
				$nbsp = $this->nbsp;
				$this->get_tree($id, $str, $sid, $disabled_id, $adds . $k . $nbsp, $strgroup);
				$number++;
			}
		}
		return $this->ret;
	}

	/**
	 * 转换数组到树状结构
	 * 
	 * @param type $list 数据
	 * @param type $pk 主键名称
	 * @param type $pid 父级名称
	 * @param type $child 子类存放名称
	 * @param type $root 根节点
	 * @return type
	 */
	public static function listToTree($list, $pk = 'id', $pid = 'pid', $child = '_child', $root = 0) {
		// 创建Tree
		$tree = array();
		if (is_array($list)) {
			// 创建基于主键的数组引用
			$refer = array();
			foreach ($list as $key => $data) {
				$refer[$data[$pk]] = & $list[$key];
			}
			foreach ($list as $key => $data) {
				// 判断是否存在parent
				$parentId = $data[$pid];
				if ($root == $parentId) {
					$tree[] = & $list[$key];
				} else {
					if (isset($refer[$parentId])) {
						$parent = & $refer[$parentId];
						$parent[$child][] = & $list[$key];
					}
				}
			}
		}
		return $tree;
	}

	/**
	 * 转换树状结构的数组为普通列表,并加上等级以及前缀
	 * 
	 * @param type $tree 树状结构数组
	 * @param type $level 树深度
	 * @param type $child 树子集名称
	 * @param type $icon 空格前缀元素
	 * @return type
	 */
	public static function treeToList($tree, $level = 0,$child = '_child', $icon = ['│', '&nbsp;&nbsp;&nbsp;', '├─ ']) {
		static $list = [];
		$blank = str_repeat($icon[0].$icon[1], $level) . $icon[2];
		$level++;
		foreach ($tree as $t) {
			if (isset($t[$child])) {
				$temp = $t;
				unset($temp[$child]);
				$temp['tree_level'] = $level;
				$temp['tree_spacer'] = $blank;
				$list[] = $temp;
				$list = self::treeToList($t[$child], $level);
			} else {
				$t['tree_spacer'] = $blank;
				$t['tree_level'] = $level;
				$list[] = $t;
			}
		}
		return $list;
	}

	/**
	 * 重新排列具有子父级关系的数组
	 */
	public static function getList($list, $pk = 'id', $pid = 'pid', $child = '_child', $root = 0, $icon = ['│', '&nbsp;&nbsp;&nbsp;', '├─ ']){
		$tree = self::listToTree($list, $pk, $pid, $child, $root);
		$list = self::treeToList($tree, 0, $child, $icon);
		return $list;
	}

}
