4include_once 
'./Services/Tree/interfaces/interface.ilTreeImplementation.php';
 
   26        $this->tree = $a_tree;
 
   47        $query = 
'SELECT s.child FROM ' .
 
   48            $this->
getTree()->getTreeTable() . 
' s, ' .
 
   49            $this->
getTree()->getTreeTable() . 
' t ' .
 
   50            'WHERE t.child = %s ' .
 
   51            'AND s.lft > t.lft ' .
 
   52            'AND s.rgt < t.rgt ' .
 
   53            'AND s.' . $this->
getTree()->getTreePk() . 
' = %s';
 
   57            array(
'integer',
'integer'),
 
   58            array($a_node_id,$this->
getTree()->getTreeId())
 
   61            $childs[] = 
$row->child;
 
   63        return $childs ? $childs : array();
 
   75    public function getSubTreeQuery($a_node, $a_types = 
'', $a_force_join_reference = 
true, $a_fields = array())
 
   80        if (is_array($a_types)) {
 
   82                $type_str = 
"AND " . 
$ilDB->in($this->
getTree()->getObjectDataTable() . 
".type", $a_types, 
false, 
"text");
 
   84        } elseif (strlen($a_types)) {
 
   85            $type_str = 
"AND " . $this->
getTree()->getObjectDataTable() . 
".type = " . $ilDB->quote($a_types, 
"text");
 
   89        if ($type_str or $a_force_join_reference) {
 
   90            $join = $this->
getTree()->buildJoin();
 
   94        if (count($a_fields)) {
 
   95            $fields = implode(
',', $a_fields);
 
  100            "FROM " . $this->
getTree()->getTreeTable() . 
" " .
 
  102            "WHERE " . $this->
getTree()->getTreeTable() . 
'.lft ' .
 
  103            'BETWEEN ' . $ilDB->quote($a_node[
'lft'], 
'integer') . 
' ' .
 
  104            'AND ' . 
$ilDB->quote($a_node[
'rgt'], 
'integer') . 
' ' .
 
  105            "AND " . $this->
getTree()->getTreeTable() . 
"." . $this->
getTree()->getTreePk() . 
" = " . $ilDB->quote($this->
getTree()->getTreeId(), 
'integer') . 
' ' .
 
  107            "ORDER BY " . $this->
getTree()->getTreeTable() . 
".lft";
 
  109        #ilLoggerFactory::getLogger('tree')->debug('-----------------: '. $query); 
  123        if ($a_node_a[
'child'] == $a_node_b[
'child']) {
 
  127        if ($a_node_a[
'lft'] < $a_node_b[
'lft'] and $a_node_a[
'rgt'] > $a_node_b[
'rgt']) {
 
  131        if ($a_node_b[
'lft'] < $a_node_a[
'lft'] and $a_node_b[
'rgt'] > $a_node_a[
'rgt']) {
 
  137        if ($a_node_a[
'parent'] == $a_node_b[
'parent']) {
 
  168        $insert_node_callable = 
function (
ilDBInterface $ilDB) use ($a_node_id, $a_parent_id, $a_pos) {
 
  174                        'SELECT * FROM ' . $this->
getTree()->getTreeTable() . 
' ' .
 
  175                        'WHERE child = %s ' .
 
  176                        'AND ' . $this->
getTree()->getTreePk() . 
' = %s ',
 
  177                        $ilDB->quote($a_parent_id, 
'integer'),
 
  178                        $ilDB->quote($this->getTree()->getTreeId(), 
'integer')
 
  184                    if (
$r->parent === 
null) {
 
  195                        'UPDATE ' . $this->
getTree()->getTreeTable() . 
' SET ' .
 
  196                        'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, ' .
 
  197                        'rgt = CASE WHEN rgt > %s THEN rgt + 2 ELSE rgt END ' .
 
  198                        'WHERE ' . $this->
getTree()->getTreePk() . 
' = %s ',
 
  199                        $ilDB->quote($left, 
'integer'),
 
  200                        $ilDB->quote($left, 
'integer'),
 
  201                        $ilDB->quote($this->getTree()->getTreeId(), 
'integer')
 
  208                    if ($this->
getTree()->getGap() > 0) {
 
  211                            'SELECT rgt,lft,parent FROM ' . $this->
getTree()->getTreeTable() . 
' ' .
 
  212                            'WHERE child = %s ' .
 
  213                            'AND ' . $this->
getTree()->getTreePk() . 
' =  %s',
 
  214                            $ilDB->quote($a_parent_id, 
'integer'),
 
  215                            $ilDB->quote($this->getTree()->getTreeId(), 
'integer')
 
  220                        if (
$r[
'parent'] === 
null) {
 
  224                        $parentRgt = 
$r[
'rgt'];
 
  225                        $parentLft = 
$r[
'lft'];
 
  228                        $availableSpace = $parentRgt - $parentLft;
 
  229                        if ($availableSpace < 2) {
 
  238                                'SELECT MAX(rgt) max_rgt FROM ' . $this->
getTree()->getTreeTable() . 
' ' .
 
  239                                'WHERE parent = %s ' .
 
  240                                'AND ' . $this->
getTree()->getTreePk() . 
' = %s',
 
  241                                $ilDB->quote($a_parent_id, 
'integer'),
 
  242                                $ilDB->quote($this->getTree()->getTreeId(), 
'integer')
 
  247                            if (isset(
$r[
'max_rgt'])) {
 
  250                                $availableSpace = $parentRgt - 
$r[
'max_rgt'];
 
  251                                $lft = 
$r[
'max_rgt'] + 1;
 
  256                                $lft = $parentLft + 1;
 
  263                        if ($availableSpace < 2) {
 
  266                                'UPDATE ' . $this->
getTree()->getTreeTable() . 
' SET ' .
 
  267                                'lft = CASE WHEN lft  > %s THEN lft + %s ELSE lft END, ' .
 
  268                                'rgt = CASE WHEN rgt >= %s THEN rgt + %s ELSE rgt END ' .
 
  269                                'WHERE ' . $this->
getTree()->getTreePk() . 
' = %s ',
 
  270                                $ilDB->quote($parentRgt, 
'integer'),
 
  271                                $ilDB->quote((2 + $this->getTree()->getGap() * 2), 
'integer'),
 
  272                                $ilDB->quote($parentRgt, 
'integer'),
 
  273                                $ilDB->quote((2 + $this->getTree()->getGap() * 2), 
'integer'),
 
  274                                $ilDB->quote($this->getTree()->getTreeId(), 
'integer')
 
  284                            'SELECT * FROM ' . $this->
getTree()->getTreeTable() . 
' ' .
 
  285                            'WHERE child = %s ' .
 
  286                            'AND ' . $this->
getTree()->getTreePk() . 
' = %s ',
 
  287                            $ilDB->quote($a_parent_id, 
'integer'),
 
  288                            $ilDB->quote($this->getTree()->getTreeId(), 
'integer')
 
  293                        if (
$r->parent === 
null) {
 
  304                            'UPDATE ' . $this->
getTree()->getTreeTable() . 
' SET ' .
 
  305                            'lft = CASE WHEN lft >  %s THEN lft + 2 ELSE lft END, ' .
 
  306                            'rgt = CASE WHEN rgt >= %s THEN rgt + 2 ELSE rgt END ' .
 
  307                            'WHERE ' . $this->
getTree()->getTreePk() . 
' = %s',
 
  308                            $ilDB->quote($right, 
'integer'),
 
  309                            $ilDB->quote($right, 
'integer'),
 
  310                            $ilDB->quote($this->getTree()->getTreeId(), 
'integer')
 
  321                        'SELECT * FROM ' . $this->
getTree()->getTreeTable() . 
' ' .
 
  322                        'WHERE child = %s ' .
 
  323                        'AND ' . $this->
getTree()->getTreePk() . 
' = %s ',
 
  324                        $ilDB->quote($a_pos, 
'integer'),
 
  325                        $ilDB->quote($this->getTree()->getTreeId(), 
'integer')
 
  331                    if (
$r->parent != $a_parent_id) {
 
  342                        'UPDATE ' . $this->
getTree()->getTreeTable() . 
' SET ' .
 
  343                        'lft = CASE WHEN lft >  %s THEN lft + 2 ELSE lft END, ' .
 
  344                        'rgt = CASE WHEN rgt >  %s THEN rgt + 2 ELSE rgt END ' .
 
  345                        'WHERE ' . $this->
getTree()->getTreePk() . 
' = %s',
 
  346                        $ilDB->quote($right, 
'integer'),
 
  347                        $ilDB->quote($right, 
'integer'),
 
  348                        $ilDB->quote($this->getTree()->getTreeId(), 
'integer')
 
  356            $depth = $this->
getTree()->getDepth($a_parent_id) + 1;
 
  360                'INSERT INTO ' . $this->
getTree()->getTreeTable() . 
' (' . $this->
getTree()->getTreePk() . 
',child,parent,lft,rgt,depth) ' .
 
  361                'VALUES (%s,%s,%s,%s,%s,%s)',
 
  362                $ilDB->quote($this->getTree()->getTreeId(), 
'integer'),
 
  363                $ilDB->quote($a_node_id, 
'integer'),
 
  364                $ilDB->quote($a_parent_id, 
'integer'),
 
  365                $ilDB->quote($lft, 
'integer'),
 
  366                $ilDB->quote($rgt, 
'integer'),
 
  367                $ilDB->quote($depth, 
'integer')
 
  372        if ($this->
getTree()->__isMainTree()) {
 
  373            $ilAtomQuery = 
$ilDB->buildAtomQuery();
 
  374            $ilAtomQuery->addTableLock(
'tree');
 
  375            $ilAtomQuery->addQueryCallable($insert_node_callable);
 
  378            $insert_node_callable(
$ilDB);
 
  396            $query = 
'SELECT *  FROM ' . $this->
getTree()->getTreeTable() . 
' ' .
 
  397                'WHERE child = ' . $ilDB->quote($a_node_id, 
'integer') . 
' ' .
 
  398                'AND ' . $this->
getTree()->getTreePk() . 
' = ' . $ilDB->quote($this->
getTree()->getTreeId(), 
'integer');
 
  404                'DELETE FROM ' . $this->
getTree()->getTreeTable() . 
' ' .
 
  405                'WHERE lft BETWEEN %s AND %s ' .
 
  406                'AND rgt BETWEEN %s AND %s ' .
 
  407                'AND ' . $this->
getTree()->getTreePk() . 
' = %s',
 
  408                $ilDB->quote($a_node[
'lft'], 
'integer'),
 
  409                $ilDB->quote($a_node[
'rgt'], 
'integer'),
 
  410                $ilDB->quote($a_node[
'lft'], 
'integer'),
 
  411                $ilDB->quote($a_node[
'rgt'], 
'integer'),
 
  412                $ilDB->quote($a_node[$this->getTree()->getTreePk()], 
'integer')
 
  420            $diff = $a_node[
"rgt"] - $a_node[
"lft"] + 1;
 
  422                $a_node[$this->
getTree()->getTreePk()] >= 0 &&
 
  423                $a_node[
'rgt'] - $a_node[
'lft'] >= $this->
getTree()->getGap() * 2
 
  427                    'UPDATE ' . $this->
getTree()->getTreeTable() . 
' SET ' .
 
  428                    'lft = CASE WHEN lft > %s THEN lft - %s ELSE lft END, ' .
 
  429                    'rgt = CASE WHEN rgt > %s THEN rgt - %s ELSE rgt END ' .
 
  430                    'WHERE ' . $this->
getTree()->getTreePk() . 
' = %s ',
 
  431                    $ilDB->quote($a_node[
'lft'], 
'integer'),
 
  432                    $ilDB->quote($diff, 
'integer'),
 
  433                    $ilDB->quote($a_node[
'lft'], 
'integer'),
 
  434                    $ilDB->quote($diff, 
'integer'),
 
  435                    $ilDB->quote($a_node[$this->getTree()->getTreePk()], 
'integer')
 
  443        if ($this->
getTree()->__isMainTree()) {
 
  444            $ilAtomQuery = 
$ilDB->buildAtomQuery();
 
  445            $ilAtomQuery->addTableLock(
'tree');
 
  446            $ilAtomQuery->addQueryCallable($delete_tree_callable);
 
  449            $delete_tree_callable(
$ilDB);
 
  468            $node = $this->
getTree()->getNodeTreeData($a_node_id);
 
  470            $query = 
'UPDATE ' . $this->
getTree()->getTreeTable() . 
' ' .
 
  471                'SET tree = ' . $ilDB->quote(-1 * $node[
'child'], 
'integer') . 
' ' .
 
  472                'WHERE ' . $this->
getTree()->getTreePk() . 
' =  ' . $ilDB->quote($this->
getTree()->getTreeId(), 
'integer') . 
' ' .
 
  473                'AND lft BETWEEN ' . 
$ilDB->quote($node[
'lft'], 
'integer') . 
' AND ' . 
$ilDB->quote($node[
'rgt'], 
'integer') . 
' ';
 
  480        if ($this->
getTree()->__isMainTree()) {
 
  481            $ilAtomQuery = 
$ilDB->buildAtomQuery();
 
  482            $ilAtomQuery->addTableLock(
"tree");
 
  484            $ilAtomQuery->addQueryCallable($move_to_trash_callable);
 
  488            $move_to_trash_callable(
$ilDB);
 
  512        $takeId = $a_startnode_id == 0;
 
  514        $depth_cache = $this->
getTree()->getDepthCache();
 
  515        $parent_cache = $this->
getTree()->getParentCache();
 
  518            $this->
getTree()->__isMainTree() &&
 
  519            isset($depth_cache[$a_endnode_id]) &&
 
  520            isset($parent_cache[$a_endnode_id])) {
 
  521            $nodeDepth = $depth_cache[$a_endnode_id];
 
  522            $parentId = $parent_cache[$a_endnode_id];
 
  524            $nodeDepth = $this->
getTree()->getDepth($a_endnode_id);
 
  525            $parentId = $this->
getTree()->getParentId($a_endnode_id);
 
  534        } elseif ($nodeDepth == 1) {
 
  535            $takeId = $takeId || $a_endnode_id == $a_startnode_id;
 
  537                $pathIds[] = $a_endnode_id;
 
  539        } elseif ($nodeDepth == 2) {
 
  540            $takeId = $takeId || $parentId == $a_startnode_id;
 
  542                $pathIds[] = $parentId;
 
  544            $takeId = $takeId || $a_endnode_id == $a_startnode_id;
 
  546                $pathIds[] = $a_endnode_id;
 
  548        } elseif ($nodeDepth == 3) {
 
  549            $takeId = $takeId || $this->
getTree()->getRootId() == $a_startnode_id;
 
  551                $pathIds[] = $this->
getTree()->getRootId();
 
  553            $takeId = $takeId || $parentId == $a_startnode_id;
 
  555                $pathIds[] = $parentId;
 
  557            $takeId = $takeId || $a_endnode_id == $a_startnode_id;
 
  559                $pathIds[] = $a_endnode_id;
 
  561        } elseif ($nodeDepth < 32) {
 
  571            $qSelect = 
't1.child c0';
 
  573            for (
$i = 1; 
$i < $nodeDepth - 2; 
$i++) {
 
  574                $qSelect .= 
', t' . 
$i . 
'.parent c' . 
$i;
 
  575                $qJoin .= 
' JOIN ' . $this->
getTree()->getTreeTable() . 
' t' . 
$i . 
' ON ' .
 
  576                            't' . 
$i . 
'.child=t' . (
$i - 1) . 
'.parent AND ' .
 
  577                            't' . 
$i . 
'.' . $this->
getTree()->getTreePk() . 
' = ' . (int) $this->
getTree()->getTreeId();
 
  580            $types = array(
'integer',
'integer');
 
  582            $query = 
'SELECT ' . $qSelect . 
' ' .
 
  583                'FROM ' . $this->
getTree()->getTreeTable() . 
' t0 ' . $qJoin . 
' ' .
 
  584                'WHERE t0.' . $this->
getTree()->getTreePk() . 
' = %s ' .
 
  585                'AND t0.child = %s ';
 
  590            if (
$res->numRows() == 0) {
 
  596            $takeId = $takeId || $this->
getTree()->getRootId() == $a_startnode_id;
 
  598                $pathIds[] = $this->
getTree()->getRootId();
 
  600            for (
$i = $nodeDepth - 4; 
$i >=0; 
$i--) {
 
  601                $takeId = $takeId || 
$row[
'c' . 
$i] == $a_startnode_id;
 
  603                    $pathIds[] = 
$row[
'c' . 
$i];
 
  606            $takeId = $takeId || $parentId == $a_startnode_id;
 
  608                $pathIds[] = $parentId;
 
  610            $takeId = $takeId || $a_endnode_id == $a_startnode_id;
 
  612                $pathIds[] = $a_endnode_id;
 
  639        $fields = array(
'integer',
'integer',
'integer');
 
  642        $query = 
"SELECT T2.child " .
 
  643            "FROM " . $this->
getTree()->getTreeTable() . 
" T1, " . $this->
getTree()->getTreeTable() . 
" T2 " .
 
  644            "WHERE T1.child = %s " .
 
  645            "AND T1.lft BETWEEN T2.lft AND T2.rgt " .
 
  646            "AND T1." . $this->
getTree()->getTreePk() . 
" = %s " .
 
  647            "AND T2." . $this->
getTree()->getTreePk() . 
" = %s " .
 
  652        $takeId = $a_startnode_id == 0;
 
  654            if ($takeId || 
$row[
'child'] == $a_startnode_id) {
 
  656                $pathIds[] = 
$row[
'child'];
 
  659        return $pathIds ? $pathIds : array();
 
  671    public function moveTree($a_source_id, $a_target_id, $a_position)
 
  675        $move_tree_callable = 
function (
ilDBInterface $ilDB) use ($a_source_id, $a_target_id, $a_position) {
 
  677            $query = 
'SELECT * FROM ' . $this->
getTree()->getTreeTable() . 
' ' .
 
  678                'WHERE ( child = %s OR child = %s ) ' .
 
  679                'AND ' . $this->
getTree()->getTreePk() . 
' = %s ';
 
  680            $res = $ilDB->queryF(
$query, array(
'integer', 
'integer', 
'integer'), array(
 
  683                $this->
getTree()->getTreeId()));
 
  686            if (
$res->numRows() != 2) {
 
  688                throw new InvalidArgumentException(
'Error moving subtree');
 
  691                if (
$row->child == $a_source_id) {
 
  692                    $source_lft = 
$row->lft;
 
  693                    $source_rgt = 
$row->rgt;
 
  694                    $source_depth = 
$row->depth;
 
  695                    $source_parent = 
$row->parent;
 
  697                    $target_lft = 
$row->lft;
 
  698                    $target_rgt = 
$row->rgt;
 
  699                    $target_depth = 
$row->depth;
 
  704            if ($target_lft >= $source_lft and $target_rgt <= $source_rgt) {
 
  706                throw new InvalidArgumentException(
'Error moving subtree: target is child of source');
 
  711            $spread_diff = $source_rgt - $source_lft + 1;
 
  712            #var_dump("<pre>","SPREAD_DIFF: ",$spread_diff,"<pre>");
 
  714            $query = 
'UPDATE ' . $this->
getTree()->getTreeTable() . 
' SET ' .
 
  715                'lft = CASE WHEN lft >  %s THEN lft + %s ELSE lft END, ' .
 
  716                'rgt = CASE WHEN rgt >= %s THEN rgt + %s ELSE rgt END ' .
 
  717                'WHERE ' . $this->
getTree()->getTreePk() . 
' = %s ';
 
  718            $res = $ilDB->manipulateF(
$query, array(
'integer', 
'integer', 
'integer', 
'integer', 
'integer'), array(
 
  723                $this->
getTree()->getTreeId()));
 
  727            if ($source_lft > $target_rgt) {
 
  728                $where_offset = $spread_diff;
 
  729                $move_diff = $target_rgt - $source_lft - $spread_diff;
 
  732                $move_diff = $target_rgt - $source_lft;
 
  734            $depth_diff = $target_depth - $source_depth + 1;
 
  737            $query = 
'UPDATE ' . $this->
getTree()->getTreeTable() . 
' SET ' .
 
  738                'parent = CASE WHEN parent = %s THEN %s ELSE parent END, ' .
 
  741                'depth = depth + %s ' .
 
  744                'AND ' . $this->
getTree()->getTreePk() . 
' = %s ';
 
  745            $res = $ilDB->manipulateF(
$query, array(
'integer', 
'integer', 
'integer', 
'integer', 
'integer', 
'integer', 
'integer', 
'integer'), array(
 
  751                $source_lft + $where_offset,
 
  752                $source_rgt + $where_offset,
 
  753                $this->
getTree()->getTreeId()));
 
  756            $query = 
'UPDATE ' . $this->
getTree()->getTreeTable() . 
' SET ' .
 
  757                'lft = CASE WHEN lft >= %s THEN lft - %s ELSE lft END, ' .
 
  758                'rgt = CASE WHEN rgt >= %s THEN rgt - %s ELSE rgt END ' .
 
  759                'WHERE ' . $this->
getTree()->getTreePk() . 
' = %s ';
 
  761            $res = $ilDB->manipulateF(
$query, array(
'integer', 
'integer', 
'integer', 
'integer', 
'integer'), array(
 
  762                $source_lft + $where_offset,
 
  764                $source_rgt + $where_offset,
 
  766                $this->
getTree()->getTreeId()));
 
  770        if ($this->
getTree()->__isMainTree()) {
 
  771            $ilAtomQuery = 
$ilDB->buildAtomQuery();
 
  772            $ilAtomQuery->addTableLock(
'tree');
 
  773            $ilAtomQuery->addQueryCallable($move_tree_callable);
 
  776            $move_tree_callable(
$ilDB);
 
  790        $query = 
"SELECT t2.lft lft, t2.rgt rgt, t2.child child, type " .
 
  791            "FROM " . $this->
getTree()->getTreeTable() . 
" t1 " .
 
  792            "JOIN " . $this->
getTree()->getTreeTable() . 
" t2 ON (t2.lft BETWEEN t1.lft AND t1.rgt) " .
 
  793            "JOIN " . $this->
getTree()->getTableReference() . 
" obr ON t2.child = obr.ref_id " .
 
  794            "JOIN " . $this->
getTree()->getObjectDataTable() . 
" obd ON obr.obj_id = obd.obj_id " .
 
  795            "WHERE t1.child = " . $ilDB->quote($a_endnode_id, 
'integer') . 
" " .
 
  796            "AND t1." . $this->
getTree()->getTreePk() . 
" = " . $ilDB->quote($this->
getTree()->getTreeId(), 
'integer') . 
" " .
 
  797            "AND t2." . $this->
getTree()->getTreePk() . 
" = " . $ilDB->quote($this->
getTree()->getTreeId(), 
'integer') . 
" " .
 
  806            $nodes[
$row->child][
'lft']  = 
$row->lft;
 
  807            $nodes[
$row->child][
'rgt']  = 
$row->rgt;
 
  808            $nodes[
$row->child][
'child']= 
$row->child;
 
  809            $nodes[
$row->child][
'type'] = 
$row->type;
 
  811        return (array) $nodes;
 
  821        $query = 
'select child from ' . $this->
getTree()->getTreeTable() . 
' child where not exists ' .
 
  823                'select child from ' . $this->
getTree()->getTreeTable() . 
' parent where child.parent = parent.child and (parent.lft < child.lft) and (parent.rgt > child.rgt) ' .
 
  825                'and ' . $this->
getTree()->getTreePk() . 
' = ' . $this->
getTree()->getTreeId() . 
' and child <> 1';
 
sprintf('%.4f', $callTime)
An exception for terminatinating execution or to throw for unit testing.
Thrown if invalid tree strucutes are found.
static getLogger($a_component_id)
Get component logger.
Base class for nested set path based trees.
moveToTrash($a_node_id)
Move to trash.
getRelation($a_node_a, $a_node_b)
Get relation.
insertNode($a_node_id, $a_parent_id, $a_pos)
Insert tree node.
getPathIds($a_endnode, $a_startnode=0)
Get path ids.
getTree()
Get tree object.
deleteTree($a_node_id)
Delete a subtree.
getSubTreeQuery($a_node, $a_types='', $a_force_join_reference=true, $a_fields=array())
Get subtree.
moveTree($a_source_id, $a_target_id, $a_position)
Move source subtree to target.
getPathIdsUsingAdjacencyMap($a_endnode_id, $a_startnode_id=0)
get path from a given startnode to a given endnode if startnode is not given the rootnode is startnod...
__construct(ilTree $a_tree)
Constructor.
getSubtreeInfo($a_endnode_id)
Get rbac subtree info @global type $ilDB.
getPathIdsUsingNestedSets($a_endnode_id, $a_startnode_id=0)
get path from a given startnode to a given endnode if startnode is not given the rootnode is startnod...
validateParentRelations()
Validate the parent relations of the tree implementation For nested set, validate the lft,...
getSubTreeIds($a_node_id)
Get subtree ids.
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
Interface for tree implementations Currrently nested set or materialize path.
foreach($_POST as $key=> $value) $res