_table = $table;
$this->_sql_parent_id_col = 'PARENT_ID';
$this->_params = array();
$this->cookie_name = 'TREE_' . $table;
// TODO: fun name must be uniq to show couple tree's on one site
$this->js_tree_hide_fun = 'TREE_' . $table . '_hide';
$this->js_tree_open_rec_fun = 'TREE_' . $table . '_open_rec';
$this->_limit = 0;
$this->_deep_limit = 0;
$this->_opened_nodes_to_save = array();
}
public function setProfiler($profiler) {
$this->_profiler = $profiler;
}
public function log($msg, $groups = array()) {
if ($this->_profiler && method_exists($this->_profiler, 'log')) {
$this->_profiler->log($msg, $groups);
}
}
public function set_parent_id_col($p_id_col) {
$this->_sql_parent_id_col = $p_id_col;
}
public function get_item_p_id(&$r) {
if (isset($r->{$this->_sql_parent_id_col})) {
return $r->{$this->_sql_parent_id_col};
}
return null;
}
public function is_closed($id) {
static $c;
if (!$c) {
$c = explode(' ', V::get($this->cookie_name, '', $_COOKIE));
}
if ($this->get_param('lazy_open_rec')) {
if (!in_array($id, $c)) {
$this->lazy_open($id);
}
return false;
}
return !in_array($id, $c);
}
public function show() {
//echo'
';print_r(explode(' ', $_COOKIE[$this->cookie_name]));echo'';
$this->show_css();
$this->show_js();
echo "\n".''."\n";
$this->show_rec();
echo '
'."\n";
$this->_save_lazy_opened_nodes();
echo"\n".''."\n";
}
/*
* Save collapsed nodes in cookie
* @see _save_lazy_opened_nodes
*/
public function lazy_open($id) {
$this->_opened_nodes_to_save[$id] = true;
}
/*
* Save collapsed nodes in cookie
* @see lazy_open
*/
public function _save_lazy_opened_nodes() {
if (!empty($this->_opened_nodes_to_save)) {
$opened = array();
if (!empty($_COOKIE[$this->cookie_name]) && $_COOKIE[$this->cookie_name] != '') {
$opened = explode(' ', $_COOKIE[$this->cookie_name]);
}
foreach ($opened as $id) {
$this->_opened_nodes_to_save [$id] = true;
}
$_COOKIE[$this->cookie_name] = implode(' ', array_keys($this->_opened_nodes_to_save));
echo'';
}
}
public function showSubTree($id = 0) {
$this->show_css();
$this->show_js();
echo "\n".''."\n";
$ids = explode(',', $id);
foreach ($ids as $id) {
$parents = array();
$this->get_parents_rec($id, $parents);
//echo'
';print_r($parents);echo'
';
$this->set_param('show_state', 'parents');
$r = null;
if (($r = reset($parents)) != null && $this->get_item_p_id($r) == -1) {
echo'
'."Kosz".'';
}
foreach ($parents as $r) {
$cls = ' class="tree-last"';
echo'
'."\n";
$item_id_html_id = ' id="TREE'.$r->ID.'"';
echo '- ';
if ($r->ID == $id) break;
$this->show_item($r);
}
$this->set_param('show_state', 'items');
if ($r) {
$this->show_item($r);
} else {
if ($this->get_param('is_trash')) {// is _trash
echo''."Kosz".'';
} else {
echo''."Brak danych".'';
}
}
//TODO: get item and if exists then show parents and childrens
$this->show_rec($id);
foreach ($parents as $r) {
echo '
'."\n";
echo'
';
}
echo '
';
}
echo '
'."\n";
}
/*
* Wyszukiwanie ID w drzewie.
*/
public function showSearchNode($id) {
$parents = array();
$this->get_parents_rec($id, $parents);
if (empty($parents)) {
echo'Rekord id="'.$id.'" nie istnieje.
';
} else {
// TODO: drzewo ZWIN, trzeba teraz zmienic zawartosc cookie!
//echo'TODO: wyszukaj "'.$id.'" {'.implode(',', $parent_ids).'}
';
echo'';
$js = "return scrollToProces('".$id."');";
echo''."Przejdz do ID ".$id."".'';
echo'
';
// TODO: sprawdzi czy aby na pewno dziala poprawnie, test szukaj 901, nie otwiera 892
foreach ($parents as $r) {
$this->lazy_open($r->ID);
}
$this->_save_lazy_opened_nodes();
}
$this->show();
}
/**
* TODO: Np. do menu, czy filtrowania drzewa.
* @see task_CRM_MENU
* @param items - array of items to show, array(ID => $r)
* @param show_item_callback - inna funkcja do wypisywania - TODO: jest $tree->set_param('show_item_callback');
*/
public function showItems(&$base_items, $show_item_callback = null) {
$items = array();
// get paretns flat
$items_flat = array();
foreach ($base_items as $p_id => $p) {
$items[$p->ID] = $p;
$items_flat[$p->ID] = $p->PARENT_ID;
$items_flat[$this->get_item_p_id($p)] = null;
}
$user_menu_tree_created = TreeHelper::build_tree_flat($this->_table, $items_flat);
$user_menu_tree = TreeHelper::get_tree_from_flat($items_flat);
$this->fetch_data($items, $items_flat);
if (!empty($user_menu_tree[0])) {
$this->show_css();
echo'';
$this->show_rec_by_tree($user_menu_tree[0], $items);
echo'
';
} else {
//
}
}
public function show_rec_by_tree(&$tree, &$items) {
if (empty($tree)) {
return;
}
echo'';
$i = 0; $cnt = count($tree);
foreach ($tree as $k_id => $v_arr) {
$r = (isset($items[$k_id]))? $items[$k_id] : null;
if ($r) {
$cls = array();
if ($this->is_closed($r->ID)) $cls['tree-close'] = true;
if (++$i == $cnt) {
$cls['tree-last'] = true;
}
if (empty($v_arr)) {
$cls['tree-leaf'] = true;
}
$cls = (!empty($cls))? ' class="'.implode(' ', array_keys($cls)).'"' : '';
$item_id_html_id = ' id="TREE'.$r->ID.'"';
echo '- ';
if (isset($r->has_childrens) && $r->has_childrens) {
echo'';
}
$this->show_item($r);
$this->show_rec_by_tree($v_arr, $items);
echo'
';
}
}
echo'
';
}
public function fetch_data(&$items, $tree_flat) {
$db = DB::getDB();
$sql_ids = array();
// find only not set
foreach ($tree_flat as $k_id => $v) {
if (empty($items[$k_id])) {
$sql_ids[] = $k_id;
}
}
// add tree parent proces info
if (!empty($sql_ids)) {
$sql_ids = implode(", ", $sql_ids);
$sql = "select p.* from `{$this->_table}` as p where p.`ID` in ({$sql_ids}) ";
$res = $db->query($sql);
while ($r = $db->fetch($res)) {
$items[$r->ID] = $r;
}
}
}
/*
* Open all nodes recursive.
*/
public function show_rec_all($parent_id = 0, $deep = 0) {
$this->set_param('lazy_open_rec', true);// @see is_closed
$this->lazy_open($parent_id);
$this->show_rec($parent_id, $deep);
$this->_save_lazy_opened_nodes();
}
public function show_rec($parent_id = 0, $deep = 0) {
//if ($this->_deep_limit > 0 && $deep > $this->_deep_limit) {
// return;
//}
$this->log("show_rec({$parent_id}, {$deep}) start");
$list = $this->get_childrens($parent_id);
if (empty($list)) return;
$this->log("show_rec({$parent_id}, {$deep}) -> get_childrens({$parent_id})", array('get_childrens'));
echo ''."\n";
$list_total = count($list);
foreach ($list as $r) {
$cls = array();
if (!--$list_total) $cls['tree-last'] = true;
if (!$this->get_param('rozwin')) {
if ($this->is_closed($r->ID)) $cls['tree-close'] = true;
}
if ($this->_deep_limit > 0 && $deep >= $this->_deep_limit) {
$cls['tree-close'] = true;
}
if (!$r->has_childrens) {
$cls['tree-leaf'] = true;
if (isset($cls['tree-close'])) unset($cls['tree-close']);// show wskazniki on leaf
}
$cls = array_keys($cls);// uniq array
// reopen nodes marked as open, but hide by default or deep, etc., @see show_js: tree_..._ajax_reopen
$btn_open_cls_add = '';
if (in_array('tree-close', $cls) && $this->is_closed($r->ID) == false) {
$btn_open_cls_add = ' ajax-reopen';
}
//$cls[] = 'deep-'.$deep;
$cls = (empty($cls))? '' : ' class="'.implode(' ', $cls).'"';
$item_id_html_id = '';
if ($this->get_item_p_id($r) == $parent_id) {// tylko normalny, a nie P_ID2, czy P_ID3, etc
$item_id_html_id = ' id="TREE'.$r->ID.'"';
}
echo '- ';
if ($this->get_param('rozwin')) {
if ($r->has_childrens) {
if ($this->_deep_limit > 0 && $deep + 1 > $this->_deep_limit) {
//echo' ';
echo'';
}
}
} else {
if ($r->has_childrens) {
//echo' ';
echo'';
}
}
$this->log("show_rec({$parent_id}, {$deep}) -> show_item start");
$this->show_item($r);
$this->log("show_rec({$parent_id}, {$deep}) -> show_item end", array('show_item'));
if ($r->has_childrens) {
$this->show_rec($r->ID, $deep + 1);
}
echo '
'."\n";
}
echo '
'."\n";
$this->log("show_rec({$parent_id}, {$deep}) end");
}
public function show_item(&$r) {
if ($callback = $this->get_param('show_item_callback')) {
$callback($r, $this);
} else {
echo'- ';
echo ''.$r->ID.'';
echo'
';
}
}
public function &get_childrens($parent_id) {
$ret = array();
// check tree limit - load more by ajax
// mved to show_rec
// if ($this->_limit > 0 && $this->_nodes_from_db > $this->_limit) {
// return $ret;
// }
$sql = new stdClass();
$sql->select = array();
$sql->select[] = "t.*";
// PARENT_TYPE dla tabeli CRM_LISTA_ZASOBOW
if ($this->_table == 'CRM_LISTA_ZASOBOW') {
$sql->select[] = "
IF( t.`{$this->_sql_parent_id_col}`='{$parent_id}'
, 'P_ID'
, IF( (FIND_IN_SET('{$parent_id}', t.`PARENT_ID_ACCESS`) > 0)
, 'P_ID_ACCESS'
, IF( (FIND_IN_SET('{$parent_id}', t.`PARENT_ID_MAP`) > 0)
, 'P_ID_MAP'
, 'P_ID_UNKNOWN'
)
)
) as PARENT_TYPE
";
$sql->select[] = "IF(t.`ALIAS_ID` > 0
, (select concat_ws('.', zap.`DESC`, za.`DESC`)
from `CRM_LISTA_ZASOBOW` as za
left join `CRM_LISTA_ZASOBOW` as zap on(zap.`ID`=za.`PARENT_ID`)
where za.`ID`=t.`ALIAS_ID`
limit 1
)
, ''
) as ALIAS_NAME
";
}
$sql->filter = array();
$sql->join_filter = array();
$sql->filter[] = "(t.`{$this->_sql_parent_id_col}`='{$parent_id}')";
$sql->join_filter[] = "(t2.`{$this->_sql_parent_id_col}`=t.`ID`)";
if ($this->_table == 'CRM_LISTA_ZASOBOW') {
// TODO: $this->get_param('TREE_SHOW_P_ID2') $this->get_param('TREE_SHOW_P_ID3')
if ($_SESSION['TREE_SHOW_P_ID2'] || $_SESSION['TREE_SHOW_P_ID3']) {
if ($_SESSION['TREE_SHOW_P_ID2']) {
$sql->filter[] = "(FIND_IN_SET('{$parent_id}', t.`PARENT_ID_ACCESS`) > 0)";
$sql->join_filter[] = "(FIND_IN_SET(t.`ID`, t2.`PARENT_ID_ACCESS`) > 0)";
}
if ($_SESSION['TREE_SHOW_P_ID3']) {
$sql->filter[] = "(FIND_IN_SET('{$parent_id}', t.`PARENT_ID_MAP`) > 0)";
$sql->join_filter[] = "(FIND_IN_SET(t.`ID`, t2.`PARENT_ID_MAP`) > 0)";
}
}
}
$sql->where = implode(" or ", $sql->filter);
$sql->join_filter = implode(" or ", $sql->join_filter);
// filtr_status
if ($this->_table == 'IN7_MK_BAZA_DYSTRYBUCJI') {
$sqlStatus = array();
if ($this->get_param('filtr_status') == 'NORMAL') {
$sqlStatus[] = "'NORMAL'";
} else if ($this->get_param('filtr_status') == 'WAITING') {
$sqlStatus[] = "'NORMAL'";
$sqlStatus[] = "'WAITING'";
}
if (!empty($sqlStatus)) {
$sqlStatus = implode(',', $sqlStatus);
$sql->where = "({$sql->where}) and t.`A_STATUS` in({$sqlStatus}) ";
}
}
if (in_array($this->_table, array('CRM_PROCES','CRM_LISTA_ZASOBOW'))) {
$sql->order_by = "order by t.`SORT_PRIO` asc, t.`ID` asc";
} else {
$sql->order_by = "order by t.`ID` asc";
}
// has_childrens
# IF((select 1 from `CRM_PROCES` as t2 where t2.`PARENT_ID` = t.`ID` limit 1) > 0, 1, 0) AS has_childrens
if ($this->_table == 'CRM_LISTA_ZASOBOW') {
//$sql->select [] = "IF(t.`".$this->_sql_parent_id_col."`='".$parent_id."' and t2.`ID` is not null, 1, 0) as has_childrens";
$sql->select[] = "IF((select 1 from `{$this->_table}` as t2 where {$sql->join_filter} limit 1) is not null, 1, 0) as has_childrens";
} else {
//$sql->select [] = "IF(t2.`ID` is not null, 1, 0) as has_childrens";
$sql->select[] = "IF((select 1 from `{$this->_table}` as t2 where {$sql->join_filter} limit 1) is not null, 1, 0) as has_childrens";
}
$db = DB::getDB();
$sql->select = implode("\n, ", $sql->select);
$sql = "select
{$sql->select}
from `{$this->_table}` as t
where
{$sql->where}
{$sql->order_by}
";
if('123' == V::get('DBG_SQL', '', $_GET)){echo' (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($sql);echo'';}
$res = $db->query($sql);
$rowsCount = 0;
while ($r = $db->fetch($res)) {
$ret[$r->ID] = $r;
$rowsCount++;
}
$this->_nodes_from_db += $rowsCount;
return $ret;
}
public function &get_parents_rec($id, &$arr) {
$db = DB::getDB();
$sql = "select
t.*
, '1' as has_childrens
, 'P_ID' as PARENT_TYPE
from `{$this->_table}` as t
where
t.`ID`='".$id."'
";
$res = $db->query($sql);
if ($r = $db->fetch($res)) {
array_unshift($arr, $r);
if (null == $this->get_item_p_id($r) || '0' == $this->get_item_p_id($r)) {
return $arr;
} else {
$this->get_parents_rec($this->get_item_p_id($r), $arr);
}
}
return $arr;
}
public function set_param($key, $value) {
$this->_params[$key] = $value;
}
public function get_param($key) {
if (array_key_exists($key, $this->_params)) {
return $this->_params[$key];
}
return null;
}
public function show_css() {
static $_run_only_once;
if ($_run_only_once) {
return;
}
$_run_only_once = true;
?>