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);
 
  932                                         echo $e->getTraceAsString();
 
  937                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
  941                 $fields = array(
'integer',
'integer',
'integer');
 
  942                 $data = array($a_node[
'lft'],$a_node[
'rgt'],$this->tree_id);
 
  945                 if (is_array($a_type))
 
  947                         $type_str = 
"AND ".$ilDB->in($this->table_obj_data.
".type", $a_type, 
false, 
"text");
 
  949                 else if(strlen($a_type))
 
  953                         $type_str = 
"AND ".$this->table_obj_data.
".type = ".
 
  954                                 $ilDB->quote($a_type, 
"text");
 
  957                 $query = 
"SELECT * FROM ".$this->table_tree.
" ".
 
  959                         "WHERE ".$this->table_tree.
".lft BETWEEN %s AND %s ".
 
  960                         "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
 
  962                         "ORDER BY ".$this->table_tree.
".lft";
 
  964                 while(
$row = $ilDB->fetchAssoc(
$res))
 
  972                                 $subtree[] = 
$row[
'child'];
 
  976                                 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true'); 
  977                                 $this->in_tree_cache[
$row[
'child']] = 
true;
 
  981                 return $subtree ? $subtree : array();
 
  994                 $a_filter = $a_filter ? $a_filter : array();
 
  996                 foreach($this->getSubtree($this->
getNodeData($a_node)) as $node)
 
  998                         if(in_array($node[
"type"],$a_filter))
 
 1002                         $types[
"$node[type]"] = $node[
"type"];
 
 1004                 return $types ? $types : array();
 
 1016                 $GLOBALS[
'ilLog']->write(__METHOD__.
': Delete tree with node '. $a_node);
 
 1018                 if (!is_array($a_node))
 
 1020                         $this->ilErr->raiseError(get_class($this).
"::deleteTree(): Wrong datatype for node_data! ",$this->ilErr->WARNING);
 
 1022                 if($this->
__isMainTree() and $a_node[$this->tree_pk] === 1)
 
 1024                         if($a_node[
'lft'] <= 1 or $a_node[
'rgt'] <= 2)
 
 1026                                 $message = sprintf(
'%s::deleteTree(): Invalid parameters given: $a_node["lft"]: %s, $a_node["rgt"] %s',
 
 1031                                 $this->log->write($message,$this->log->FATAL);
 
 1032                                 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 1036                                 $message = sprintf(
'%s::deleteTree(): Check delete failed: $a_node["lft"]: %s, $a_node["rgt"] %s',
 
 1040                                 $this->log->write($message,$this->log->FATAL);
 
 1041                                 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 1045                 $diff = $a_node[
"rgt"] - $a_node[
"lft"] + 1;
 
 1052                         #ilDB::_lockTables(array('tree' => 'WRITE')); 
 1059                 $query = sprintf(
'SELECT * FROM '.$this->table_tree.
' '.
 
 1060                         'WHERE child = %s '.
 
 1061                         'AND '.$this->tree_pk.
' = %s ',
 
 1062                         $ilDB->quote($a_node[
'child'],
'integer'),
 
 1063                         $ilDB->quote($a_node[$this->tree_pk],
'integer'));
 
 1065                 while(
$row = $ilDB->fetchObject($res))
 
 1067                         $a_node[
'lft'] = 
$row->lft;
 
 1068                         $a_node[
'rgt'] = 
$row->rgt;
 
 1069                         $diff = $a_node[
"rgt"] - $a_node[
"lft"] + 1;
 
 1073                 $query = sprintf(
'DELETE FROM '.$this->table_tree.
' '.
 
 1074                         'WHERE lft BETWEEN %s AND %s '.
 
 1075                         'AND rgt BETWEEN %s AND %s '.
 
 1076                         'AND '.$this->tree_pk.
' = %s',
 
 1077                         $ilDB->quote($a_node[
'lft'],
'integer'),
 
 1078                         $ilDB->quote($a_node[
'rgt'],
'integer'),
 
 1079                         $ilDB->quote($a_node[
'lft'],
'integer'),
 
 1080                         $ilDB->quote($a_node[
'rgt'],
'integer'),
 
 1081                         $ilDB->quote($a_node[$this->tree_pk],
'integer'));
 
 1082                 $res = $ilDB->manipulate(
$query);
 
 1087                 if ($a_node[$this->tree_pk] >= 0 && $a_node[
'rgt'] - $a_node[
'lft'] >= $this->gap * 2)
 
 1091                         $query = sprintf(
'UPDATE '.$this->table_tree.
' SET '.
 
 1092                                 'lft = CASE WHEN lft > %s THEN lft - %s ELSE lft END, '.
 
 1093                                 'rgt = CASE WHEN rgt > %s THEN rgt - %s ELSE rgt END '.
 
 1094                                 'WHERE '.$this->tree_pk.
' = %s ',
 
 1095                                 $ilDB->quote($a_node[
'lft'],
'integer'),
 
 1096                                 $ilDB->quote($diff,
'integer'),
 
 1097                                 $ilDB->quote($a_node[
'lft'],
'integer'),
 
 1098                                 $ilDB->quote($diff,
'integer'),
 
 1099                                 $ilDB->quote($a_node[$this->tree_pk],
'integer'));
 
 1101                         $res = $ilDB->manipulate(
$query);
 
 1110                         #$GLOBALS['ilLog']->write(__METHOD__.': Resetting in tree cache '); 
 1111                         $ilDB->unlockTables();
 
 1112                         $this->in_tree_cache = array();
 
 1129                 $pathIds =& $this->
getPathId($a_endnode_id, $a_startnode_id);
 
 1135                 if (count($pathIds) == 0)
 
 1140                 $inClause = 
'child IN (';
 
 1141                 for ($i=0; $i < count($pathIds); $i++)
 
 1143                         if ($i > 0) $inClause .= 
',';
 
 1144                         $inClause .= $ilDB->quote($pathIds[$i],
'integer');
 
 1149                         'FROM '.$this->table_tree.
' '.
 
 1151                         'WHERE '.$inClause.
' '.
 
 1152             'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = '.$this->
ilDB->
quote($this->tree_id,
'integer').
' '.
 
 1154                 $r = $ilDB->query($q);
 
 1156                 $pathFull = array();
 
 1164                                 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$row['child']); 
 1165                                 $this->in_tree_cache[
$row[
'child']] = $row[
'tree'] == 1;
 
 1188                 if (!isset($a_endnode_id))
 
 1190                         $this->ilErr->raiseError(get_class($this).
"::getPathId(): No endnode_id given! ",$this->ilErr->WARNING);
 
 1193                 $fields = array(
'integer',
'integer',
'integer');
 
 1194                 $data = array($a_endnode_id,$this->tree_id,$this->tree_id);
 
 1196                 $query = 
"SELECT T2.child ".
 
 1197                         "FROM ".$this->table_tree.
" T1, ".$this->table_tree.
" T2 ".
 
 1198                         "WHERE T1.child = %s ".
 
 1199                         "AND T1.lft BETWEEN T2.lft AND T2.rgt ".
 
 1200                         "AND T1.".$this->tree_pk.
" = %s ".
 
 1201                         "AND T2.".$this->tree_pk.
" = %s ".
 
 1202                         "ORDER BY T2.depth";
 
 1205                 $takeId = $a_startnode_id == 0;
 
 1206                 while(
$row = $ilDB->fetchAssoc(
$res))
 
 1208                         if ($takeId || 
$row[
'child'] == $a_startnode_id)
 
 1211                                 $pathIds[] = 
$row[
'child'];
 
 1214                 return $pathIds ? $pathIds : array();
 
 1232                 $takeId = $a_startnode_id == 0;
 
 1234                 if (!isset($a_endnode_id))
 
 1236                         $this->ilErr->raiseError(get_class($this).
"::getPathId(): No endnode_id given! ",$this->ilErr->WARNING);
 
 1241                 if ($this->
__isMainTree() && isset($this->depth_cache[$a_endnode_id])
 
 1242                         && isset($this->parent_cache[$a_endnode_id]))
 
 1244                         $nodeDepth = $this->depth_cache[$a_endnode_id];
 
 1245                         $parentId = $this->parent_cache[$a_endnode_id];
 
 1249                         $types = array(
'integer',
'integer');
 
 1250                         $data = array($a_endnode_id,$this->tree_id);
 
 1251                         $query = 
'SELECT t.depth, t.parent '.
 
 1252                                 'FROM '.$this->table_tree.
' t '.
 
 1253                                 'WHERE child = %s '.
 
 1254                                 'AND '.$this->tree_pk.
' = %s ';
 
 1257                         if(
$res->numRows() == 0)
 
 1263                         $nodeDepth = 
$row[
'depth'];
 
 1264                         $parentId = 
$row[
'parent'];
 
 1271                 if ($nodeDepth == 1)
 
 1273                                 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
 
 1274                                 if ($takeId) $pathIds[] = $a_endnode_id;
 
 1276                 else if ($nodeDepth == 2)
 
 1278                                 $takeId = $takeId || $parentId == $a_startnode_id;
 
 1279                                 if ($takeId) $pathIds[] = $parentId;
 
 1280                                 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
 
 1281                                 if ($takeId) $pathIds[] = $a_endnode_id;
 
 1283                 else if ($nodeDepth == 3)
 
 1285                                 $takeId = $takeId || $this->root_id == $a_startnode_id;
 
 1287                                 $takeId = $takeId || $parentId == $a_startnode_id;
 
 1288                                 if ($takeId) $pathIds[] = $parentId;
 
 1289                                 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
 
 1290                                 if ($takeId) $pathIds[] = $a_endnode_id;
 
 1292                 else if ($nodeDepth < 32)
 
 1303                         $qSelect = 
't1.child c0';
 
 1305                         for ($i = 1; $i < $nodeDepth - 2; $i++)
 
 1307                                 $qSelect .= 
', t'.$i.
'.parent c'.$i;
 
 1308                                 $qJoin .= 
' JOIN '.$this->table_tree.
' t'.$i.
' ON '.
 
 1309                                                         't'.$i.
'.child=t'.($i - 1).
'.parent AND '.
 
 1313                         $types = array(
'integer',
'integer');
 
 1314                         $data = array($this->tree_id,$parentId);
 
 1315                         $query = 
'SELECT '.$qSelect.
' '.
 
 1316                                 'FROM '.$this->table_tree.
' t0 '.$qJoin.
' '.
 
 1317                                 'WHERE t0.'.$this->tree_pk.
' = %s '.
 
 1318                                 'AND t0.child = %s ';
 
 1323                         if (
$res->numRows() == 0)
 
 1329                         $takeId = $takeId || $this->root_id == $a_startnode_id;                 
 
 1331                         for ($i = $nodeDepth - 4; $i >=0; $i--)
 
 1333                                 $takeId = $takeId || 
$row[
'c'.$i] == $a_startnode_id;
 
 1334                                 if ($takeId) $pathIds[] = 
$row[
'c'.$i];
 
 1336                         $takeId = $takeId || $parentId == $a_startnode_id;
 
 1337                         if ($takeId) $pathIds[] = $parentId;
 
 1338                         $takeId = $takeId || $a_endnode_id == $a_startnode_id;
 
 1339                         if ($takeId) $pathIds[] = $a_endnode_id;
 
 1365                 $res = $ilDB->query(
'SELECT t.depth, t.parent, t.child '.
 
 1366                         'FROM '.$this->table_tree.
' t '.
 
 1367                         'WHERE '.$ilDB->in(
"child", $a_node_ids, 
false, 
"integer").
 
 1368                         'AND '.$this->tree_pk.
' = '.$ilDB->quote($this->tree_id, 
"integer"));
 
 1369                 while (
$row = $ilDB->fetchAssoc(
$res))
 
 1371                         $this->depth_cache[
$row[
"child"]] = $row[
"depth"];
 
 1372                         $this->parent_cache[$row[
"child"]] = $row[
"parent"];
 
 1387                 if ($this->
isCacheUsed() && isset($this->path_id_cache[$a_endnode_id][$a_startnode_id]))
 
 1390                         return $this->path_id_cache[$a_endnode_id][$a_startnode_id];
 
 1398                         $this->path_id_cache[$a_endnode_id][$a_startnode_id] = $pathIds;
 
 1427                 if ($titlePath == null || count($titlePath) == 0)
 
 1429                         if ($a_startnode_id == 0)
 
 1440                 if ($a_startnode_id != null && $a_startnode_id != 0)
 
 1444                         $parent = $a_startnode_id;
 
 1449                         $nodePath = array();
 
 1457                 require_once(
'include/Unicode/UtfNormal.php');
 
 1458                 include_once 
'./Services/Utilities/classes/class.ilStr.php';
 
 1459                 $inClause = 
'd.title IN (';
 
 1460                 for ($i=0; $i < count($titlePath); $i++)
 
 1463                         if ($i > 0) $inClause .= 
',';
 
 1464                         $inClause .= $ilDB->quote($titlePath[$i],
'text');
 
 1469                 if ($this->table_obj_reference)
 
 1471                         $joinClause = 
'JOIN '.$this->table_obj_reference.
'  r ON t.child = r.'.$this->ref_pk.
' '.
 
 1472                                 'JOIN '.$this->table_obj_data.
' d ON r.'.$this->obj_pk.
' = d.'.
$this->obj_pk;
 
 1476                         $joinClause = 
'JOIN '.$this->table_obj_data.
'  d ON t.child = d.'.
$this->obj_pk;
 
 1483                 $q = 
'SELECT t.depth, t.parent, t.child, d.'.$this->obj_pk.
' obj_id, d.type, d.title '.
 
 1484                         'FROM '.$this->table_tree.
'  t '.
 
 1486                         'WHERE '.$inClause.
' '.
 
 1487                         'AND t.depth <= '.(count($titlePath)+count($nodePath)).
' '.
 
 1489                         'ORDER BY t.depth, t.child ASC';
 
 1490                 $r = $ilDB->query($q);
 
 1501                 for ($i = 0; $i < count($titlePath); $i++) {
 
 1502                         $pathElementFound = 
false; 
 
 1503                         foreach ($rows as 
$row) {
 
 1504                                 if ($row[
'parent'] == $parent && 
 
 1510                                         $parent = $row[
'child'];
 
 1511                                         $pathElementFound = 
true;
 
 1516                         if (! $pathElementFound)
 
 1548                 $pathIds = $this->
getPathId($a_endnode_id, $a_startnode_id);
 
 1551                 if (count($pathIds) == 0)
 
 1559                 for ($i = 0; $i < count($pathIds); $i++)
 
 1561                         $types[] = 
'integer';
 
 1562                         $data[] = $pathIds[$i];
 
 1565                 $query = 
'SELECT t.depth,t.parent,t.child,d.obj_id,d.type,d.title '.
 
 1566                         'FROM '.$this->table_tree.
' t '.
 
 1567                         'JOIN '.$this->table_obj_reference.
' r ON r.ref_id = t.child '.
 
 1568                         'JOIN '.$this->table_obj_data.
' d ON d.obj_id = r.obj_id '.
 
 1569                         'WHERE '.$ilDB->in(
't.child',
$data,
false,
'integer').
' '.
 
 1570                         'ORDER BY t.depth ';
 
 1574                 $titlePath = array();
 
 1575                 while (
$row = $ilDB->fetchAssoc(
$res))
 
 1577                         $titlePath[] = 
$row;
 
 1593                 $types = array(
'integer');
 
 1594                 $query = 
'SELECT lft,rgt FROM '.$this->table_tree.
' '.
 
 1595                         'WHERE '.$this->tree_pk.
' = %s ';
 
 1597                 $res = $ilDB->queryF(
$query,$types,array($this->tree_id));
 
 1598                 while (
$row = $ilDB->fetchObject(
$res))
 
 1604                 $all = array_merge($lft,$rgt);
 
 1605                 $uni = array_unique($all);
 
 1607                 if (count($all) != count($uni))
 
 1609                         $message = sprintf(
'%s::checkTree(): Tree is corrupted!',
 
 1612                         $this->log->write($message,$this->log->FATAL);
 
 1613                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 1626                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 1627                                 'WHERE '.$this->tree_pk.
' = %s '.
 
 1629                 $r1 = $ilDB->queryF(
$query,array(
'integer'),array($this->tree_id));
 
 1631                 while (
$row = $ilDB->fetchAssoc($r1))
 
 1634                         if ((
$row[
"child"] == 0) && $a_no_zero_child)
 
 1636                                 $this->ilErr->raiseError(get_class($this).
"::checkTreeChilds(): Tree contains child with ID 0!",$this->ilErr->WARNING);
 
 1639                         if ($this->table_obj_reference)
 
 1642                                 $query = 
'SELECT * FROM '.$this->table_obj_reference.
' WHERE '.$this->ref_pk.
' = %s ';
 
 1643                                 $r2 = $ilDB->queryF(
$query,array(
'integer'),array(
$row[
'child']));
 
 1646                                 if ($r2->numRows() == 0)
 
 1648                                         $this->ilErr->raiseError(get_class($this).
"::checkTree(): No Object-to-Reference entry found for ID ".
 
 1649                                                 $row[
"child"].
"!",$this->ilErr->WARNING);
 
 1651                                 if ($r2->numRows() > 1)
 
 1653                                         $this->ilErr->raiseError(get_class($this).
"::checkTree(): More Object-to-Reference entries found for ID ".
 
 1654                                                 $row[
"child"].
"!",$this->ilErr->WARNING);
 
 1658                                 $obj_ref = $ilDB->fetchAssoc($r2);
 
 1660                                 $query = 
'SELECT * FROM '.$this->table_obj_data.
' WHERE '.$this->obj_pk.
' = %s';
 
 1661                                 $r3 = $ilDB->queryF(
$query,array(
'integer'),array($obj_ref[$this->obj_pk]));
 
 1662                                 if ($r3->numRows() == 0)
 
 1664                                         $this->ilErr->raiseError(get_class($this).
"::checkTree(): No child found for ID ".
 
 1665                                                 $obj_ref[$this->obj_pk].
"!",$this->ilErr->WARNING);
 
 1667                                 if ($r3->numRows() > 1)
 
 1669                                         $this->ilErr->raiseError(get_class($this).
"::checkTree(): More childs found for ID ".
 
 1670                                                 $obj_ref[$this->obj_pk].
"!",$this->ilErr->WARNING);
 
 1677                                 $query = 
'SELECT * FROM '.$this->table_obj_data.
' WHERE '.$this->obj_pk.
' = %s';
 
 1678                                 $r2 = $ilDB->queryF(
$query,array(
'integer'),array(
$row[
'child']));
 
 1680                                 if ($r2->numRows() == 0)
 
 1682                                         $this->ilErr->raiseError(get_class($this).
"::checkTree(): No child found for ID ".
 
 1683                                                 $row[
"child"].
"!",$this->ilErr->WARNING);
 
 1685                                 if ($r2->numRows() > 1)
 
 1687                                         $this->ilErr->raiseError(get_class($this).
"::checkTree(): More childs found for ID ".
 
 1688                                                 $row[
"child"].
"!",$this->ilErr->WARNING);
 
 1705                 $query = 
'SELECT MAX(depth) depth FROM '.$this->table_tree;
 
 1709                 return $row[
'depth'];
 
 1724                         $query = 
'SELECT depth FROM '.$this->table_tree.
' '.
 
 1725                                 'WHERE child = %s '.
 
 1726                                 'AND '.$this->tree_pk.
' = %s ';
 
 1727                         $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array($a_node_id,$this->tree_id));
 
 1753                 if (!isset($a_node_id))
 
 1756                         $this->ilErr->raiseError(get_class($this).
"::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
 
 1762                                 $message = sprintf(
'%s::getNodeData(): No valid parameter given! $a_node_id: %s',
 
 1766                                 $this->log->write($message,$this->log->FATAL);
 
 1767                                 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 1772                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 1774                         'WHERE '.$this->table_tree.
'.child = %s '.
 
 1775                         'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 1776                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 1778                         $a_tree_pk === null ? $this->tree_id : $a_tree_pk));
 
 1799                 $data[
"desc"] = $a_row[
"description"];  
 
 1804                 if (is_object($objDefinition))
 
 1806                         $translation_type = $objDefinition->getTranslationType(
$data[
"type"]);
 
 1810                 if ($translation_type == 
"sys")
 
 1813                         if (
$data[
"type"] == 
"rolf" and 
$data[
"obj_id"] != ROLE_FOLDER_ID)
 
 1815                                 $data[
"description"] = $lng->txt(
"obj_".
$data[
"type"].
"_local_desc").$data[
"title"].$data[
"desc"];
 
 1816                                 $data[
"desc"] = $lng->txt(
"obj_".
$data[
"type"].
"_local_desc").$data[
"title"].$data[
"desc"];
 
 1817                                 $data[
"title"] = $lng->txt(
"obj_".
$data[
"type"].
"_local");
 
 1821                                 $data[
"title"] = $lng->txt(
"obj_".
$data[
"type"]);
 
 1822                                 $data[
"description"] = $lng->txt(
"obj_".
$data[
"type"].
"_desc");
 
 1823                                 $data[
"desc"] = $lng->txt(
"obj_".
$data[
"type"].
"_desc");
 
 1827                 elseif ($translation_type == 
"db")
 
 1832                                 array_key_exists(
$data[
"obj_id"].
'.'.$lang_code, $this->translation_cache)) {
 
 1834                                 $key = 
$data[
"obj_id"].
'.'.$lang_code;
 
 1835                                 $data[
"title"] = $this->translation_cache[$key][
'title'];
 
 1836                                 $data[
"description"] = $this->translation_cache[$key][
'description'];
 
 1837                                 $data[
"desc"] = $this->translation_cache[$key][
'desc'];
 
 1843                                 $query = 
'SELECT title,description FROM object_translation '.
 
 1844                                         'WHERE obj_id = %s '.
 
 1845                                         'AND lang_code = %s '.
 
 1846                                         'AND NOT lang_default = %s';
 
 1848                                 $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer'),array(
 
 1863                                 if ($this->
isCacheUsed() && count($this->translation_cache) < 1000)
 
 1865                                         $key = 
$data[
"obj_id"].
'.'.$lang_code;
 
 1866                                         $this->translation_cache[$key] = array();
 
 1867                                         $this->translation_cache[$key][
'title'] = 
$data[
"title"] ;
 
 1868                                         $this->translation_cache[$key][
'description'] = 
$data[
"description"];
 
 1869                                         $this->translation_cache[$key][
'desc'] = 
$data[
"desc"];
 
 1875                 if(
$data[
'type'] == 
'crsr' or 
$data[
'type'] == 
'catr')
 
 1877                         include_once(
'./Services/ContainerReference/classes/class.ilContainerReference.php');
 
 1891                 global $ilObjDataCache;
 
 1893                 if ($this->
isCacheUsed() && is_array($a_obj_ids) && is_object($ilObjDataCache))
 
 1895                         foreach ($a_obj_ids as $id)
 
 1897                                 $this->translation_cache[$id.
'.'][
'title'] = $ilObjDataCache->lookupTitle($id);
 
 1898                                 $this->translation_cache[$id.
'.'][
'description'] = $ilObjDataCache->lookupDescription($id);;
 
 1899                                 $this->translation_cache[$id.
'.'][
'desc'] =
 
 1900                                         $this->translation_cache[$id.
'.'][
'description'];
 
 1917                 if (!isset($a_node_id))
 
 1920                         #$this->ilErr->raiseError(get_class($this)."::getNodeData(): No node_id given! ",$this->ilErr->WARNING); 
 1924                 if ($this->
isCacheUsed() && isset($this->in_tree_cache[$a_node_id]))
 
 1926                         #$GLOBALS['ilLog']->write(__METHOD__.': Using in tree cache '.$a_node_id); 
 1928                         return $this->in_tree_cache[$a_node_id];
 
 1931                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 1932                         'WHERE '.$this->table_tree.
'.child = %s '.
 
 1933                         'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s';
 
 1935                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 1939                 if (
$res->numRows() > 0)
 
 1943                                 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true'); 
 1944                                 $this->in_tree_cache[$a_node_id] = 
true;
 
 1952                                 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = false'); 
 1953                                 $this->in_tree_cache[$a_node_id] = 
false;
 
 1970                 if (!isset($a_node_id))
 
 1973                         $this->ilErr->raiseError(get_class($this).
"::getParentNodeData(): No node_id given! ",$this->ilErr->WARNING);
 
 1976                 if ($this->table_obj_reference)
 
 1979                         $innerjoin = 
"JOIN ".$this->table_obj_reference.
" ON v.child=".$this->table_obj_reference.
".".$this->ref_pk.
" ".
 
 1980                                                 "JOIN ".$this->table_obj_data.
" ON ".$this->table_obj_reference.
".".$this->obj_pk.
"=".$this->table_obj_data.
".".$this->obj_pk.
" ";
 
 1985                         $innerjoin = 
"JOIN ".$this->table_obj_data.
" ON v.child=".$this->table_obj_data.
".".$this->obj_pk.
" ";
 
 1988                 $query = 
'SELECT * FROM '.$this->table_tree.
' s, '.$this->table_tree.
' v '.
 
 1990                         'WHERE s.child = %s '.
 
 1991                         'AND s.parent = v.child '.
 
 1992                         'AND s.lft > v.lft '.
 
 1993                         'AND s.rgt < v.rgt '.
 
 1994                         'AND s.'.$this->tree_pk.
' = %s '.
 
 1995                         'AND v.'.$this->tree_pk.
' = %s';
 
 1996                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
 
 2015                 if (!isset($a_startnode_id) or !isset($a_querynode_id))
 
 2020                 $query = 
'SELECT * FROM '.$this->table_tree.
' s, '.$this->table_tree.
' v '.
 
 2021                         'WHERE s.child = %s '.
 
 2022                         'AND v.child = %s '.
 
 2023                         'AND s.'.$this->tree_pk.
' = %s '.
 
 2024                         'AND v.'.$this->tree_pk.
' = %s '.
 
 2025                         'AND v.lft BETWEEN s.lft AND s.rgt '.
 
 2026                         'AND v.rgt BETWEEN s.lft AND s.rgt';
 
 2027                 $res = $ilDB->queryF(
 
 2029                         array(
'integer',
'integer',
'integer',
'integer'),
 
 2036                 return $res->numRows();
 
 2054                         $message = sprintf(
'%s::addTree(): Operation not allowed on main tree! $a_tree_if: %s $a_node_id: %s',
 
 2058                         $this->log->write($message,$this->log->FATAL);
 
 2059                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2062                 if (!isset($a_tree_id))
 
 2064                         $this->ilErr->raiseError(get_class($this).
"::addTree(): No tree_id given! ",$this->ilErr->WARNING);
 
 2067                 if ($a_node_id <= 0)
 
 2069                         $a_node_id = $a_tree_id;
 
 2072                 $query = 
'INSERT INTO '.$this->table_tree.
' ('.
 
 2073                         $this->tree_pk.
', child,parent,lft,rgt,depth) '.
 
 2075                         '(%s,%s,%s,%s,%s,%s)';
 
 2076                 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer',
'integer',
'integer',
'integer',
'integer'),array(
 
 2098                 if (!isset($a_type) or (!is_string($a_type)))
 
 2100                         $this->ilErr->raiseError(get_class($this).
"::getNodeDataByType(): Type not given or wrong datatype!",$this->ilErr->WARNING);
 
 2108                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2109                         'WHERE '.$this->tree_pk.
' = %s '.
 
 2111                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2115                 while (
$row = $ilDB->fetchObject(
$res))
 
 2121                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2123                         'WHERE '.$this->table_obj_data.
'.type = %s '.
 
 2124                         'AND '.$this->table_tree.
'.lft BETWEEN %s AND %s '.
 
 2125                         'AND '.$this->table_tree.
'.rgt BETWEEN %s AND %s '.
 
 2126                         'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2127                 $res = $ilDB->queryF(
$query,array(
'text',
'integer',
'integer',
'integer',
'integer',
'integer'),array(
 
 2135                 while(
$row = $ilDB->fetchAssoc(
$res))
 
 2157                         $message = sprintf(
'%s::removeTree(): Operation not allowed on main tree! $a_tree_if: %s',
 
 2160                         $this->log->write($message,$this->log->FATAL);
 
 2161                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2165                         $this->ilErr->raiseError(get_class($this).
"::removeTree(): No tree_id given! Action aborted",$this->ilErr->MESSAGE);
 
 2168                 $query = 
'DELETE FROM '.$this->table_tree.
 
 2169                         ' WHERE '.$this->tree_pk.
' = %s ';
 
 2170                 $res = $ilDB->manipulateF(
$query,array(
'integer'),array($a_tree_id));
 
 2187                         $message = sprintf(
'%s::saveSubTree(): No valid parameter given! $a_node_id: %s',
 
 2190                         $this->log->write($message,$this->log->FATAL);
 
 2191                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2202                         #ilDB::_lockTables(array('tree' => 'WRITE', 
 2203                         #       'object_reference' => 'WRITE')); 
 2208                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2209                         'WHERE '.$this->tree_pk.
' = %s '.
 
 2211                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2215                 while(
$row = $ilDB->fetchObject(
$res))
 
 2222                 $query = 
'SELECT child FROM '.$this->table_tree.
' '.
 
 2223                         'WHERE '.$this->tree_pk.
' = %s '.
 
 2224                         'AND lft BETWEEN %s AND %s ';
 
 2225                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
 
 2230                 $subnodes = array();
 
 2231                 while(
$row = $ilDB->fetchAssoc(
$res))
 
 2233                         $subnodes[] = 
$row[
'child'];
 
 2236                 if(!count($subnodes))
 
 2243                                 $ilDB->unlockTables();
 
 2250                 foreach($subnodes as $child)
 
 2261                 $query = 
'UPDATE '.$this->table_tree.
' '.
 
 2263                         'WHERE '.$this->tree_pk.
' = %s '.
 
 2264                         'AND lft BETWEEN %s AND %s ';
 
 2265                 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer',
'integer',
'integer'),array(
 
 2273                         $ilDB->unlockTables();
 
 2285                 return $this->
isSaved($a_node_id);
 
 2296                 if ($this->
isCacheUsed() && isset($this->is_saved_cache[$a_node_id]))
 
 2299                         return $this->is_saved_cache[$a_node_id];
 
 2302                 $query = 
'SELECT '.$this->tree_pk.
' FROM '.$this->table_tree.
' '.
 
 2303                         'WHERE child = %s ';
 
 2304                 $res = $ilDB->queryF(
$query,array(
'integer'),array($a_node_id));
 
 2307                 if (
$row[$this->tree_pk] < 0)
 
 2311                                 $this->is_saved_cache[$a_node_id] = 
true;
 
 2319                                 $this->is_saved_cache[$a_node_id] = 
false;
 
 2335                 if (!is_array($a_node_ids) || !$this->
isCacheUsed())
 
 2340                 $query = 
'SELECT '.$this->tree_pk.
', child FROM '.$this->table_tree.
' '.
 
 2341                         'WHERE '.$ilDB->in(
"child", $a_node_ids, 
false, 
"integer");
 
 2344                 while (
$row = $ilDB->fetchAssoc(
$res))
 
 2346                         if (
$row[$this->tree_pk] < 0)
 
 2350                                         $this->is_saved_cache[
$row[
"child"]] = 
true;
 
 2357                                         $this->is_saved_cache[
$row[
"child"]] = 
false;
 
 2374                 if (!isset($a_parent_id))
 
 2376                         $this->ilErr->raiseError(get_class($this).
"::getSavedNodeData(): No node_id given!",$this->ilErr->WARNING);
 
 2379                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2381                         'WHERE '.$this->table_tree.
'.'.$this->tree_pk.
' < %s '.
 
 2382                         'AND '.$this->table_tree.
'.parent = %s';
 
 2383                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2387                 while(
$row = $ilDB->fetchAssoc(
$res))
 
 2392                 return $saved ? $saved : array();
 
 2405                 $query = 
'SELECT '.$this->table_obj_data.
'.obj_id FROM '.$this->table_tree.
' '.
 
 2407                         'WHERE '.$this->table_tree.
'.'.$this->tree_pk.
' < '.$ilDB->quote(0, 
'integer').
' '.
 
 2408                         'AND '.$ilDB->in($this->table_obj_data.
'.obj_id', $a_obj_ids, 
'', 
'integer');
 
 2410                 while(
$row = $ilDB->fetchAssoc(
$res))
 
 2412                         $saved[] = 
$row[
'obj_id'];
 
 2415                 return $saved ? $saved : array();
 
 2428                 if (!isset($a_node_id))
 
 2430                         $this->ilErr->raiseError(get_class($this).
"::getParentId(): No node_id given! ",$this->ilErr->WARNING);
 
 2433                 $query = 
'SELECT parent FROM '.$this->table_tree.
' '.
 
 2434                         'WHERE child = %s '.
 
 2435                         'AND '.$this->tree_pk.
' = %s ';
 
 2436                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2441                 return $row->parent;
 
 2454                 if (!isset($a_node_id))
 
 2456                         $this->ilErr->raiseError(get_class($this).
"::getLeftValued(): No node_id given! ",$this->ilErr->WARNING);
 
 2459                 $query = 
'SELECT lft FROM '.$this->table_tree.
' '.
 
 2460                         'WHERE child = %s '.
 
 2461                         'AND '.$this->tree_pk.
' = %s ';
 
 2462                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2479                 if (!isset($a_node))
 
 2481                         $this->ilErr->raiseError(get_class($this).
"::getChildSequenceNumber(): No node_id given! ",$this->ilErr->WARNING);
 
 2486                         $query = 
'SELECT count(*) cnt FROM '.$this->table_tree.
' '.
 
 2491                                 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2493                         $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer',
'integer'),array(
 
 2501                         $query = 
'SELECT count(*) cnt FROM '.$this->table_tree.
' '.
 
 2505                                 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2507                         $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
 
 2527                 $query = 
'SELECT child FROM '.$this->table_tree.
' '.
 
 2528                         'WHERE parent = %s '.
 
 2529                         'AND '.$this->tree_pk.
' = %s ';
 
 2530                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2534                 $this->root_id = 
$row->child;
 
 2549                 $this->root_id = $a_root_id;
 
 2569                 $this->tree_id = $a_tree_id;
 
 2583                 if (!isset($a_node_id))
 
 2585                         $this->ilErr->raiseError(get_class($this).
"::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
 
 2589                 $query = 
'SELECT lft FROM '.$this->table_tree.
' '.
 
 2590                         'WHERE '.$this->table_tree.
'.child = %s '.
 
 2591                         'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2592                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2596                 $curr_node = $ilDB->fetchAssoc(
$res);
 
 2600                         $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2603                                 'AND '.$this->table_obj_data.
'.type = %s '.
 
 2604                                 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
 
 2607                         $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer'),array(
 
 2614                         $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2617                                 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
 
 2620                         $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2625                 if (
$res->numRows() < 1)
 
 2647                 if (!isset($a_node_id))
 
 2649                         $this->ilErr->raiseError(get_class($this).
"::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
 
 2653                 $query = 
'SELECT lft FROM '.$this->table_tree.
' '.
 
 2654                         'WHERE '.$this->table_tree.
'.child = %s '.
 
 2655                         'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2656                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2660                 $curr_node = $ilDB->fetchAssoc(
$res);
 
 2664                         $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2667                                 'AND '.$this->table_obj_data.
'.type = %s '.
 
 2668                                 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
 
 2669                                 'ORDER BY lft DESC';
 
 2671                         $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer'),array(
 
 2678                         $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2681                                 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
 
 2682                                 'ORDER BY lft DESC';
 
 2684                         $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2689                 if (
$res->numRows() < 1)
 
 2727                                         2 => array(
'name' => $this->table_obj_reference, 
'type' => 
ilDB::LOCK_WRITE),
 
 2729                                         4 => array(
'name' => 
'object_data', 
'type' => 
ilDB::LOCK_WRITE, 
'alias' => 
'od'),
 
 2730                                         5 => array(
'name' => 
'container_reference', 
'type' => 
ilDB::LOCK_WRITE, 
'alias' => 
'cr')
 
 2736                         $ilDB->unlockTables();
 
 2756                 $query = 
'UPDATE '.$this->table_tree.
' SET lft = %s WHERE child = %s';
 
 2757                 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer'),array(
 
 2763                 foreach ($childs as $child)
 
 2765                         $i = $this->
__renumber($child[
"child"],$i+1);
 
 2770                 if (count($childs) > 0)
 
 2772                         $i += $this->gap * 2;
 
 2776                 $query = 
'UPDATE '.$this->table_tree.
' SET rgt = %s WHERE child = %s';
 
 2777                 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer'),array(
 
 2797                 $cache_key = $a_ref_id.
'.'.$a_type.
'.'.((int)$a_exclude_source_check);
 
 2801                         array_key_exists($cache_key, $this->parent_type_cache)) 
 
 2803                         return $this->parent_type_cache[$cache_key];
 
 2807                 $do_cache = ($this->
__isMainTree() && count($this->parent_type_cache) < 1000);
 
 2814                 $this->parent_type_cache[$cache_key] = 
false;
 
 2822                 if($a_exclude_source_check)
 
 2827                 foreach(
$path as $node)
 
 2830                         if($node[
"type"] == $a_type)
 
 2834                                         $this->parent_type_cache[$cache_key] = $node[
"child"];
 
 2836                                 return $node[
"child"];
 
 2842                         $this->parent_type_cache[$cache_key] = 
false;
 
 2860                 if($a_db_table === 
'tree')
 
 2862                         if($a_tree == 1 and $a_child == ROOT_FOLDER_ID)
 
 2864                                 $message = sprintf(
'%s::_removeEntry(): Tried to delete root node! $a_tree: %s $a_child: %s',
 
 2868                                 $ilLog->write($message,$ilLog->FATAL);
 
 2869                                 $ilErr->raiseError($message,$ilErr->WARNING);
 
 2873                 $query = 
'DELETE FROM '.$a_db_table.
' '.
 
 2876                 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer'),array(
 
 2891                 return $this->table_tree === 
'tree';
 
 2907                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2910                         'AND '.$this->tree_pk.
' = %s ';
 
 2911                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
 
 2914                         $a_node[$this->tree_pk]));
 
 2916                 $counter = (int) $lft_childs = array();
 
 2917                 while(
$row = $ilDB->fetchObject(
$res))
 
 2919                         $lft_childs[
$row->child] = 
$row->parent;
 
 2924                 if($counter != count($lft_childs))
 
 2926                         $message = sprintf(
'%s::__checkTree(): Duplicate entries for "child" in maintree! $a_node_id: %s',
 
 2929                         $this->log->write($message,$this->log->FATAL);
 
 2930                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2934                 $parent_childs = array();
 
 2946                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2947                         'WHERE child = %s '.
 
 2949                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
 
 2954                 while(
$row = $ilDB->fetchObject(
$res))
 
 2956                         $parent_childs[$a_node_id] = 
$row->parent;
 
 2962                         $message = sprintf(
'%s::__getSubTreeByParentRelation(): Multiple entries in maintree! $a_node_id: %s',
 
 2965                         $this->log->write($message,$this->log->FATAL);
 
 2966                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2970                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2971                         'WHERE parent = %s ';
 
 2972                 $res = $ilDB->queryF(
$query,array(
'integer'),array($a_node_id));
 
 2974                 while(
$row = $ilDB->fetchObject(
$res))
 
 2986                 ksort($parent_childs);
 
 2988                 if(count($lft_childs) != count($parent_childs))
 
 2990                         $message = sprintf(
'%s::__validateSubtrees(): (COUNT) Tree is corrupted! Left/Right subtree does not comply .'.
 
 2991                                                            'with parent relation',
 
 2993                         $this->log->write($message,$this->log->FATAL);
 
 2994                         $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 2997                 foreach($lft_childs as $key => $value)
 
 2999                         if($parent_childs[$key] != $value)
 
 3001                                 $message = sprintf(
'%s::__validateSubtrees(): (COMPARE) Tree is corrupted! Left/Right subtree does not comply '.
 
 3002                                                                    'with parent relation',
 
 3004                                 $this->log->write($message,$this->log->FATAL);
 
 3005                                 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 3007                         if($key == ROOT_FOLDER_ID)
 
 3009                                 $message = sprintf(
'%s::__validateSubtrees(): (ROOT_FOLDER) Tree is corrupted! Tried to delete root folder',
 
 3011                                 $this->log->write($message,$this->log->FATAL);
 
 3012                                 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
 
 3033                         #ilDB::_lockTables(array('tree' => 'WRITE')); 
 3040                 $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 3041                         'WHERE ( child = %s OR child = %s ) '.
 
 3042                         'AND '.$this->tree_pk.
' = %s ';
 
 3043                 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
 
 3049                 if(
$res->numRows() != 2)
 
 3053                                 $ilDB->unlockTables();
 
 3055                         $this->log->write(__METHOD__.
' Objects not found in tree!',$this->log->FATAL);
 
 3056                         $this->ilErr->raiseError(
'Error moving node',$this->ilErr->WARNING);
 
 3058                 while(
$row = $ilDB->fetchObject(
$res))
 
 3060                         if(
$row->child == $a_source_id)
 
 3062                                 $source_lft = 
$row->lft;
 
 3063                                 $source_rgt = 
$row->rgt;
 
 3064                                 $source_depth = 
$row->depth;
 
 3065                                 $source_parent = 
$row->parent;
 
 3069                                 $target_lft = 
$row->lft;
 
 3070                                 $target_rgt = 
$row->rgt;
 
 3071                                 $target_depth = 
$row->depth;
 
 3075                 #var_dump("<pre>",$source_lft,$source_rgt,$source_depth,$target_lft,$target_rgt,$target_depth,"<pre>"); 
 3077                 if($target_lft >= $source_lft and $target_rgt <= $source_rgt)
 
 3081                                 $ilDB->unlockTables();
 
 3083                         $this->log->write(__METHOD__.
' Target is child of source',$this->log->FATAL);
 
 3084                         $this->ilErr->raiseError(
'Error moving node',$this->ilErr->WARNING);
 
 3089                 $spread_diff = $source_rgt - $source_lft + 1;
 
 3090                 #var_dump("<pre>","SPREAD_DIFF: ",$spread_diff,"<pre>"); 
 3092                 $query = 
'UPDATE '.$this->table_tree.
' SET '.
 
 3093                         'lft = CASE WHEN lft >  %s THEN lft + %s ELSE lft END, '.
 
 3094                         'rgt = CASE WHEN rgt >= %s THEN rgt + %s ELSE rgt END '.
 
 3095                         'WHERE '.$this->tree_pk.
' = %s ';
 
 3096                 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer',
'integer',
'integer',
'integer'),array(
 
 3105                 if($source_lft > $target_rgt)
 
 3107                         $where_offset = $spread_diff;
 
 3108                         $move_diff = $target_rgt - $source_lft - $spread_diff;
 
 3113                         $move_diff = $target_rgt - $source_lft;
 
 3115                 $depth_diff = $target_depth - $source_depth + 1;
 
 3118                 $query = 
'UPDATE '.$this->table_tree.
' SET '.
 
 3119                         'parent = CASE WHEN parent = %s THEN %s ELSE parent END, '.
 
 3122                         'depth = depth + %s '.
 
 3125                         'AND '.$this->tree_pk.
' = %s ';
 
 3127                         array(
'integer',
'integer',
'integer',
'integer',
'integer',
'integer',
'integer',
'integer'),
 
 3134                         $source_lft + $where_offset,
 
 3135                         $source_rgt + $where_offset,
 
 3139                 $query = 
'UPDATE '.$this->table_tree.
' SET '.
 
 3140                         'lft = CASE WHEN lft >= %s THEN lft - %s ELSE lft END, '.
 
 3141                         'rgt = CASE WHEN rgt >= %s THEN rgt - %s ELSE rgt END '.
 
 3142                         'WHERE '.$this->tree_pk.
' = %s ';
 
 3145                         array(
'integer',
'integer',
'integer',
'integer',
'integer'),
 
 3147                         $source_lft + $where_offset,
 
 3149                         $source_rgt +$where_offset,
 
 3155                         $ilDB->unlockTables();
 
 3158            global $ilAppEventHandler;
 
 3160                 $ilAppEventHandler->raise(
 
 3164                                         'tree'          => $this->table_tree,
 
 3165                                         'source_id' => $a_source_id, 
 
 3166                                         'target_id' => $a_target_id)
 
 3183                 $query = 
"SELECT t2.lft lft, t2.rgt rgt, t2.child child, type ".
 
 3184                         "FROM ".$this->table_tree.
" t1 ".
 
 3185                         "JOIN ".$this->table_tree.
" t2 ON (t2.lft BETWEEN t1.lft AND t1.rgt) ".
 
 3186                         "JOIN ".$this->table_obj_reference.
" obr ON t2.child = obr.ref_id ".
 
 3187                         "JOIN ".$this->table_obj_data.
" obd ON obr.obj_id = obd.obj_id ".
 
 3188                         "WHERE t1.child = ".$ilDB->quote($a_endnode_id,
'integer').
" ".
 
 3189                         "AND t1.".$this->tree_pk.
" = ".$ilDB->quote($this->tree_id,
'integer').
" ".
 
 3190                         "AND t2.".$this->tree_pk.
" = ".$ilDB->quote($this->tree_id,
'integer').
" ".
 
 3196                         $nodes[
$row->child][
'lft']      = 
$row->lft;
 
 3197                         $nodes[
$row->child][
'rgt']      = 
$row->rgt;
 
 3198                         $nodes[
$row->child][
'child']= 
$row->child;
 
 3199                         $nodes[
$row->child][
'type']     = 
$row->type;
 
 3202                 return (array) $nodes;