<?php

/**
 *--------------------------------------
 * tree structure
 *--------------------------------------
 * @project		: pfa
 * @author		: cblee
 * @created		: 2012-12-13
 * @copyright	: (c)2012 AsThis
 *--------------------------------------
 */
defined('PFA_PATH') or exit('Access Denied');

class ATree {
	private $data; // source data
	private $fields; // field names
	private $root; // root parent id
	private $tree; // tree structure data
	private $arr; // result array
	private $str; // result string
	private $already = array();
	public $icon = array(
		'┃　',
		'┣',
		'┗',
		'　　'); // item icon

	public function __construct($data, $fields = array('id', 'pid', 'child'), $root = 0) {
		$this->data = $data;
		$this->fields = $fields;
		$this->root = $root;
		$this->_handler();
	}

	/* get item. $id: id */
	public function get_item($id = '') {
		$item = array();
		foreach($this->data as $v) {
			if($v[$this->fields[0]] == $id) {
				$item = $v;
				break;
			}
		}
		return $item;
	}

	/* get menu. $id: id, return leaf, default return full tree */
	public function get_leaf($id = null) {
		$id = ($id == null) ? $this->root : $id;
		return isset($this->tree[$id][$this->fields[2]]) ? $this->tree[$id][$this->fields[2]] : array();
	}

	/* get navigation. $id: id, return root to id */
	public function get_navi($id = '') {
		$this->arr = array();
		$this->_recur_n($this->data, $id);
		if(!is_null($this->arr)) {
			krsort($this->arr);
		}
		return $this->arr;
	}

	/* get leaf ids. $id: id, retrun ids under leaf */
	public function get_leafid($id = '') {
		$this->arr = array();
		$this->arr[] = $id;
		$this->_recur_p($this->get_leaf($id));
		return $this->arr;
	}

	/* get select form <option value='\$id' \$selected>\$spacer \$name</option>\r\n, <optgroup label='\$name'></optgroup>\r\n */
	public function get_leafStr($id, $str, $selectId = 0, $selectedStr = '', $spacerAddon = '', $wapper = array(), $childWapper = array()) {
		$return = '';
		$child = $this->get_leaf($id);
		if(is_array($child)) {
			if(!empty($wapper)) {
				$return .= $wapper[0];
			}

			$number = 1;
			$count = count($child);
			foreach($child as $v) {
				if(!empty($childWapper)) {
					$return .= $childWapper[0];
				}

				$spacer = $spacerAddon.($number == $count ? $this->icon[2] : $this->icon[1]);

				@extract($v);
				if(!is_array($selectId)) {
					$selectId = explode(',', $selectId);
				}
				
				$return .= in_array($v[$this->fields[0]], $selectId) ? $selectedStr : $str;
				eval("\$_t_str = \"$return\";");
				$return = $_t_str;

				if(isset($v[$this->fields[2]])) {
					$addon = $spacerAddon.($number == $count ? $this->icon[3] : $this->icon[0]);
					$return .= $this->get_leafStr($v[$this->fields[0]], $str, $selectId, $selectedStr, $addon, $wapper, $childWapper);
				}
				if(!empty($childWapper)) {
					$return .= $childWapper[1];
				}

				$number++;
			}
			if(!empty($wapper)) {
				$return .= $wapper[1];
			}
		}
		return $return;
	}

	/* tree structure data table handler */
	private function _handler() {
		$tree = array();
		foreach($this->data as $item) {
			$tree[$item[$this->fields[0]]] = $item;
		}
		foreach ($tree as $id => $item) {
			$tree[$item[$this->fields[1]]][$this->fields[2]][] = &$tree[$item[$this->fields[0]]];
		}

		$this->tree = $tree;
	}

	/* reverse recursion */
	private function _recur_n($arr, $id) {
		foreach($arr as $v) {
			if($v[$this->fields[0]] == $id) {
				$this->arr[] = $v;
				if($v[$this->fields[1]] != $this->root) {
					$this->_recur_n($arr, $v[$this->fields[1]]);
				}
			}
		}
	}

	/* forward recursion */
	private function _recur_p($arr) {
		foreach($arr as $v) {
			$this->arr[] = $v[$this->fields[0]];
			if(isset($v[$this->fields[2]]) and !empty($v[$this->fields[2]])) {
				$this->_recur_p($v[$this->fields[2]]);
			}
		}
	}
}

/**
 * $tree= new ATree($data, array('id', 'pid', 'child'));
 * $arr=$tree->get_leaf(0);
 * $nav=$tree->get_navi(15);
 * $str = $tree->get_leafStr(0, "<option value='\$id'>\$spacer \$name</option>\r\n", 4, "<option value='\$id' selected='selected'>\$spacer \$name</option>\r\n");
 *
 * echo "<select name=\"f_id\" size=10>\r\n";
 * echo $str;
 * echo "</select>";
 */

?>