<?php
/**
 * 通用的树型类，可以生成任何树型结构
 */
class Tree {
	// 生成树型结构所需要的2维数组
	public $data = array();
	// 生成树型结构所需修饰符号，可以换成图片
	public $icon = array('│', '├', '└', '&nbsp;');
	// 父分类加标记
	public $flag = '*';
	private $bigPost = array();
	private $ret = '';
	private $idIndex = 'catid';

	/**
	 * 构造函数，初始化类
	 *
	 * @param array $data 2维数组
	 */
	public function __construct($data = array(), $type = '', $checkBigPost = false, $selectId = 0) {
		if ($type !== '') $typeArray = explode(',', $type);
		if (is_array($data)) {
			$tmp = array_keys(current($data));
			foreach($tmp as $key) {
				if (substr($key, -2) == 'id') {
					$this -> idIndex = $key;
					break;
				}
			}
			foreach($data as $k => $v) { // 根据父类ID合并分类
				if ($type === '' || !isset($v['type']) || in_array($v['type'], $typeArray)) $this -> data[$v['pid']][$v[$this -> idIndex]] = $v;
			}
		}
		if ($checkBigPost) {
			$bigPost = array();
			$module = get_module();
			foreach($module as $tmp) {
				if ($tmp['usecategory']) {
					$bigPost[$tmp['id']] = C('isbigpost', 0, $tmp['name']);
				}
			}
			$this -> bigPost = $bigPost;
		}
		$this -> ret = '';
	}

	/**
	 * 得到树型结构
	 *
	 * @param int $pid，表示获得这个ID下的所有子级
	 * @param string $str 生成树型结构的基本代码，例如："<option value=\$id \$selected>\$tab\$name</option>"
	 * @param int $sid 被选中的ID，比如在做树型下拉框的时候需要用到
	 * @return string
	 */
	public function getTree($pid, $str, $sid = 0, $adds = '', $first = true) {
		if (isset($this -> data[$pid])) {
			$number = 1;
			$total = count($this -> data[$pid]);
			foreach($this -> data[$pid] as $key => $tmp) {
				$j = $k = '';
				$isparent = isset($this -> data[$key]);
				if ($number == $total) {
					$j .= $this -> icon[2];
					$isparent && !$first && $k = $this -> icon[3] . $this -> icon[3];
				} else {
					$j .= $this -> icon[1];
					$k = $adds ? $this -> icon[0] : '';
				}
				$tab = $adds ? $adds . $j : '';
				$selected = $key == $sid ? 'selected' : '';
				@extract($tmp);
				if ($isparent && $this -> flag && isset($moduleid) && $this -> bigPost && $this -> bigPost[$moduleid] == 0) ${$this -> idIndex} .= $this -> flag;
				eval("\$nstr = \"$str\";");
				$this -> ret .= $nstr;
				$isparent && $this -> getTree($key, $str, $sid, $adds . $k . $this -> icon[3], 0);
				$number++;
			}
		}
		return $this -> ret;
	}

	/**
	 * 得到加强树型结构
	 *
	 * @param int $ ID，表示获得这个ID下的所有子级
	 * @return string
	 */
	public function getStree($pid = 0, $treename = 'jxcms', $adds = '', $first = 1) {
		if (isset($this -> data[$pid])) {
			$number = 1;
			$this -> ret .= $first ? "<div class=\"tree\">\n" : "<div class=\"clip\" id=\"{$treename}{$pid}\">\n";
			$total = count($this -> data[$pid]);
			foreach($this -> data[$pid] as $key => $tmp) {
				$j = $k = '';
				$isparent = isset($this -> data[$key]);
				if ($number == $total) {
					$j .= '<img src="statics/images/joinbottom.gif" />';
					$isparent && $k = $first ? '' : '<img src="statics/images/space.gif" />';
				} else {
					$j .= '<img src="statics/images/join.gif" />';
					$k = $first ? '' : '<img src="statics/images/line.gif" />';
				}
				$tab = $first ? '' : $adds . $j;
				if ($isparent) {
					$isfolder = '<img src="statics/images/folder.gif" />';
				} else {
					$isfolder = '<img src="statics/images/page.gif" />';
				}
				$this -> ret .= "<div class=\"node\">{$tab}{$isfolder}{$tmp[name]}</div>\n";
				$isparent && $this -> getStree($key, $treename, $adds . $k, 0);
				$number++;
			}
			$this -> ret .= "</div>\n";
		}
		return $this -> ret;
	}
	/**
	 * 得到加强树型结构admin
	 *
	 * @param int $ ID，表示获得这个ID下的所有子级
	 * @return string
	 */
	public function getStreeAdmin($pid = 0, $treename = 'jxcms', $adds = '', $first = 1) {
		if (isset($this -> data[$pid])) {
			$number = 1;
			$this -> ret .= $first ? "<div class=\"tree\">\n" : "<div id=\"div{$treename}{$pid}\" style=\"display:none;\">\n";
			$total = count($this -> data[$pid]);
			foreach($this -> data[$pid] as $key => $tmp) {
				$j = $k = '';
				$isparent = isset($this -> data[$key]);
				if ($number == $total) {
					$j .= '<img src="statics/images/joinbottom.gif" />';
					$isparent && $k = $first ? '' : '<img src="statics/images/space.gif" />';
				} else {
					$j .= '<img src="statics/images/join.gif" />';
					$k = $first ? '' : '<img src="statics/images/line.gif" />';
				}
				$tab = $first ? '' : $adds . $j;
				$img = $isparent ? "<img src=\"statics/images/folder.gif\" id=\"img{$treename}{$key}\" class=\"folder\" onclick=\"treeChange('{$treename}{$key}')\" />" : "<img src=\"statics/images/page.gif\" />";
				$c = $tmp['type'] == 1?'onepage':get_module($tmp['moduleid'],'name');
				$this -> ret .= "<div class=\"node\">{$tab}{$img}<a href=\"?c={$c}&catid=$tmp[catid]\" target=\"right\" hidefocus=\"true\">$tmp[name]</a></div>\n";
				$isparent && $this -> getStreeAdmin($key, $treename, $adds . $k, 0);
				$number++;
			}
			$this -> ret .= "</div>\n";
		}
		return $this -> ret;
	}

	/**
	 * 同上一方法类似,但允许多选
	 */
	public function getTreeMulti($pid, $str, $sid = 0, $adds = '') {
		if (isset($this -> data[$pid])) {
			$number = 1;
			$total = count($this -> data[$pid]);
			foreach($this -> data[$pid] as $catid => $tmp) {
				$j = $k = '';
				if ($number == $total) {
					$j .= $this -> icon[2];
				} else {
					$j .= $this -> icon[1];
					$k = $adds ? $this -> icon[0] : '';
				}
				$tabr = $adds ? $adds . $j : '';

				$selected = $this -> have($sid, $id) ? 'selected' : '';
				// echo $sid.'=>'.$id.' : '.$selected.' . <br/>';
				@extract($tmp);
				eval("\$nstr = \"$str\";");
				$this -> ret .= $nstr;
				$this -> getTreeMulti($catid, $str, $sid, $adds . $k . '&nbsp;');
				$number++;
			}
		}
		return $this -> ret;
	}

	private function have($list, $item) {
		return strpos(',,' . $list . ',', ',' . $item . ',');
	}
}
