You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
602 lines
22 KiB
602 lines
22 KiB
<?php |
|
class _tree_struct { |
|
// Structure table and fields |
|
protected $table = ""; |
|
protected $fields = array( |
|
"id" => false, |
|
"parent_id" => false, |
|
"position" => false, |
|
"left" => false, |
|
"right" => false, |
|
"level" => false |
|
); |
|
|
|
// Constructor |
|
function __construct($table = "tree", $fields = array()) { |
|
$this->table = $table; |
|
if(!count($fields)) { |
|
foreach($this->fields as $k => &$v) { $v = $k; } |
|
} |
|
else { |
|
foreach($fields as $key => $field) { |
|
switch($key) { |
|
case "id": |
|
case "parent_id": |
|
case "position": |
|
case "left": |
|
case "right": |
|
case "level": |
|
$this->fields[$key] = $field; |
|
break; |
|
} |
|
} |
|
} |
|
// Database |
|
$this->db = new _database; |
|
} |
|
|
|
function _get_node($id) { |
|
$this->db->query("SELECT `".implode("` , `", $this->fields)."` FROM `".$this->table."` WHERE `".$this->fields["id"]."` = ".(int) $id); |
|
$this->db->nextr(); |
|
return $this->db->nf() === 0 ? false : $this->db->get_row("assoc"); |
|
} |
|
function _get_children($id, $recursive = false) { |
|
$children = array(); |
|
if($recursive) { |
|
$node = $this->_get_node($id); |
|
$this->db->query("SELECT `".implode("` , `", $this->fields)."` FROM `".$this->table."` WHERE `".$this->fields["left"]."` >= ".(int) $node[$this->fields["left"]]." AND `".$this->fields["right"]."` <= ".(int) $node[$this->fields["right"]]." ORDER BY `".$this->fields["left"]."` ASC"); |
|
} |
|
else { |
|
$this->db->query("SELECT `".implode("` , `", $this->fields)."` FROM `".$this->table."` WHERE `".$this->fields["parent_id"]."` = ".(int) $id." ORDER BY `".$this->fields["position"]."` ASC"); |
|
} |
|
while($this->db->nextr()) $children[$this->db->f($this->fields["id"])] = $this->db->get_row("assoc"); |
|
return $children; |
|
} |
|
function _get_path($id) { |
|
$node = $this->_get_node($id); |
|
$path = array(); |
|
if(!$node === false) return false; |
|
$this->db->query("SELECT `".implode("` , `", $this->fields)."` FROM `".$this->table."` WHERE `".$this->fields["left"]."` <= ".(int) $node[$this->fields["left"]]." AND `".$this->fields["right"]."` >= ".(int) $node[$this->fields["right"]]); |
|
while($this->db->nextr()) $path[$this->db->f($this->fields["id"])] = $this->db->get_row("assoc"); |
|
return $path; |
|
} |
|
|
|
function _create($parent, $position) { |
|
return $this->_move(0, $parent, $position); |
|
} |
|
function _remove($id) { |
|
if((int)$id === 1) { return false; } |
|
$data = $this->_get_node($id); |
|
$lft = (int)$data[$this->fields["left"]]; |
|
$rgt = (int)$data[$this->fields["right"]]; |
|
$dif = $rgt - $lft + 1; |
|
|
|
// deleting node and its children |
|
$this->db->query("" . |
|
"DELETE FROM `".$this->table."` " . |
|
"WHERE `".$this->fields["left"]."` >= ".$lft." AND `".$this->fields["right"]."` <= ".$rgt |
|
); |
|
// shift left indexes of nodes right of the node |
|
$this->db->query("". |
|
"UPDATE `".$this->table."` " . |
|
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` - ".$dif." " . |
|
"WHERE `".$this->fields["left"]."` > ".$rgt |
|
); |
|
// shift right indexes of nodes right of the node and the node's parents |
|
$this->db->query("" . |
|
"UPDATE `".$this->table."` " . |
|
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` - ".$dif." " . |
|
"WHERE `".$this->fields["right"]."` > ".$lft |
|
); |
|
|
|
$pid = (int)$data[$this->fields["parent_id"]]; |
|
$pos = (int)$data[$this->fields["position"]]; |
|
|
|
// Update position of siblings below the deleted node |
|
$this->db->query("" . |
|
"UPDATE `".$this->table."` " . |
|
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` - 1 " . |
|
"WHERE `".$this->fields["parent_id"]."` = ".$pid." AND `".$this->fields["position"]."` > ".$pos |
|
); |
|
return true; |
|
} |
|
function _move($id, $ref_id, $position = 0, $is_copy = false) { |
|
if((int)$ref_id === 0 || (int)$id === 1) { return false; } |
|
$sql = array(); // Queries executed at the end |
|
$node = $this->_get_node($id); // Node data |
|
$nchildren = $this->_get_children($id); // Node children |
|
$ref_node = $this->_get_node($ref_id); // Ref node data |
|
$rchildren = $this->_get_children($ref_id);// Ref node children |
|
|
|
$ndif = 2; |
|
$node_ids = array(-1); |
|
if($node !== false) { |
|
$node_ids = array_keys($this->_get_children($id, true)); |
|
// TODO: should be !$is_copy && , but if copied to self - screws some right indexes |
|
if(in_array($ref_id, $node_ids)) return false; |
|
$ndif = $node[$this->fields["right"]] - $node[$this->fields["left"]] + 1; |
|
} |
|
if($position >= count($rchildren)) { |
|
$position = count($rchildren); |
|
} |
|
|
|
// Not creating or copying - old parent is cleaned |
|
if($node !== false && $is_copy == false) { |
|
$sql[] = "" . |
|
"UPDATE `".$this->table."` " . |
|
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` - 1 " . |
|
"WHERE " . |
|
"`".$this->fields["parent_id"]."` = ".$node[$this->fields["parent_id"]]." AND " . |
|
"`".$this->fields["position"]."` > ".$node[$this->fields["position"]]; |
|
$sql[] = "" . |
|
"UPDATE `".$this->table."` " . |
|
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` - ".$ndif." " . |
|
"WHERE `".$this->fields["left"]."` > ".$node[$this->fields["right"]]; |
|
$sql[] = "" . |
|
"UPDATE `".$this->table."` " . |
|
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` - ".$ndif." " . |
|
"WHERE " . |
|
"`".$this->fields["right"]."` > ".$node[$this->fields["left"]]." AND " . |
|
"`".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") "; |
|
} |
|
// Preparing new parent |
|
$sql[] = "" . |
|
"UPDATE `".$this->table."` " . |
|
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` + 1 " . |
|
"WHERE " . |
|
"`".$this->fields["parent_id"]."` = ".$ref_id." AND " . |
|
"`".$this->fields["position"]."` >= ".$position." " . |
|
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") "); |
|
|
|
$ref_ind = $ref_id === 0 ? (int)$rchildren[count($rchildren) - 1][$this->fields["right"]] + 1 : (int)$ref_node[$this->fields["right"]]; |
|
$ref_ind = max($ref_ind, 1); |
|
|
|
$self = ($node !== false && !$is_copy && (int)$node[$this->fields["parent_id"]] == $ref_id && $position > $node[$this->fields["position"]]) ? 1 : 0; |
|
foreach($rchildren as $k => $v) { |
|
if($v[$this->fields["position"]] - $self == $position) { |
|
$ref_ind = (int)$v[$this->fields["left"]]; |
|
break; |
|
} |
|
} |
|
if($node !== false && !$is_copy && $node[$this->fields["left"]] < $ref_ind) { |
|
$ref_ind -= $ndif; |
|
} |
|
|
|
$sql[] = "" . |
|
"UPDATE `".$this->table."` " . |
|
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` + ".$ndif." " . |
|
"WHERE " . |
|
"`".$this->fields["left"]."` >= ".$ref_ind." " . |
|
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") "); |
|
$sql[] = "" . |
|
"UPDATE `".$this->table."` " . |
|
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` + ".$ndif." " . |
|
"WHERE " . |
|
"`".$this->fields["right"]."` >= ".$ref_ind." " . |
|
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") "); |
|
|
|
$ldif = $ref_id == 0 ? 0 : $ref_node[$this->fields["level"]] + 1; |
|
$idif = $ref_ind; |
|
if($node !== false) { |
|
$ldif = $node[$this->fields["level"]] - ($ref_node[$this->fields["level"]] + 1); |
|
$idif = $node[$this->fields["left"]] - $ref_ind; |
|
if($is_copy) { |
|
$sql[] = "" . |
|
"INSERT INTO `".$this->table."` (" . |
|
"`".$this->fields["parent_id"]."`, " . |
|
"`".$this->fields["position"]."`, " . |
|
"`".$this->fields["left"]."`, " . |
|
"`".$this->fields["right"]."`, " . |
|
"`".$this->fields["level"]."`" . |
|
") " . |
|
"SELECT " . |
|
"".$ref_id.", " . |
|
"`".$this->fields["position"]."`, " . |
|
"`".$this->fields["left"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " . |
|
"`".$this->fields["right"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " . |
|
"`".$this->fields["level"]."` - (".$ldif.") " . |
|
"FROM `".$this->table."` " . |
|
"WHERE " . |
|
"`".$this->fields["id"]."` IN (".implode(",", $node_ids).") " . |
|
"ORDER BY `".$this->fields["level"]."` ASC"; |
|
} |
|
else { |
|
$sql[] = "" . |
|
"UPDATE `".$this->table."` SET " . |
|
"`".$this->fields["parent_id"]."` = ".$ref_id.", " . |
|
"`".$this->fields["position"]."` = ".$position." " . |
|
"WHERE " . |
|
"`".$this->fields["id"]."` = ".$id; |
|
$sql[] = "" . |
|
"UPDATE `".$this->table."` SET " . |
|
"`".$this->fields["left"]."` = `".$this->fields["left"]."` - (".$idif."), " . |
|
"`".$this->fields["right"]."` = `".$this->fields["right"]."` - (".$idif."), " . |
|
"`".$this->fields["level"]."` = `".$this->fields["level"]."` - (".$ldif.") " . |
|
"WHERE " . |
|
"`".$this->fields["id"]."` IN (".implode(",", $node_ids).") "; |
|
} |
|
} |
|
else { |
|
$sql[] = "" . |
|
"INSERT INTO `".$this->table."` (" . |
|
"`".$this->fields["parent_id"]."`, " . |
|
"`".$this->fields["position"]."`, " . |
|
"`".$this->fields["left"]."`, " . |
|
"`".$this->fields["right"]."`, " . |
|
"`".$this->fields["level"]."` " . |
|
") " . |
|
"VALUES (" . |
|
$ref_id.", " . |
|
$position.", " . |
|
$idif.", " . |
|
($idif + 1).", " . |
|
$ldif. |
|
")"; |
|
} |
|
foreach($sql as $q) { $this->db->query($q); } |
|
$ind = $this->db->insert_id(); |
|
if($is_copy) $this->_fix_copy($ind, $position); |
|
return $node === false || $is_copy ? $ind : true; |
|
} |
|
function _fix_copy($id, $position) { |
|
$node = $this->_get_node($id); |
|
$children = $this->_get_children($id, true); |
|
|
|
$map = array(); |
|
for($i = $node[$this->fields["left"]] + 1; $i < $node[$this->fields["right"]]; $i++) { |
|
$map[$i] = $id; |
|
} |
|
foreach($children as $cid => $child) { |
|
if((int)$cid == (int)$id) { |
|
$this->db->query("UPDATE `".$this->table."` SET `".$this->fields["position"]."` = ".$position." WHERE `".$this->fields["id"]."` = ".$cid); |
|
continue; |
|
} |
|
$this->db->query("UPDATE `".$this->table."` SET `".$this->fields["parent_id"]."` = ".$map[(int)$child[$this->fields["left"]]]." WHERE `".$this->fields["id"]."` = ".$cid); |
|
for($i = $child[$this->fields["left"]] + 1; $i < $child[$this->fields["right"]]; $i++) { |
|
$map[$i] = $cid; |
|
} |
|
} |
|
} |
|
|
|
function _reconstruct() { |
|
$this->db->query("" . |
|
"CREATE TEMPORARY TABLE `temp_tree` (" . |
|
"`".$this->fields["id"]."` INTEGER NOT NULL, " . |
|
"`".$this->fields["parent_id"]."` INTEGER NOT NULL, " . |
|
"`". $this->fields["position"]."` INTEGER NOT NULL" . |
|
") type=HEAP" |
|
); |
|
$this->db->query("" . |
|
"INSERT INTO `temp_tree` " . |
|
"SELECT " . |
|
"`".$this->fields["id"]."`, " . |
|
"`".$this->fields["parent_id"]."`, " . |
|
"`".$this->fields["position"]."` " . |
|
"FROM `".$this->table."`" |
|
); |
|
|
|
$this->db->query("" . |
|
"CREATE TEMPORARY TABLE `temp_stack` (" . |
|
"`".$this->fields["id"]."` INTEGER NOT NULL, " . |
|
"`".$this->fields["left"]."` INTEGER, " . |
|
"`".$this->fields["right"]."` INTEGER, " . |
|
"`".$this->fields["level"]."` INTEGER, " . |
|
"`stack_top` INTEGER NOT NULL, " . |
|
"`".$this->fields["parent_id"]."` INTEGER, " . |
|
"`".$this->fields["position"]."` INTEGER " . |
|
") type=HEAP" |
|
); |
|
$counter = 2; |
|
$this->db->query("SELECT COUNT(*) FROM temp_tree"); |
|
$this->db->nextr(); |
|
$maxcounter = (int) $this->db->f(0) * 2; |
|
$currenttop = 1; |
|
$this->db->query("" . |
|
"INSERT INTO `temp_stack` " . |
|
"SELECT " . |
|
"`".$this->fields["id"]."`, " . |
|
"1, " . |
|
"NULL, " . |
|
"0, " . |
|
"1, " . |
|
"`".$this->fields["parent_id"]."`, " . |
|
"`".$this->fields["position"]."` " . |
|
"FROM `temp_tree` " . |
|
"WHERE `".$this->fields["parent_id"]."` = 0" |
|
); |
|
$this->db->query("DELETE FROM `temp_tree` WHERE `".$this->fields["parent_id"]."` = 0"); |
|
|
|
while ($counter <= $maxcounter) { |
|
$this->db->query("" . |
|
"SELECT " . |
|
"`temp_tree`.`".$this->fields["id"]."` AS tempmin, " . |
|
"`temp_tree`.`".$this->fields["parent_id"]."` AS pid, " . |
|
"`temp_tree`.`".$this->fields["position"]."` AS lid " . |
|
"FROM `temp_stack`, `temp_tree` " . |
|
"WHERE " . |
|
"`temp_stack`.`".$this->fields["id"]."` = `temp_tree`.`".$this->fields["parent_id"]."` AND " . |
|
"`temp_stack`.`stack_top` = ".$currenttop." " . |
|
"ORDER BY `temp_tree`.`".$this->fields["position"]."` ASC LIMIT 1" |
|
); |
|
|
|
if ($this->db->nextr()) { |
|
$tmp = $this->db->f("tempmin"); |
|
|
|
$q = "INSERT INTO temp_stack (stack_top, `".$this->fields["id"]."`, `".$this->fields["left"]."`, `".$this->fields["right"]."`, `".$this->fields["level"]."`, `".$this->fields["parent_id"]."`, `".$this->fields["position"]."`) VALUES(".($currenttop + 1).", ".$tmp.", ".$counter.", NULL, ".$currenttop.", ".$this->db->f("pid").", ".$this->db->f("lid").")"; |
|
$this->db->query($q); |
|
$this->db->query("DELETE FROM `temp_tree` WHERE `".$this->fields["id"]."` = ".$tmp); |
|
$counter++; |
|
$currenttop++; |
|
} |
|
else { |
|
$this->db->query("" . |
|
"UPDATE temp_stack SET " . |
|
"`".$this->fields["right"]."` = ".$counter.", " . |
|
"`stack_top` = -`stack_top` " . |
|
"WHERE `stack_top` = ".$currenttop |
|
); |
|
$counter++; |
|
$currenttop--; |
|
} |
|
} |
|
|
|
$temp_fields = $this->fields; |
|
unset($temp_fields["parent_id"]); |
|
unset($temp_fields["position"]); |
|
unset($temp_fields["left"]); |
|
unset($temp_fields["right"]); |
|
unset($temp_fields["level"]); |
|
if(count($temp_fields) > 1) { |
|
$this->db->query("" . |
|
"CREATE TEMPORARY TABLE `temp_tree2` " . |
|
"SELECT `".implode("`, `", $temp_fields)."` FROM `".$this->table."` " |
|
); |
|
} |
|
$this->db->query("TRUNCATE TABLE `".$this->table."`"); |
|
$this->db->query("" . |
|
"INSERT INTO ".$this->table." (" . |
|
"`".$this->fields["id"]."`, " . |
|
"`".$this->fields["parent_id"]."`, " . |
|
"`".$this->fields["position"]."`, " . |
|
"`".$this->fields["left"]."`, " . |
|
"`".$this->fields["right"]."`, " . |
|
"`".$this->fields["level"]."` " . |
|
") " . |
|
"SELECT " . |
|
"`".$this->fields["id"]."`, " . |
|
"`".$this->fields["parent_id"]."`, " . |
|
"`".$this->fields["position"]."`, " . |
|
"`".$this->fields["left"]."`, " . |
|
"`".$this->fields["right"]."`, " . |
|
"`".$this->fields["level"]."` " . |
|
"FROM temp_stack " . |
|
"ORDER BY `".$this->fields["id"]."`" |
|
); |
|
if(count($temp_fields) > 1) { |
|
$sql = "" . |
|
"UPDATE `".$this->table."` v, `temp_tree2` SET v.`".$this->fields["id"]."` = v.`".$this->fields["id"]."` "; |
|
foreach($temp_fields as $k => $v) { |
|
if($k == "id") continue; |
|
$sql .= ", v.`".$v."` = `temp_tree2`.`".$v."` "; |
|
} |
|
$sql .= " WHERE v.`".$this->fields["id"]."` = `temp_tree2`.`".$this->fields["id"]."` "; |
|
$this->db->query($sql); |
|
} |
|
} |
|
|
|
function _analyze() { |
|
$report = array(); |
|
|
|
$this->db->query("" . |
|
"SELECT " . |
|
"`".$this->fields["left"]."` FROM `".$this->table."` s " . |
|
"WHERE " . |
|
"`".$this->fields["parent_id"]."` = 0 " |
|
); |
|
$this->db->nextr(); |
|
if($this->db->nf() == 0) { |
|
$report[] = "[FAIL]\tNo root node."; |
|
} |
|
else { |
|
$report[] = ($this->db->nf() > 1) ? "[FAIL]\tMore than one root node." : "[OK]\tJust one root node."; |
|
} |
|
$report[] = ($this->db->f(0) != 1) ? "[FAIL]\tRoot node's left index is not 1." : "[OK]\tRoot node's left index is 1."; |
|
|
|
$this->db->query("" . |
|
"SELECT " . |
|
"COUNT(*) FROM `".$this->table."` s " . |
|
"WHERE " . |
|
"`".$this->fields["parent_id"]."` != 0 AND " . |
|
"(SELECT COUNT(*) FROM `".$this->table."` WHERE `".$this->fields["id"]."` = s.`".$this->fields["parent_id"]."`) = 0 "); |
|
$this->db->nextr(); |
|
$report[] = ($this->db->f(0) > 0) ? "[FAIL]\tMissing parents." : "[OK]\tNo missing parents."; |
|
|
|
$this->db->query("SELECT MAX(`".$this->fields["right"]."`) FROM `".$this->table."`"); |
|
$this->db->nextr(); |
|
$n = $this->db->f(0); |
|
$this->db->query("SELECT COUNT(*) FROM `".$this->table."`"); |
|
$this->db->nextr(); |
|
$c = $this->db->f(0); |
|
$report[] = ($n/2 != $c) ? "[FAIL]\tRight index does not match node count." : "[OK]\tRight index matches count."; |
|
|
|
$this->db->query("" . |
|
"SELECT COUNT(`".$this->fields["id"]."`) FROM `".$this->table."` s " . |
|
"WHERE " . |
|
"(SELECT COUNT(*) FROM `".$this->table."` WHERE " . |
|
"`".$this->fields["right"]."` < s.`".$this->fields["right"]."` AND " . |
|
"`".$this->fields["left"]."` > s.`".$this->fields["left"]."` AND " . |
|
"`".$this->fields["level"]."` = s.`".$this->fields["level"]."` + 1" . |
|
") != " . |
|
"(SELECT COUNT(*) FROM `".$this->table."` WHERE " . |
|
"`".$this->fields["parent_id"]."` = s.`".$this->fields["id"]."`" . |
|
") " |
|
); |
|
$this->db->nextr(); |
|
$report[] = ($this->db->f(0) > 0) ? "[FAIL]\tAdjacency and nested set do not match." : "[OK]\tNS and AJ match"; |
|
|
|
return implode("<br />",$report); |
|
} |
|
|
|
function _dump($output = false) { |
|
$nodes = array(); |
|
$this->db->query("SELECT * FROM ".$this->table." ORDER BY `".$this->fields["left"]."`"); |
|
while($this->db->nextr()) $nodes[] = $this->db->get_row("assoc"); |
|
if($output) { |
|
echo "<pre>"; |
|
foreach($nodes as $node) { |
|
echo str_repeat(" ",(int)$node[$this->fields["level"]] * 2); |
|
echo $node[$this->fields["id"]]." (".$node[$this->fields["left"]].",".$node[$this->fields["right"]].",".$node[$this->fields["level"]].",".$node[$this->fields["parent_id"]].",".$node[$this->fields["position"]].")<br />"; |
|
} |
|
echo str_repeat("-",40); |
|
echo "</pre>"; |
|
} |
|
return $nodes; |
|
} |
|
function _drop() { |
|
$this->db->query("TRUNCATE TABLE `".$this->table."`"); |
|
$this->db->query("" . |
|
"INSERT INTO `".$this->table."` (" . |
|
"`".$this->fields["id"]."`, " . |
|
"`".$this->fields["parent_id"]."`, " . |
|
"`".$this->fields["position"]."`, " . |
|
"`".$this->fields["left"]."`, " . |
|
"`".$this->fields["right"]."`, " . |
|
"`".$this->fields["level"]."` " . |
|
") " . |
|
"VALUES (" . |
|
"1, " . |
|
"0, " . |
|
"0, " . |
|
"1, " . |
|
"2, " . |
|
"0 ". |
|
")"); |
|
} |
|
} |
|
|
|
class json_tree extends _tree_struct { |
|
function __construct($table = "tree", $fields = array(), $add_fields = array("title" => "title", "type" => "type")) { |
|
parent::__construct($table, $fields); |
|
$this->fields = array_merge($this->fields, $add_fields); |
|
$this->add_fields = $add_fields; |
|
} |
|
|
|
function create_node($data) { |
|
$id = parent::_create((int)$data[$this->fields["id"]], (int)$data[$this->fields["position"]]); |
|
if($id) { |
|
$data["id"] = $id; |
|
$this->set_data($data); |
|
return "{ \"status\" : 1, \"id\" : ".(int)$id." }"; |
|
} |
|
return "{ \"status\" : 0 }"; |
|
} |
|
function set_data($data) { |
|
if(count($this->add_fields) == 0) { return "{ \"status\" : 1 }"; } |
|
$s = "UPDATE `".$this->table."` SET `".$this->fields["id"]."` = `".$this->fields["id"]."` "; |
|
foreach($this->add_fields as $k => $v) { |
|
if(isset($data[$k])) $s .= ", `".$this->fields[$v]."` = \"".$this->db->escape($data[$k])."\" "; |
|
else $s .= ", `".$this->fields[$v]."` = `".$this->fields[$v]."` "; |
|
} |
|
$s .= "WHERE `".$this->fields["id"]."` = ".(int)$data["id"]; |
|
$this->db->query($s); |
|
return "{ \"status\" : 1 }"; |
|
} |
|
function rename_node($data) { return $this->set_data($data); } |
|
|
|
function move_node($data) { |
|
$id = parent::_move((int)$data["id"], (int)$data["ref"], (int)$data["position"], (int)$data["copy"]); |
|
if(!$id) return "{ \"status\" : 0 }"; |
|
if((int)$data["copy"] && count($this->add_fields)) { |
|
$ids = array_keys($this->_get_children($id, true)); |
|
$data = $this->_get_children((int)$data["id"], true); |
|
|
|
$i = 0; |
|
foreach($data as $dk => $dv) { |
|
$s = "UPDATE `".$this->table."` SET `".$this->fields["id"]."` = `".$this->fields["id"]."` "; |
|
foreach($this->add_fields as $k => $v) { |
|
if(isset($dv[$k])) $s .= ", `".$this->fields[$v]."` = \"".$this->db->escape($dv[$k])."\" "; |
|
else $s .= ", `".$this->fields[$v]."` = `".$this->fields[$v]."` "; |
|
} |
|
$s .= "WHERE `".$this->fields["id"]."` = ".$ids[$i]; |
|
$this->db->query($s); |
|
$i++; |
|
} |
|
} |
|
return "{ \"status\" : 1, \"id\" : ".$id." }"; |
|
} |
|
function remove_node($data) { |
|
$id = parent::_remove((int)$data["id"]); |
|
return "{ \"status\" : 1 }"; |
|
} |
|
function get_children($data) { |
|
$tmp = $this->_get_children((int)$data["id"]); |
|
if((int)$data["id"] === 1 && count($tmp) === 0) { |
|
$this->_create_default(); |
|
$tmp = $this->_get_children((int)$data["id"]); |
|
} |
|
$result = array(); |
|
if((int)$data["id"] === 0) return json_encode($result); |
|
foreach($tmp as $k => $v) { |
|
$result[] = array( |
|
"attr" => array("id" => "node_".$k, "rel" => $v[$this->fields["type"]]), |
|
"data" => $v[$this->fields["title"]], |
|
"state" => ((int)$v[$this->fields["right"]] - (int)$v[$this->fields["left"]] > 1) ? "closed" : "" |
|
); |
|
} |
|
return json_encode($result); |
|
} |
|
function search($data) { |
|
$this->db->query("SELECT `".$this->fields["left"]."`, `".$this->fields["right"]."` FROM `".$this->table."` WHERE `".$this->fields["title"]."` LIKE '%".$this->db->escape($data["search_str"])."%'"); |
|
if($this->db->nf() === 0) return "[]"; |
|
$q = "SELECT DISTINCT `".$this->fields["id"]."` FROM `".$this->table."` WHERE 0 "; |
|
while($this->db->nextr()) { |
|
$q .= " OR (`".$this->fields["left"]."` < ".(int)$this->db->f(0)." AND `".$this->fields["right"]."` > ".(int)$this->db->f(1).") "; |
|
} |
|
$result = array(); |
|
$this->db->query($q); |
|
while($this->db->nextr()) { $result[] = "#node_".$this->db->f(0); } |
|
return json_encode($result); |
|
} |
|
|
|
function _create_default() { |
|
$this->_drop(); |
|
$this->create_node(array( |
|
"id" => 1, |
|
"position" => 0, |
|
"title" => "C:", |
|
"type" => "drive" |
|
)); |
|
$this->create_node(array( |
|
"id" => 1, |
|
"position" => 1, |
|
"title" => "D:", |
|
"type" => "drive" |
|
)); |
|
$this->create_node(array( |
|
"id" => 2, |
|
"position" => 0, |
|
"title" => "_demo", |
|
"type" => "folder" |
|
)); |
|
$this->create_node(array( |
|
"id" => 2, |
|
"position" => 1, |
|
"title" => "_docs", |
|
"type" => "folder" |
|
)); |
|
$this->create_node(array( |
|
"id" => 4, |
|
"position" => 0, |
|
"title" => "index.html", |
|
"type" => "default" |
|
)); |
|
$this->create_node(array( |
|
"id" => 5, |
|
"position" => 1, |
|
"title" => "doc.html", |
|
"type" => "default" |
|
)); |
|
} |
|
} |
|
|
|
?>
|