4 define(
"IL_LAST_NODE", -2);
 
    5 define(
"IL_FIRST_NODE", -1);
 
  130         function ilTree($a_tree_id, $a_root_id = 0)
 
  147                 $this->lang_code = 
"en";
 
  149                 if (!isset($a_tree_id) or (func_num_args() == 0) )
 
  151                         $this->ilErr->raiseError(get_class($this).
"::Constructor(): No tree_id given!",$this->ilErr->WARNING);
 
  154                 if (func_num_args() > 2)
 
  156                         $this->ilErr->raiseError(get_class($this).
"::Constructor(): Wrong parameter count!",$this->ilErr->WARNING);
 
  163                 if (empty($a_root_id))
 
  165                         $a_root_id = ROOT_FOLDER_ID;
 
  168                 $this->tree_id            = $a_tree_id;
 
  169                 $this->root_id            = $a_root_id;
 
  170                 $this->table_tree     = 
'tree';
 
  171                 $this->table_obj_data = 
'object_data';
 
  172                 $this->table_obj_reference = 
'object_reference';
 
  173                 $this->ref_pk = 
'ref_id';
 
  174                 $this->obj_pk = 
'obj_id';
 
  175                 $this->tree_pk = 
'tree';
 
  177                 $this->use_cache = 
true;
 
  180                 $this->translation_cache = array();
 
  181                 $this->parent_type_cache = array();
 
  192                 $this->use_cache = $a_use;
 
  213                 if (!is_object($ilUser))
 
  215                         $this->lang_code = 
"en";
 
  219                         $this->lang_code = $ilUser->getCurrentLanguage();
 
  238         function setTableNames($a_table_tree,$a_table_obj_data,$a_table_obj_reference = 
"")
 
  240                 if (!isset($a_table_tree) or !isset($a_table_obj_data))
 
  242                         $this->ilErr->raiseError(get_class($this).
"::setTableNames(): Missing parameter! ".
 
  243                                                                 "tree table: ".$a_table_tree.
" object data table: ".$a_table_obj_data,$this->ilErr->WARNING);
 
  246                 $this->table_tree = $a_table_tree;
 
  247                 $this->table_obj_data = $a_table_obj_data;
 
  248                 $this->table_obj_reference = $a_table_obj_reference;
 
  261                 if (!isset($a_column_name))
 
  263                         $this->ilErr->raiseError(get_class($this).
"::setReferenceTablePK(): No column name given!",$this->ilErr->WARNING);
 
  266                 $this->ref_pk = $a_column_name;
 
  278                 if (!isset($a_column_name))
 
  280                         $this->ilErr->raiseError(get_class($this).
"::setObjectTablePK(): No column name given!",$this->ilErr->WARNING);
 
  283                 $this->obj_pk = $a_column_name;
 
  295                 if (!isset($a_column_name))
 
  297                         $this->ilErr->raiseError(get_class($this).
"::setTreeTablePK(): No column name given!",$this->ilErr->WARNING);
 
  300                 $this->tree_pk = $a_column_name;
 
  311                 if ($this->table_obj_reference)
 
  314                         return "JOIN ".$this->table_obj_reference.
" ON ".$this->table_tree.
".child=".$this->table_obj_reference.
".".$this->ref_pk.
" ".
 
  315                                    "JOIN ".$this->table_obj_data.
" ON ".$this->table_obj_reference.
".".$this->obj_pk.
"=".$this->table_obj_data.
".".$this->obj_pk.
" ";
 
  320                         return "JOIN ".$this->table_obj_data.
" ON ".$this->table_tree.
".child=".$this->table_obj_data.
".".$this->obj_pk.
" ";
 
  332         function getChilds($a_node_id, $a_order = 
"", $a_direction = 
"ASC")
 
  336                 if (!isset($a_node_id))
 
  338                         $message = get_class($this).
"::getChilds(): No node_id given!";
 
  339                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
  352                 if (!empty($a_order))
 
  354                         $order_clause = 
"ORDER BY ".$a_order.
" ".$a_direction;
 
  358                         $order_clause = 
"ORDER BY ".$this->table_tree.
".lft";
 
  362                 $query = sprintf(
'SELECT * FROM '.$this->table_tree.
' '.
 
  364                                 "WHERE parent = %s " .
 
  365                                 "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
 
  367                                 $ilDB->quote($a_node_id,
'integer'),
 
  368                                 $ilDB->quote($this->tree_id,
'integer'));
 
  372                 if(!$count = $res->numRows())
 
  379                 while($r = $ilDB->fetchAssoc($res))
 
  382                         $obj_ids[] = $r[
"obj_id"];
 
  387                         is_object($ilUser) && $this->lang_code == $ilUser->getLanguage() && !$this->oc_preloaded[$a_node_id])
 
  390                         $ilObjDataCache->preloadObjectCache($obj_ids, $this->lang_code);
 
  392                         $this->oc_preloaded[$a_node_id] = 
true;
 
  395                 foreach ($rows as 
$row)
 
  402                                 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$row['child'].' = true'); 
  403                                 $this->in_tree_cache[$row[
'child']] = $row[
'tree'] == 1;
 
  406                 $childs[$count - 1][
"last"] = 
true;
 
  421                 $childs = $this->
getChilds($a_node,$a_order,$a_direction);
 
  423                 foreach($childs as $child)
 
  425                         if(!in_array($child[
"type"],$a_filter))
 
  427                                 $filtered[] = $child;
 
  430                 return $filtered ? $filtered : array();
 
  445                 if (!isset($a_node_id) or !isset($a_type))
 
  447                         $message = get_class($this).
"::getChildsByType(): Missing parameter! node_id:".$a_node_id.
" type:".$a_type;
 
  448                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
  451         if ($a_type==
'rolf' && $this->table_obj_reference) {
 
  455             $ilDB->setLimit(1,0);
 
  456             $query = sprintf(
"SELECT * FROM ".$this->table_tree.
" ".
 
  458                 "WHERE parent = %s ".
 
  459                 "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
 
  460                 "AND ".$this->table_obj_data.
".type = %s ",
 
  461                 $ilDB->quote($a_node_id,
'integer'),
 
  462                 $ilDB->quote($this->tree_id,
'integer'),
 
  463                 $ilDB->quote($a_type,
'text'));
 
  465             $query = sprintf(
"SELECT * FROM ".$this->table_tree.
" ".
 
  467                 "WHERE parent = %s ".
 
  468                 "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
 
  469                 "AND ".$this->table_obj_data.
".type = %s ".
 
  470                 "ORDER BY ".$this->table_tree.
".lft",
 
  471                 $ilDB->quote($a_node_id,
'integer'),
 
  472                 $ilDB->quote($this->tree_id,
'integer'),
 
  473                 $ilDB->quote($a_type,
'text'));
 
  479                 while(
$row = $ilDB->fetchAssoc(
$res))
 
  484                 return $childs ? $childs : array();
 
  499                 if (!isset($a_node_id) or !$a_types)
 
  501                         $message = get_class($this).
"::getChildsByType(): Missing parameter! node_id:".$a_node_id.
" type:".$a_types;
 
  502                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
  508                         $filter = 
'AND '.$this->table_obj_data.
'.type IN('.implode(
',',
ilUtil::quoteArray($a_types)).
') ';
 
  511                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
  513                         'WHERE parent = '.$ilDB->quote($a_node_id,
'integer').
' '.
 
  514                         'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = '.$ilDB->quote($this->tree_id,
'integer').
' '.
 
  516                         'ORDER BY '.$this->table_tree.
'.lft';
 
  519                 while(
$row = $ilDB->fetchAssoc(
$res))
 
  524                 return $childs ? $childs : array();
 
  542                         if($a_node_id <= 1 or $a_parent_id <= 0)
 
  544                                 $message = sprintf(
'%s::insertNode(): Invalid parameters! $a_node_id: %s $a_parent_id: %s',
 
  548                                 $this->log->write($message,$this->log->FATAL);
 
  549                                 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
  554                 if (!isset($a_node_id) or !isset($a_parent_id))
 
  556                         $this->ilErr->raiseError(get_class($this).
"::insertNode(): Missing parameter! ".
 
  557                                 "node_id: ".$a_node_id.
" parent_id: ".$a_parent_id,$this->ilErr->WARNING);
 
  561                         $this->ilErr->raiseError(get_class($this).
"::insertNode(): Node ".$a_node_id.
" already in tree ".
 
  562                                                                          $this->table_tree.
"!",$this->ilErr->WARNING);
 
  572                                         #ilDB::_lockTables(array('tree' => 'WRITE')); 
  579                                 $query = sprintf(
'SELECT * FROM '.$this->table_tree.
' '.
 
  581                                         'AND '.$this->tree_pk.
' = %s ',
 
  582                                         $ilDB->quote($a_parent_id,
'integer'),
 
  583                                         $ilDB->quote($this->tree_id,
'integer'));
 
  586                                 $r = $ilDB->fetchObject($res);
 
  588                                 if ($r->parent == NULL)
 
  592                                                 $ilDB->unlockTables();
 
  594                                         $this->ilErr->raiseError(get_class($this).
"::insertNode(): Parent with ID ".$a_parent_id.
" not found in ".
 
  595                                                                                          $this->table_tree.
"!",$this->ilErr->WARNING);
 
  603                                 $query = sprintf(
'UPDATE '.$this->table_tree.
' SET '.
 
  604                                         'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, '.
 
  605                                         'rgt = CASE WHEN rgt > %s THEN rgt + 2 ELSE rgt END '.
 
  606                                         'WHERE '.$this->tree_pk.
' = %s ',
 
  607                                         $ilDB->quote($left,
'integer'),
 
  608                                         $ilDB->quote($left,
'integer'),
 
  609                                         $ilDB->quote($this->tree_id,
'integer'));
 
  610                                 $res = $ilDB->manipulate(
$query);
 
  619                                                 #ilDB::_lockTables(array('tree' => 'WRITE')); 
  627                                         $query = sprintf(
'SELECT rgt,lft,parent FROM '.$this->table_tree.
' '.
 
  629                                                 'AND '.$this->tree_pk.
' =  %s',
 
  630                                                 $ilDB->quote($a_parent_id,
'integer'),
 
  631                                                 $ilDB->quote($this->tree_id,
'integer'));
 
  632                                         $res = $ilDB->query(
$query);
 
  633                                         $r = $ilDB->fetchAssoc($res);
 
  635                                         if ($r[
'parent'] == null)
 
  639                                                         $ilDB->unlockTables();
 
  641                                                 $this->ilErr->raiseError(get_class($this).
"::insertNode(): Parent with ID ".
 
  642                                                                                                 $a_parent_id.
" not found in ".$this->table_tree.
"!",$this->ilErr->WARNING);
 
  644                                         $parentRgt = $r[
'rgt'];
 
  645                                         $parentLft = $r[
'lft'];
 
  648                                         $availableSpace = $parentRgt - $parentLft;
 
  649                                         if ($availableSpace < 2)
 
  660                                                 $query = sprintf(
'SELECT MAX(rgt) max_rgt FROM '.$this->table_tree.
' '.
 
  661                                                         'WHERE parent = %s '.
 
  662                                                         'AND '.$this->tree_pk.
' = %s',
 
  663                                                         $ilDB->quote($a_parent_id,
'integer'),
 
  664                                                         $ilDB->quote($this->tree_id,
'integer'));
 
  665                                                 $res = $ilDB->query(
$query);
 
  666                                                 $r = $ilDB->fetchAssoc($res);
 
  668                                                 if (isset($r[
'max_rgt']))
 
  672                                                         $availableSpace = $parentRgt - $r[
'max_rgt'];
 
  673                                                         $lft = $r[
'max_rgt'] + 1;
 
  680                                                         $lft = $parentLft + 1;
 
  687                                         if ($availableSpace < 2)
 
  690                                                 $query = sprintf(
'UPDATE '.$this->table_tree.
' SET '.
 
  691                                                         'lft = CASE WHEN lft  > %s THEN lft + %s ELSE lft END, '.
 
  692                                                         'rgt = CASE WHEN rgt >= %s THEN rgt + %s ELSE rgt END '.
 
  693                                                         'WHERE '.$this->tree_pk.
' = %s ',
 
  694                                                         $ilDB->quote($parentRgt,
'integer'),
 
  695                                                         $ilDB->quote((2 + $this->gap * 2),
'integer'),
 
  696                                                         $ilDB->quote($parentRgt,
'integer'),
 
  697                                                         $ilDB->quote((2 + $this->gap * 2),
'integer'),
 
  698                                                         $ilDB->quote($this->tree_id,
'integer'));
 
  699                                                 $res = $ilDB->manipulate(
$query);
 
  711                                                 #ilDB::_lockTables(array('tree' => 'WRITE')); 
  719                                         $query = sprintf(
'SELECT * FROM '.$this->table_tree.
' '.
 
  721                                                 'AND '.$this->tree_pk.
' = %s ',
 
  722                                                 $ilDB->quote($a_parent_id,
'integer'),
 
  723                                                 $ilDB->quote($this->tree_id,
'integer'));
 
  724                                         $res = $ilDB->query(
$query);
 
  725                                         $r = $ilDB->fetchObject($res);
 
  727                                         if ($r->parent == null)
 
  731                                                         $ilDB->unlockTables();
 
  733                                                 $this->ilErr->raiseError(get_class($this).
"::insertNode(): Parent with ID ".
 
  734                                                                                                  $a_parent_id.
" not found in ".$this->table_tree.
"!",$this->ilErr->WARNING);
 
  742                                         $query = sprintf(
'UPDATE '.$this->table_tree.
' SET '.
 
  743                                                 'lft = CASE WHEN lft >  %s THEN lft + 2 ELSE lft END, '.
 
  744                                                 'rgt = CASE WHEN rgt >= %s THEN rgt + 2 ELSE rgt END '.
 
  745                                                 'WHERE '.$this->tree_pk.
' = %s',
 
  746                                                 $ilDB->quote($right,
'integer'),
 
  747                                                 $ilDB->quote($right,
'integer'),
 
  748                                                 $ilDB->quote($this->tree_id,
'integer'));
 
  749                                         $res = $ilDB->manipulate(
$query);
 
  759                                         #ilDB::_lockTables(array('tree' => 'WRITE')); 
  767                                 $query = sprintf(
'SELECT * FROM '.$this->table_tree.
' '.
 
  769                                         'AND '.$this->tree_pk.
' = %s ',
 
  770                                         $ilDB->quote($a_pos,
'integer'),
 
  771                                         $ilDB->quote($this->tree_id,
'integer'));
 
  772                                 $res = $ilDB->query(
$query);
 
  773                                 $r = $ilDB->fetchObject($res);
 
  776                                 if ($r->parent != $a_parent_id)
 
  780                                                 $ilDB->unlockTables();
 
  782                                         $this->ilErr->raiseError(get_class($this).
"::insertNode(): Parents mismatch! ".
 
  783                                                 "new node parent: ".$a_parent_id.
" sibling parent: ".$r->parent,$this->ilErr->WARNING);
 
  791                                 $query = sprintf(
'UPDATE '.$this->table_tree.
' SET '.
 
  792                                         'lft = CASE WHEN lft >  %s THEN lft + 2 ELSE lft END, '.
 
  793                                         'rgt = CASE WHEN rgt >  %s THEN rgt + 2 ELSE rgt END '.
 
  794                                         'WHERE '.$this->tree_pk.
' = %s',
 
  795                                         $ilDB->quote($right,
'integer'),
 
  796                                         $ilDB->quote($right,
'integer'),
 
  797                                         $ilDB->quote($this->tree_id,
'integer'));
 
  798                                 $res = $ilDB->manipulate(
$query);
 
  804                 $depth = $this->
getDepth($a_parent_id) + 1;
 
  808                 $query = sprintf(
'INSERT INTO '.$this->table_tree.
' ('.$this->tree_pk.
',child,parent,lft,rgt,depth) '.
 
  809                         'VALUES (%s,%s,%s,%s,%s,%s)',
 
  810                         $ilDB->quote($this->tree_id,
'integer'),
 
  811                         $ilDB->quote($a_node_id,
'integer'),
 
  812                         $ilDB->quote($a_parent_id,
'integer'),
 
  813                         $ilDB->quote($lft,
'integer'),
 
  814                         $ilDB->quote($rgt,
'integer'),
 
  815                         $ilDB->quote($depth,
'integer'));
 
  821                         #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true'); 
  822                         $this->in_tree_cache[$a_node_id] = 
true;
 
  823                         $ilDB->unlockTables();
 
  827                 if ($a_reset_deletion_date)
 
  853                         if($depth and $subnode[
'depth'] > $depth)
 
  857                         if(!$first and in_array($subnode[
'type'],$a_filter))
 
  859                                 $depth = $subnode[
'depth'];
 
  865                         $filtered[] = $subnode; 
 
  867                 return $filtered ? $filtered : array();
 
  879                 $query = 
'SELECT s.child FROM '.$this->table_tree.
' s, '.$this->table_tree.
' t '. 
 
  880                         'WHERE t.child = %s '.
 
  881                         'AND s.lft > t.lft '.
 
  882                         'AND s.rgt < t.rgt '.
 
  883                         'AND s.'.$this->tree_pk.
' = %s';
 
  885                 $res = $ilDB->queryF(
 
  887                         array(
'integer',
'integer'),
 
  888                         array($a_ref_id,$this->tree_id)
 
  892                         $childs[] = 
$row->child;
 
  894                 return $childs ? $childs : array();
 
  906         function getSubTree($a_node,$a_with_data = 
true, $a_type = 
"")
 
  910                 if (!is_array($a_node))
 
  912                         $this->ilErr->raiseError(get_class($this).
"::getSubTree(): Wrong datatype for node_data! ",$this->ilErr->WARNING);
 
  915                 if($a_node[
'lft'] < 1 or $a_node[
'rgt'] < 2)
 
  917                         $message = sprintf(
'%s::getSubTree(): Invalid node given! $a_node["lft"]: %s $a_node["rgt"]: %s',
 
  922                         $this->log->write($message,$this->log->FATAL);
 
  924                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
  928                 $fields = array(
'integer',
'integer',
'integer');
 
  929                 $data = array($a_node[
'lft'],$a_node[
'rgt'],$this->tree_id);
 
  936                         $type_str = 
"AND ".$this->table_obj_data.
".type= %s ";
 
  939                 $query = 
"SELECT * FROM ".$this->table_tree.
" ".
 
  941                         "WHERE ".$this->table_tree.
".lft BETWEEN %s AND %s ".
 
  942                         "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
 
  944                         "ORDER BY ".$this->table_tree.
".lft";
 
  946                 while(
$row = $ilDB->fetchAssoc(
$res))
 
  954                                 $subtree[] = 
$row[
'child'];
 
  958                                 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true'); 
  959                                 $this->in_tree_cache[
$row[
'child']] = 
true;
 
  963                 return $subtree ? $subtree : array();
 
  976                 $a_filter = $a_filter ? $a_filter : array();
 
  978                 foreach($this->getSubtree($this->
getNodeData($a_node)) as $node)
 
  980                         if(in_array($node[
"type"],$a_filter))
 
  984                         $types[
"$node[type]"] = $node[
"type"];
 
  986                 return $types ? $types : array();
 
  998                 if (!is_array($a_node))
 
 1000                         $this->ilErr->raiseError(get_class($this).
"::deleteTree(): Wrong datatype for node_data! ",$this->ilErr->WARNING);
 
 1002                 if($this->
__isMainTree() and $a_node[$this->tree_pk] === 1)
 
 1004                         if($a_node[
'lft'] <= 1 or $a_node[
'rgt'] <= 2)
 
 1006                                 $message = sprintf(
'%s::deleteTree(): Invalid parameters given: $a_node["lft"]: %s, $a_node["rgt"] %s',
 
 1011                                 $this->log->write($message,$this->log->FATAL);
 
 1012                                 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 1016                                 $message = sprintf(
'%s::deleteTree(): Check delete failed: $a_node["lft"]: %s, $a_node["rgt"] %s',
 
 1020                                 $this->log->write($message,$this->log->FATAL);
 
 1021                                 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 1025                 $diff = $a_node[
"rgt"] - $a_node[
"lft"] + 1;
 
 1032                         #ilDB::_lockTables(array('tree' => 'WRITE')); 
 1039                 $query = sprintf(
'SELECT * FROM '.$this->table_tree.
' '.
 
 1040                         'WHERE child = %s '.
 
 1041                         'AND '.$this->tree_pk.
' = %s ',
 
 1042                         $ilDB->quote($a_node[
'child'],
'integer'),
 
 1043                         $ilDB->quote($a_node[$this->tree_pk],
'integer'));
 
 1045                 while(
$row = $ilDB->fetchObject($res))
 
 1047                         $a_node[
'lft'] = 
$row->lft;
 
 1048                         $a_node[
'rgt'] = 
$row->rgt;
 
 1049                         $diff = $a_node[
"rgt"] - $a_node[
"lft"] + 1;
 
 1053                 $query = sprintf(
'DELETE FROM '.$this->table_tree.
' '.
 
 1054                         'WHERE lft BETWEEN %s AND %s '.
 
 1055                         'AND rgt BETWEEN %s AND %s '.
 
 1056                         'AND '.$this->tree_pk.
' = %s',
 
 1057                         $ilDB->quote($a_node[
'lft'],
'integer'),
 
 1058                         $ilDB->quote($a_node[
'rgt'],
'integer'),
 
 1059                         $ilDB->quote($a_node[
'lft'],
'integer'),
 
 1060                         $ilDB->quote($a_node[
'rgt'],
'integer'),
 
 1061                         $ilDB->quote($a_node[$this->tree_pk],
'integer'));
 
 1062                 $res = $ilDB->manipulate(
$query);
 
 1067                 if ($a_node[$this->tree_pk] >= 0 && $a_node[
'rgt'] - $a_node[
'lft'] >= $this->gap * 2)
 
 1071                         $query = sprintf(
'UPDATE '.$this->table_tree.
' SET '.
 
 1072                                 'lft = CASE WHEN lft > %s THEN lft - %s ELSE lft END, '.
 
 1073                                 'rgt = CASE WHEN rgt > %s THEN rgt - %s ELSE rgt END '.
 
 1074                                 'WHERE '.$this->tree_pk.
' = %s ',
 
 1075                                 $ilDB->quote($a_node[
'lft'],
'integer'),
 
 1076                                 $ilDB->quote($diff,
'integer'),
 
 1077                                 $ilDB->quote($a_node[
'lft'],
'integer'),
 
 1078                                 $ilDB->quote($diff,
'integer'),
 
 1079                                 $ilDB->quote($a_node[$this->tree_pk],
'integer'));
 
 1081                         $res = $ilDB->manipulate(
$query);
 
 1090                         #$GLOBALS['ilLog']->write(__METHOD__.': Resetting in tree cache '); 
 1091                         $ilDB->unlockTables();
 
 1092                         $this->in_tree_cache = array();
 
 1109                 $pathIds =& $this->
getPathId($a_endnode_id, $a_startnode_id);
 
 1115                 if (count($pathIds) == 0)
 
 1120                 $inClause = 
'child IN (';
 
 1121                 for ($i=0; $i < count($pathIds); $i++)
 
 1123                         if ($i > 0) $inClause .= 
',';
 
 1124                         $inClause .= $ilDB->quote($pathIds[$i],
'integer');
 
 1129                         'FROM '.$this->table_tree.
' '.
 
 1131                         'WHERE '.$inClause.
' '.
 
 1132             'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = '.$this->
ilDB->
quote($this->tree_id,
'integer').
' '.
 
 1134                 $r = $ilDB->query($q);
 
 1136                 $pathFull = array();
 
 1144                                 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$row['child']); 
 1145                                 $this->in_tree_cache[
$row[
'child']] = $row[
'tree'] == 1;
 
 1168                 if (!isset($a_endnode_id))
 
 1170                         $this->ilErr->raiseError(get_class($this).
"::getPathId(): No endnode_id given! ",$this->ilErr->WARNING);
 
 1173                 $fields = array(
'integer',
'integer',
'integer');
 
 1174                 $data = array($a_endnode_id,$this->tree_id,$this->tree_id);
 
 1176                 $query = 
"SELECT T2.child ".
 
 1177                         "FROM ".$this->table_tree.
" T1, ".$this->table_tree.
" T2 ".
 
 1178                         "WHERE T1.child = %s ".
 
 1179                         "AND T1.lft BETWEEN T2.lft AND T2.rgt ".
 
 1180                         "AND T1.".$this->tree_pk.
" = %s ".
 
 1181                         "AND T2.".$this->tree_pk.
" = %s ".
 
 1182                         "ORDER BY T2.depth";
 
 1185                 $takeId = $a_startnode_id == 0;
 
 1186                 while(
$row = $ilDB->fetchAssoc(
$res))
 
 1188                         if ($takeId || 
$row[
'child'] == $a_startnode_id)
 
 1191                                 $pathIds[] = 
$row[
'child'];
 
 1194                 return $pathIds ? $pathIds : array();
 
 1212                 $takeId = $a_startnode_id == 0;
 
 1214                 if (!isset($a_endnode_id))
 
 1216                         $this->ilErr->raiseError(get_class($this).
"::getPathId(): No endnode_id given! ",$this->ilErr->WARNING);
 
 1221                 if ($this->
__isMainTree() && isset($this->depth_cache[$a_endnode_id])
 
 1222                         && isset($this->parent_cache[$a_endnode_id]))
 
 1224                         $nodeDepth = $this->depth_cache[$a_endnode_id];
 
 1225                         $parentId = $this->parent_cache[$a_endnode_id];
 
 1229                         $types = array(
'integer',
'integer');
 
 1230                         $data = array($a_endnode_id,$this->tree_id);
 
 1231                         $query = 
'SELECT t.depth, t.parent '.
 
 1232                                 'FROM '.$this->table_tree.
' t '.
 
 1233                                 'WHERE child = %s '.
 
 1234                                 'AND '.$this->tree_pk.
' = %s ';
 
 1237                         if(
$res->numRows() == 0)
 
 1243                         $nodeDepth = 
$row[
'depth'];
 
 1244                         $parentId = 
$row[
'parent'];
 
 1251                 if ($nodeDepth == 1)
 
 1253                                 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
 
 1254                                 if ($takeId) $pathIds[] = $a_endnode_id;
 
 1256                 else if ($nodeDepth == 2)
 
 1258                                 $takeId = $takeId || $parentId == $a_startnode_id;
 
 1259                                 if ($takeId) $pathIds[] = $parentId;
 
 1260                                 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
 
 1261                                 if ($takeId) $pathIds[] = $a_endnode_id;
 
 1263                 else if ($nodeDepth == 3)
 
 1265                                 $takeId = $takeId || $this->root_id == $a_startnode_id;
 
 1267                                 $takeId = $takeId || $parentId == $a_startnode_id;
 
 1268                                 if ($takeId) $pathIds[] = $parentId;
 
 1269                                 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
 
 1270                                 if ($takeId) $pathIds[] = $a_endnode_id;
 
 1272                 else if ($nodeDepth < 32)
 
 1283                         $qSelect = 
't1.child c0';
 
 1285                         for ($i = 1; $i < $nodeDepth - 2; $i++)
 
 1287                                 $qSelect .= 
', t'.$i.
'.parent c'.$i;
 
 1288                                 $qJoin .= 
' JOIN '.$this->table_tree.
' t'.$i.
' ON '.
 
 1289                                                         't'.$i.
'.child=t'.($i - 1).
'.parent AND '.
 
 1293                         $types = array(
'integer',
'integer');
 
 1294                         $data = array($this->tree_id,$parentId);
 
 1295                         $query = 
'SELECT '.$qSelect.
' '.
 
 1296                                 'FROM '.$this->table_tree.
' t0 '.$qJoin.
' '.
 
 1297                                 'WHERE t0.'.$this->tree_pk.
' = %s '.
 
 1298                                 'AND t0.child = %s ';
 
 1303                         if (
$res->numRows() == 0)
 
 1309                         $takeId = $takeId || $this->root_id == $a_startnode_id;                 
 
 1311                         for ($i = $nodeDepth - 4; $i >=0; $i--)
 
 1313                                 $takeId = $takeId || 
$row[
'c'.$i] == $a_startnode_id;
 
 1314                                 if ($takeId) $pathIds[] = 
$row[
'c'.$i];
 
 1316                         $takeId = $takeId || $parentId == $a_startnode_id;
 
 1317                         if ($takeId) $pathIds[] = $parentId;
 
 1318                         $takeId = $takeId || $a_endnode_id == $a_startnode_id;
 
 1319                         if ($takeId) $pathIds[] = $a_endnode_id;
 
 1345                 $res = $ilDB->query(
'SELECT t.depth, t.parent, t.child '.
 
 1346                         'FROM '.$this->table_tree.
' t '.
 
 1347                         'WHERE '.$ilDB->in(
"child", $a_node_ids, 
false, 
"integer").
 
 1348                         'AND '.$this->tree_pk.
' = '.$ilDB->quote($this->tree_id, 
"integer"));
 
 1349                 while (
$row = $ilDB->fetchAssoc(
$res))
 
 1351                         $this->depth_cache[
$row[
"child"]] = $row[
"depth"];
 
 1352                         $this->parent_cache[$row[
"child"]] = $row[
"parent"];
 
 1367                 if ($this->
isCacheUsed() && isset($this->path_id_cache[$a_endnode_id][$a_startnode_id]))
 
 1370                         return $this->path_id_cache[$a_endnode_id][$a_startnode_id];
 
 1378                         $this->path_id_cache[$a_endnode_id][$a_startnode_id] = $pathIds;
 
 1407                 if ($titlePath == null || count($titlePath) == 0)
 
 1409                         if ($a_startnode_id == 0)
 
 1420                 if ($a_startnode_id != null && $a_startnode_id != 0)
 
 1424                         $parent = $a_startnode_id;
 
 1429                         $nodePath = array();
 
 1437                 require_once(
'include/Unicode/UtfNormal.php');
 
 1438                 include_once 
'./Services/Utilities/classes/class.ilStr.php';
 
 1439                 $inClause = 
'd.title IN (';
 
 1440                 for ($i=0; $i < count($titlePath); $i++)
 
 1443                         if ($i > 0) $inClause .= 
',';
 
 1444                         $inClause .= $ilDB->quote($titlePath[$i],
'text');
 
 1449                 if ($this->table_obj_reference)
 
 1451                         $joinClause = 
'JOIN '.$this->table_obj_reference.
'  r ON t.child = r.'.$this->ref_pk.
' '.
 
 1452                                 'JOIN '.$this->table_obj_data.
' d ON r.'.$this->obj_pk.
' = d.'.
$this->obj_pk;
 
 1456                         $joinClause = 
'JOIN '.$this->table_obj_data.
'  d ON t.child = d.'.
$this->obj_pk;
 
 1463                 $q = 
'SELECT t.depth, t.parent, t.child, d.'.$this->obj_pk.
' obj_id, d.type, d.title '.
 
 1464                         'FROM '.$this->table_tree.
'  t '.
 
 1466                         'WHERE '.$inClause.
' '.
 
 1467                         'AND t.depth <= '.(count($titlePath)+count($nodePath)).
' '.
 
 1469                         'ORDER BY t.depth, t.child ASC';
 
 1470                 $r = $ilDB->query($q);
 
 1481                 for ($i = 0; $i < count($titlePath); $i++) {
 
 1482                         $pathElementFound = 
false; 
 
 1483                         foreach ($rows as 
$row) {
 
 1484                                 if ($row[
'parent'] == $parent && 
 
 1490                                         $parent = $row[
'child'];
 
 1491                                         $pathElementFound = 
true;
 
 1496                         if (! $pathElementFound)
 
 1528                 $pathIds = $this->
getPathId($a_endnode_id, $a_startnode_id);
 
 1531                 if (count($pathIds) == 0)
 
 1539                 for ($i = 0; $i < count($pathIds); $i++)
 
 1541                         $types[] = 
'integer';
 
 1542                         $data[] = $pathIds[$i];
 
 1545                 $query = 
'SELECT t.depth,t.parent,t.child,d.obj_id,d.type,d.title '.
 
 1546                         'FROM '.$this->table_tree.
' t '.
 
 1547                         'JOIN '.$this->table_obj_reference.
' r ON r.ref_id = t.child '.
 
 1548                         'JOIN '.$this->table_obj_data.
' d ON d.obj_id = r.obj_id '.
 
 1549                         'WHERE '.$ilDB->in(
't.child',
$data,
false,
'integer').
' '.
 
 1550                         'ORDER BY t.depth ';
 
 1554                 $titlePath = array();
 
 1555                 while (
$row = $ilDB->fetchAssoc(
$res))
 
 1557                         $titlePath[] = 
$row;
 
 1573                 $types = array(
'integer');
 
 1574                 $query = 
'SELECT lft,rgt FROM '.$this->table_tree.
' '.
 
 1575                         'WHERE '.$this->tree_pk.
' = %s ';
 
 1577                 $res = $ilDB->queryF(
$query,$types,array($this->tree_id));
 
 1578                 while (
$row = $ilDB->fetchObject(
$res))
 
 1584                 $all = array_merge($lft,$rgt);
 
 1585                 $uni = array_unique($all);
 
 1587                 if (count($all) != count($uni))
 
 1589                         $message = sprintf(
'%s::checkTree(): Tree is corrupted!',
 
 1592                         $this->log->write($message,$this->log->FATAL);
 
 1593                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 1606                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 1607                                 'WHERE '.$this->tree_pk.
' = %s '.
 
 1609                 $r1 = $ilDB->queryF(
$query,array(
'integer'),array($this->tree_id));
 
 1611                 while (
$row = $ilDB->fetchAssoc($r1))
 
 1614                         if ((
$row[
"child"] == 0) && $a_no_zero_child)
 
 1616                                 $this->ilErr->raiseError(get_class($this).
"::checkTreeChilds(): Tree contains child with ID 0!",$this->ilErr->WARNING);
 
 1619                         if ($this->table_obj_reference)
 
 1622                                 $query = 
'SELECT * FROM '.$this->table_obj_reference.
' WHERE '.$this->ref_pk.
' = %s ';
 
 1623                                 $r2 = $ilDB->queryF(
$query,array(
'integer'),array(
$row[
'child']));
 
 1626                                 if ($r2->numRows() == 0)
 
 1628                                         $this->ilErr->raiseError(get_class($this).
"::checkTree(): No Object-to-Reference entry found for ID ".
 
 1629                                                 $row[
"child"].
"!",$this->ilErr->WARNING);
 
 1631                                 if ($r2->numRows() > 1)
 
 1633                                         $this->ilErr->raiseError(get_class($this).
"::checkTree(): More Object-to-Reference entries found for ID ".
 
 1634                                                 $row[
"child"].
"!",$this->ilErr->WARNING);
 
 1638                                 $obj_ref = $ilDB->fetchAssoc($r2);
 
 1640                                 $query = 
'SELECT * FROM '.$this->table_obj_data.
' WHERE '.$this->obj_pk.
' = %s';
 
 1641                                 $r3 = $ilDB->queryF(
$query,array(
'integer'),array($obj_ref[$this->obj_pk]));
 
 1642                                 if ($r3->numRows() == 0)
 
 1644                                         $this->ilErr->raiseError(get_class($this).
"::checkTree(): No child found for ID ".
 
 1645                                                 $obj_ref[$this->obj_pk].
"!",$this->ilErr->WARNING);
 
 1647                                 if ($r3->numRows() > 1)
 
 1649                                         $this->ilErr->raiseError(get_class($this).
"::checkTree(): More childs found for ID ".
 
 1650                                                 $obj_ref[$this->obj_pk].
"!",$this->ilErr->WARNING);
 
 1657                                 $query = 
'SELECT * FROM '.$this->table_obj_data.
' WHERE '.$this->obj_pk.
' = %s';
 
 1658                                 $r2 = $ilDB->queryF(
$query,array(
'integer'),array(
$row[
'child']));
 
 1660                                 if ($r2->numRows() == 0)
 
 1662                                         $this->ilErr->raiseError(get_class($this).
"::checkTree(): No child found for ID ".
 
 1663                                                 $row[
"child"].
"!",$this->ilErr->WARNING);
 
 1665                                 if ($r2->numRows() > 1)
 
 1667                                         $this->ilErr->raiseError(get_class($this).
"::checkTree(): More childs found for ID ".
 
 1668                                                 $row[
"child"].
"!",$this->ilErr->WARNING);
 
 1685                 $query = 
'SELECT MAX(depth) depth FROM '.$this->table_tree;
 
 1689                 return $row[
'depth'];
 
 1704                         $query = 
'SELECT depth FROM '.$this->table_tree.
' '.
 
 1705                                 'WHERE child = %s '.
 
 1706                                 'AND '.$this->tree_pk.
' = %s ';
 
 1707                         $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array($a_node_id,$this->tree_id));
 
 1733                 if (!isset($a_node_id))
 
 1735                         $this->ilErr->raiseError(get_class($this).
"::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
 
 1741                                 $message = sprintf(
'%s::getNodeData(): No valid parameter given! $a_node_id: %s',
 
 1745                                 $this->log->write($message,$this->log->FATAL);
 
 1746                                 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 1751                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 1753                         'WHERE '.$this->table_tree.
'.child = %s '.
 
 1754                         'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 1755                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 1757                         $a_tree_pk === null ? $this->tree_id : $a_tree_pk));
 
 1778                 $data[
"desc"] = $a_row[
"description"];  
 
 1783                 if (is_object($objDefinition))
 
 1785                         $translation_type = $objDefinition->getTranslationType(
$data[
"type"]);
 
 1789                 if ($translation_type == 
"sys")
 
 1792                         if (
$data[
"type"] == 
"rolf" and 
$data[
"obj_id"] != ROLE_FOLDER_ID)
 
 1794                                 $data[
"description"] = $lng->txt(
"obj_".
$data[
"type"].
"_local_desc").$data[
"title"].$data[
"desc"];
 
 1795                                 $data[
"desc"] = $lng->txt(
"obj_".
$data[
"type"].
"_local_desc").$data[
"title"].$data[
"desc"];
 
 1796                                 $data[
"title"] = $lng->txt(
"obj_".
$data[
"type"].
"_local");
 
 1800                                 $data[
"title"] = $lng->txt(
"obj_".
$data[
"type"]);
 
 1801                                 $data[
"description"] = $lng->txt(
"obj_".
$data[
"type"].
"_desc");
 
 1802                                 $data[
"desc"] = $lng->txt(
"obj_".
$data[
"type"].
"_desc");
 
 1806                 elseif ($translation_type == 
"db")
 
 1811                                 array_key_exists(
$data[
"obj_id"].
'.'.$lang_code, $this->translation_cache)) {
 
 1813                                 $key = 
$data[
"obj_id"].
'.'.$lang_code;
 
 1814                                 $data[
"title"] = $this->translation_cache[$key][
'title'];
 
 1815                                 $data[
"description"] = $this->translation_cache[$key][
'description'];
 
 1816                                 $data[
"desc"] = $this->translation_cache[$key][
'desc'];
 
 1822                                 $query = 
'SELECT title,description FROM object_translation '.
 
 1823                                         'WHERE obj_id = %s '.
 
 1824                                         'AND lang_code = %s '.
 
 1825                                         'AND NOT lang_default = %s';
 
 1827                                 $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer'),array(
 
 1842                                 if ($this->
isCacheUsed() && count($this->translation_cache) < 1000)
 
 1844                                         $key = 
$data[
"obj_id"].
'.'.$lang_code;
 
 1845                                         $this->translation_cache[$key] = array();
 
 1846                                         $this->translation_cache[$key][
'title'] = 
$data[
"title"] ;
 
 1847                                         $this->translation_cache[$key][
'description'] = 
$data[
"description"];
 
 1848                                         $this->translation_cache[$key][
'desc'] = 
$data[
"desc"];
 
 1854                 if(
$data[
'type'] == 
'crsr' or 
$data[
'type'] == 
'catr')
 
 1856                         include_once(
'./Services/ContainerReference/classes/class.ilContainerReference.php');
 
 1870                 global $ilObjDataCache;
 
 1872                 if ($this->
isCacheUsed() && is_array($a_obj_ids) && is_object($ilObjDataCache))
 
 1874                         foreach ($a_obj_ids as $id)
 
 1876                                 $this->translation_cache[$id.
'.'][
'title'] = $ilObjDataCache->lookupTitle($id);
 
 1877                                 $this->translation_cache[$id.
'.'][
'description'] = $ilObjDataCache->lookupDescription($id);;
 
 1878                                 $this->translation_cache[$id.
'.'][
'desc'] =
 
 1879                                         $this->translation_cache[$id.
'.'][
'description'];
 
 1896                 if (!isset($a_node_id))
 
 1899                         #$this->ilErr->raiseError(get_class($this)."::getNodeData(): No node_id given! ",$this->ilErr->WARNING); 
 1903                 if ($this->
isCacheUsed() && isset($this->in_tree_cache[$a_node_id]))
 
 1905                         #$GLOBALS['ilLog']->write(__METHOD__.': Using in tree cache '.$a_node_id); 
 1907                         return $this->in_tree_cache[$a_node_id];
 
 1910                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 1911                         'WHERE '.$this->table_tree.
'.child = %s '.
 
 1912                         'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s';
 
 1914                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 1918                 if (
$res->numRows() > 0)
 
 1922                                 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true'); 
 1923                                 $this->in_tree_cache[$a_node_id] = 
true;
 
 1931                                 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = false'); 
 1932                                 $this->in_tree_cache[$a_node_id] = 
false;
 
 1949                 if (!isset($a_node_id))
 
 1952                         $this->ilErr->raiseError(get_class($this).
"::getParentNodeData(): No node_id given! ",$this->ilErr->WARNING);
 
 1955                 if ($this->table_obj_reference)
 
 1958                         $innerjoin = 
"JOIN ".$this->table_obj_reference.
" ON v.child=".$this->table_obj_reference.
".".$this->ref_pk.
" ".
 
 1959                                                 "JOIN ".$this->table_obj_data.
" ON ".$this->table_obj_reference.
".".$this->obj_pk.
"=".$this->table_obj_data.
".".$this->obj_pk.
" ";
 
 1964                         $innerjoin = 
"JOIN ".$this->table_obj_data.
" ON v.child=".$this->table_obj_data.
".".$this->obj_pk.
" ";
 
 1967                 $query = 
'SELECT * FROM '.$this->table_tree.
' s, '.$this->table_tree.
' v '.
 
 1969                         'WHERE s.child = %s '.
 
 1970                         'AND s.parent = v.child '.
 
 1971                         'AND s.lft > v.lft '.
 
 1972                         'AND s.rgt < v.rgt '.
 
 1973                         'AND s.'.$this->tree_pk.
' = %s '.
 
 1974                         'AND v.'.$this->tree_pk.
' = %s';
 
 1975                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
 
 1994                 if (!isset($a_startnode_id) or !isset($a_querynode_id))
 
 1999                 $query = 
'SELECT * FROM '.$this->table_tree.
' s, '.$this->table_tree.
' v '.
 
 2000                         'WHERE s.child = %s '.
 
 2001                         'AND v.child = %s '.
 
 2002                         'AND s.'.$this->tree_pk.
' = %s '.
 
 2003                         'AND v.'.$this->tree_pk.
' = %s '.
 
 2004                         'AND v.lft BETWEEN s.lft AND s.rgt '.
 
 2005                         'AND v.rgt BETWEEN s.lft AND s.rgt';
 
 2006                 $res = $ilDB->queryF(
 
 2008                         array(
'integer',
'integer',
'integer',
'integer'),
 
 2015                 return $res->numRows();
 
 2033                         $message = sprintf(
'%s::addTree(): Operation not allowed on main tree! $a_tree_if: %s $a_node_id: %s',
 
 2037                         $this->log->write($message,$this->log->FATAL);
 
 2038                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2041                 if (!isset($a_tree_id))
 
 2043                         $this->ilErr->raiseError(get_class($this).
"::addTree(): No tree_id given! ",$this->ilErr->WARNING);
 
 2046                 if ($a_node_id <= 0)
 
 2048                         $a_node_id = $a_tree_id;
 
 2051                 $query = 
'INSERT INTO '.$this->table_tree.
' ('.
 
 2052                         $this->tree_pk.
', child,parent,lft,rgt,depth) '.
 
 2054                         '(%s,%s,%s,%s,%s,%s)';
 
 2055                 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer',
'integer',
'integer',
'integer',
'integer'),array(
 
 2077                 if (!isset($a_type) or (!is_string($a_type)))
 
 2079                         $this->ilErr->raiseError(get_class($this).
"::getNodeDataByType(): Type not given or wrong datatype!",$this->ilErr->WARNING);
 
 2087                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2088                         'WHERE '.$this->tree_pk.
' = %s '.
 
 2090                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2094                 while (
$row = $ilDB->fetchObject(
$res))
 
 2100                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2102                         'WHERE '.$this->table_obj_data.
'.type = %s '.
 
 2103                         'AND '.$this->table_tree.
'.lft BETWEEN %s AND %s '.
 
 2104                         'AND '.$this->table_tree.
'.rgt BETWEEN %s AND %s '.
 
 2105                         'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2106                 $res = $ilDB->queryF(
$query,array(
'text',
'integer',
'integer',
'integer',
'integer',
'integer'),array(
 
 2114                 while(
$row = $ilDB->fetchAssoc(
$res))
 
 2136                         $message = sprintf(
'%s::removeTree(): Operation not allowed on main tree! $a_tree_if: %s',
 
 2139                         $this->log->write($message,$this->log->FATAL);
 
 2140                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2144                         $this->ilErr->raiseError(get_class($this).
"::removeTree(): No tree_id given! Action aborted",$this->ilErr->MESSAGE);
 
 2147                 $query = 
'DELETE FROM '.$this->table_tree.
 
 2148                         ' WHERE '.$this->tree_pk.
' = %s ';
 
 2149                 $res = $ilDB->manipulateF(
$query,array(
'integer'),array($a_tree_id));
 
 2166                         $message = sprintf(
'%s::saveSubTree(): No valid parameter given! $a_node_id: %s',
 
 2169                         $this->log->write($message,$this->log->FATAL);
 
 2170                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2181                         #ilDB::_lockTables(array('tree' => 'WRITE', 
 2182                         #       'object_reference' => 'WRITE')); 
 2187                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2188                         'WHERE '.$this->tree_pk.
' = %s '.
 
 2190                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2194                 while(
$row = $ilDB->fetchObject(
$res))
 
 2201                 $query = 
'SELECT child FROM '.$this->table_tree.
' '.
 
 2202                         'WHERE '.$this->tree_pk.
' = %s '.
 
 2203                         'AND lft BETWEEN %s AND %s ';
 
 2204                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
 
 2209                 $subnodes = array();
 
 2210                 while(
$row = $ilDB->fetchAssoc(
$res))
 
 2212                         $subnodes[] = 
$row[
'child'];
 
 2215                 if(!count($subnodes))
 
 2222                                 $ilDB->unlockTables();
 
 2229                 foreach($subnodes as $child)
 
 2240                 $query = 
'UPDATE '.$this->table_tree.
' '.
 
 2242                         'WHERE '.$this->tree_pk.
' = %s '.
 
 2243                         'AND lft BETWEEN %s AND %s ';
 
 2244                 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer',
'integer',
'integer'),array(
 
 2252                         $ilDB->unlockTables();
 
 2264                 return $this->
isSaved($a_node_id);
 
 2275                 if ($this->
isCacheUsed() && isset($this->is_saved_cache[$a_node_id]))
 
 2278                         return $this->is_saved_cache[$a_node_id];
 
 2281                 $query = 
'SELECT '.$this->tree_pk.
' FROM '.$this->table_tree.
' '.
 
 2282                         'WHERE child = %s ';
 
 2283                 $res = $ilDB->queryF(
$query,array(
'integer'),array($a_node_id));
 
 2286                 if (
$row[$this->tree_pk] < 0)
 
 2290                                 $this->is_saved_cache[$a_node_id] = 
true;
 
 2298                                 $this->is_saved_cache[$a_node_id] = 
false;
 
 2314                 if (!is_array($a_node_ids) || !$this->
isCacheUsed())
 
 2319                 $query = 
'SELECT '.$this->tree_pk.
', child FROM '.$this->table_tree.
' '.
 
 2320                         'WHERE '.$ilDB->in(
"child", $a_node_ids, 
false, 
"integer");
 
 2323                 while (
$row = $ilDB->fetchAssoc(
$res))
 
 2325                         if (
$row[$this->tree_pk] < 0)
 
 2329                                         $this->is_saved_cache[
$row[
"child"]] = 
true;
 
 2336                                         $this->is_saved_cache[
$row[
"child"]] = 
false;
 
 2353                 if (!isset($a_parent_id))
 
 2355                         $this->ilErr->raiseError(get_class($this).
"::getSavedNodeData(): No node_id given!",$this->ilErr->WARNING);
 
 2358                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2360                         'WHERE '.$this->table_tree.
'.'.$this->tree_pk.
' < %s '.
 
 2361                         'AND '.$this->table_tree.
'.parent = %s';
 
 2362                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2366                 while(
$row = $ilDB->fetchAssoc(
$res))
 
 2371                 return $saved ? $saved : array();
 
 2384                 if (!isset($a_node_id))
 
 2386                         $this->ilErr->raiseError(get_class($this).
"::getParentId(): No node_id given! ",$this->ilErr->WARNING);
 
 2389                 $query = 
'SELECT parent FROM '.$this->table_tree.
' '.
 
 2390                         'WHERE child = %s '.
 
 2391                         'AND '.$this->tree_pk.
' = %s ';
 
 2392                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2397                 return $row->parent;
 
 2410                 if (!isset($a_node_id))
 
 2412                         $this->ilErr->raiseError(get_class($this).
"::getLeftValued(): No node_id given! ",$this->ilErr->WARNING);
 
 2415                 $query = 
'SELECT lft FROM '.$this->table_tree.
' '.
 
 2416                         'WHERE child = %s '.
 
 2417                         'AND '.$this->tree_pk.
' = %s ';
 
 2418                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2435                 if (!isset($a_node))
 
 2437                         $this->ilErr->raiseError(get_class($this).
"::getChildSequenceNumber(): No node_id given! ",$this->ilErr->WARNING);
 
 2442                         $query = 
'SELECT count(*) cnt FROM '.$this->table_tree.
' '.
 
 2447                                 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2449                         $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer',
'integer'),array(
 
 2457                         $query = 
'SELECT count(*) cnt FROM '.$this->table_tree.
' '.
 
 2461                                 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2463                         $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
 
 2483                 $query = 
'SELECT child FROM '.$this->table_tree.
' '.
 
 2484                         'WHERE parent = %s '.
 
 2485                         'AND '.$this->tree_pk.
' = %s ';
 
 2486                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2490                 $this->root_id = 
$row->child;
 
 2505                 $this->root_id = $a_root_id;
 
 2525                 $this->tree_id = $a_tree_id;
 
 2539                 if (!isset($a_node_id))
 
 2541                         $this->ilErr->raiseError(get_class($this).
"::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
 
 2545                 $query = 
'SELECT lft FROM '.$this->table_tree.
' '.
 
 2546                         'WHERE '.$this->table_tree.
'.child = %s '.
 
 2547                         'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2548                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2552                 $curr_node = $ilDB->fetchAssoc(
$res);
 
 2556                         $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2559                                 'AND '.$this->table_obj_data.
'.type = %s '.
 
 2560                                 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
 
 2563                         $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer'),array(
 
 2570                         $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2573                                 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
 
 2576                         $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2581                 if (
$res->numRows() < 1)
 
 2603                 if (!isset($a_node_id))
 
 2605                         $this->ilErr->raiseError(get_class($this).
"::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
 
 2609                 $query = 
'SELECT lft FROM '.$this->table_tree.
' '.
 
 2610                         'WHERE '.$this->table_tree.
'.child = %s '.
 
 2611                         'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2612                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2616                 $curr_node = $ilDB->fetchAssoc(
$res);
 
 2620                         $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2623                                 'AND '.$this->table_obj_data.
'.type = %s '.
 
 2624                                 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
 
 2625                                 'ORDER BY lft DESC';
 
 2627                         $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer'),array(
 
 2634                         $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2637                                 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
 
 2638                                 'ORDER BY lft DESC';
 
 2640                         $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2645                 if (
$res->numRows() < 1)
 
 2683                                         2 => array(
'name' => $this->table_obj_reference, 
'type' => 
ilDB::LOCK_WRITE),
 
 2685                                         4 => array(
'name' => 
'object_data', 
'type' => 
ilDB::LOCK_WRITE, 
'alias' => 
'od'),
 
 2686                                         5 => array(
'name' => 
'container_reference', 
'type' => 
ilDB::LOCK_WRITE, 
'alias' => 
'cr')
 
 2692                         $ilDB->unlockTables();
 
 2712                 $query = 
'UPDATE '.$this->table_tree.
' SET lft = %s WHERE child = %s';
 
 2713                 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer'),array(
 
 2719                 foreach ($childs as $child)
 
 2721                         $i = $this->
__renumber($child[
"child"],$i+1);
 
 2726                 if (count($childs) > 0)
 
 2728                         $i += $this->gap * 2;
 
 2732                 $query = 
'UPDATE '.$this->table_tree.
' SET rgt = %s WHERE child = %s';
 
 2733                 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer'),array(
 
 2754                                 array_key_exists($a_ref_id.
'.'.$a_type, $this->parent_type_cache)) {
 
 2755                         return $this->parent_type_cache[$a_ref_id.
'.'.$a_type];
 
 2761             if ($this->
__isMainTree() && count($this->parent_type_cache) < 1000) {
 
 2762                 $this->parent_type_cache[$a_ref_id.
'.'.$a_type] = 
false;
 
 2769                 if($a_exclude_source_check)
 
 2774                 foreach(
$path as $node)
 
 2776                         if($node[
"type"] == $a_type)
 
 2779             if ($this->
__isMainTree() && count($this->parent_type_cache) < 1000) {
 
 2780                 $this->parent_type_cache[$a_ref_id.
'.'.$a_type] = $node[
"child"];
 
 2782                                 return $node[
"child"];
 
 2786                 if ($this->
__isMainTree() && count($this->parent_type_cache) < 1000) {
 
 2787                         $this->parent_type_cache[$a_ref_id.
'.'.$a_type] = 
false;
 
 2805                 if($a_db_table === 
'tree')
 
 2807                         if($a_tree == 1 and $a_child == ROOT_FOLDER_ID)
 
 2809                                 $message = sprintf(
'%s::_removeEntry(): Tried to delete root node! $a_tree: %s $a_child: %s',
 
 2813                                 $ilLog->write($message,$ilLog->FATAL);
 
 2814                                 $ilErr->raiseError($message,$ilErr->WARNING);
 
 2818                 $query = 
'DELETE FROM '.$a_db_table.
' '.
 
 2821                 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer'),array(
 
 2836                 return $this->table_tree === 
'tree';
 
 2852                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2855                         'AND '.$this->tree_pk.
' = %s ';
 
 2856                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
 
 2859                         $a_node[$this->tree_pk]));
 
 2861                 $counter = (int) $lft_childs = array();
 
 2862                 while(
$row = $ilDB->fetchObject(
$res))
 
 2864                         $lft_childs[
$row->child] = 
$row->parent;
 
 2869                 if($counter != count($lft_childs))
 
 2871                         $message = sprintf(
'%s::__checkTree(): Duplicate entries for "child" in maintree! $a_node_id: %s',
 
 2874                         $this->log->write($message,$this->log->FATAL);
 
 2875                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2879                 $parent_childs = array();
 
 2891                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2892                         'WHERE child = %s '.
 
 2894                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2899                 while(
$row = $ilDB->fetchObject(
$res))
 
 2901                         $parent_childs[$a_node_id] = 
$row->parent;
 
 2907                         $message = sprintf(
'%s::__getSubTreeByParentRelation(): Multiple entries in maintree! $a_node_id: %s',
 
 2910                         $this->log->write($message,$this->log->FATAL);
 
 2911                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2915                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2916                         'WHERE parent = %s ';
 
 2917                 $res = $ilDB->queryF(
$query,array(
'integer'),array($a_node_id));
 
 2919                 while(
$row = $ilDB->fetchObject(
$res))
 
 2931                 ksort($parent_childs);
 
 2933                 if(count($lft_childs) != count($parent_childs))
 
 2935                         $message = sprintf(
'%s::__validateSubtrees(): (COUNT) Tree is corrupted! Left/Right subtree does not comply .'.
 
 2936                                                            'with parent relation',
 
 2938                         $this->log->write($message,$this->log->FATAL);
 
 2939                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2942                 foreach($lft_childs as $key => $value)
 
 2944                         if($parent_childs[$key] != $value)
 
 2946                                 $message = sprintf(
'%s::__validateSubtrees(): (COMPARE) Tree is corrupted! Left/Right subtree does not comply '.
 
 2947                                                                    'with parent relation',
 
 2949                                 $this->log->write($message,$this->log->FATAL);
 
 2950                                 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2952                         if($key == ROOT_FOLDER_ID)
 
 2954                                 $message = sprintf(
'%s::__validateSubtrees(): (ROOT_FOLDER) Tree is corrupted! Tried to delete root folder',
 
 2956                                 $this->log->write($message,$this->log->FATAL);
 
 2957                                 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2978                         #ilDB::_lockTables(array('tree' => 'WRITE')); 
 2985                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2986                         'WHERE ( child = %s OR child = %s ) '.
 
 2988                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
 
 2994                 if(
$res->numRows() != 2)
 
 2998                                 $ilDB->unlockTables();
 
 3000                         $this->log->write(__METHOD__.
' Objects not found in tree!',$this->log->FATAL);
 
 3001                         $this->ilErr->raiseError(
'Error moving node',$this->ilErr->WARNING);
 
 3003                 while(
$row = $ilDB->fetchObject(
$res))
 
 3005                         if(
$row->child == $a_source_id)
 
 3007                                 $source_lft = 
$row->lft;
 
 3008                                 $source_rgt = 
$row->rgt;
 
 3009                                 $source_depth = 
$row->depth;
 
 3010                                 $source_parent = 
$row->parent;
 
 3014                                 $target_lft = 
$row->lft;
 
 3015                                 $target_rgt = 
$row->rgt;
 
 3016                                 $target_depth = 
$row->depth;
 
 3020                 #var_dump("<pre>",$source_lft,$source_rgt,$source_depth,$target_lft,$target_rgt,$target_depth,"<pre>"); 
 3022                 if($target_lft >= $source_lft and $target_rgt <= $source_rgt)
 
 3026                                 $ilDB->unlockTables();
 
 3028                         $this->log->write(__METHOD__.
' Target is child of source',$this->log->FATAL);
 
 3029                         $this->ilErr->raiseError(
'Error moving node',$this->ilErr->WARNING);
 
 3034                 $spread_diff = $source_rgt - $source_lft + 1;
 
 3035                 #var_dump("<pre>","SPREAD_DIFF: ",$spread_diff,"<pre>"); 
 3037                 $query = 
'UPDATE '.$this->table_tree.
' SET '.
 
 3038                         'lft = CASE WHEN lft >  %s THEN lft + %s ELSE lft END, '.
 
 3039                         'rgt = CASE WHEN rgt >= %s THEN rgt + %s ELSE rgt END '.
 
 3041                 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer',
'integer',
'integer',
'integer'),array(
 
 3050                 if($source_lft > $target_rgt)
 
 3052                         $where_offset = $spread_diff;
 
 3053                         $move_diff = $target_rgt - $source_lft - $spread_diff;
 
 3058                         $move_diff = $target_rgt - $source_lft;
 
 3060                 $depth_diff = $target_depth - $source_depth + 1;
 
 3063                 $query = 
'UPDATE '.$this->table_tree.
' SET '.
 
 3064                         'parent = CASE WHEN parent = %s THEN %s ELSE parent END, '.
 
 3067                         'depth = depth + %s '.
 
 3072                         array(
'integer',
'integer',
'integer',
'integer',
'integer',
'integer',
'integer',
'integer'),
 
 3079                         $source_lft + $where_offset,
 
 3080                         $source_rgt + $where_offset,
 
 3084                 $query = 
'UPDATE '.$this->table_tree.
' SET '.
 
 3085                         'lft = CASE WHEN lft >= %s THEN lft - %s ELSE lft END, '.
 
 3086                         'rgt = CASE WHEN rgt >= %s THEN rgt - %s ELSE rgt END '.
 
 3090                         array(
'integer',
'integer',
'integer',
'integer',
'integer'),
 
 3092                         $source_lft + $where_offset,
 
 3094                         $source_rgt +$where_offset,
 
 3100                         $ilDB->unlockTables();
 
 3116                 $query = 
"SELECT t2.lft lft, t2.rgt rgt, t2.child child, type ".
 
 3117                         "FROM ".$this->table_tree.
" t1 ".
 
 3118                         "JOIN ".$this->table_tree.
" t2 ON (t2.lft BETWEEN t1.lft AND t1.rgt) ".
 
 3119                         "JOIN ".$this->table_obj_reference.
" obr ON t2.child = obr.ref_id ".
 
 3120                         "JOIN ".$this->table_obj_data.
" obd ON obr.obj_id = obd.obj_id ".
 
 3121                         "WHERE t1.child = ".$ilDB->quote($a_endnode_id,
'integer').
" ".
 
 3122                         "AND t1.".$this->tree_pk.
" = ".$ilDB->quote($this->tree_id,
'integer').
" ".
 
 3123                         "AND t2.".$this->tree_pk.
" = ".$ilDB->quote($this->tree_id,
'integer').
" ".
 
 3129                         $nodes[
$row->child][
'lft']      = 
$row->lft;
 
 3130                         $nodes[
$row->child][
'rgt']      = 
$row->rgt;
 
 3131                         $nodes[
$row->child][
'child']= 
$row->child;
 
 3132                         $nodes[
$row->child][
'type']     = 
$row->type;
 
 3135                 return (array) $nodes;