4define(
"IL_LAST_NODE", -2);
 
    5define(
"IL_FIRST_NODE", -1);
 
    7include_once 
'./Services/Tree/exceptions/class.ilInvalidTreeStructureException.php';
 
  155                $this->lang_code = 
"en";
 
  160                if (!isset($a_tree_id) or (func_num_args() == 0) )
 
  162                        $this->log->error(
"No tree_id given!");
 
  164                        throw new InvalidArgumentException(
"No tree_id given!");
 
  167                if (func_num_args() > 2)
 
  169                        $this->log->error(
"Wrong parameter count!");
 
  170                        throw new InvalidArgumentException(
"Wrong parameter count!");
 
  174                if (empty($a_root_id))
 
  176                        $a_root_id = ROOT_FOLDER_ID;
 
  179                $this->tree_id            = $a_tree_id;
 
  180                $this->root_id            = $a_root_id;
 
  181                $this->table_tree     = 
'tree';
 
  182                $this->table_obj_data = 
'object_data';
 
  183                $this->table_obj_reference = 
'object_reference';
 
  184                $this->ref_pk = 
'ref_id';
 
  185                $this->obj_pk = 
'obj_id';
 
  186                $this->tree_pk = 
'tree';
 
  188                $this->use_cache = 
true;
 
  191                $this->translation_cache = array();
 
  192                $this->parent_type_cache = array();
 
  210                if(!is_object(
$GLOBALS[
'ilSetting']) or 
$GLOBALS[
'ilSetting']->getModule() != 
'common')
 
  212                        include_once 
'./Services/Administration/classes/class.ilSetting.php';
 
  222                        if($setting->get(
'main_tree_impl',
'ns') == 
'ns')
 
  224                                #$GLOBALS['ilLog']->write(__METHOD__.': Using nested set.'); 
  225                                include_once 
'./Services/Tree/classes/class.ilNestedSetTree.php';
 
  230                                #$GLOBALS['ilLog']->write(__METHOD__.': Using materialized path.'); 
  231                                include_once 
'./Services/Tree/classes/class.ilMaterializedPathTree.php';
 
  237                        #$GLOBALS['ilLog']->write(__METHOD__.': Using netsted set for non main tree.'); 
  238                        include_once 
'./Services/Tree/classes/class.ilNestedSetTree.php';
 
  257                $this->use_cache = $a_use;
 
  298                        $this->lang_code = 
"en";
 
  302                        $this->lang_code = 
$ilUser->getCurrentLanguage();
 
  354                $this->in_tree_cache = array();
 
  374        function setTableNames($a_table_tree,$a_table_obj_data,$a_table_obj_reference = 
"")
 
  376                if (!isset($a_table_tree) or !isset($a_table_obj_data))
 
  378                        $message = 
"Missing parameter! ".
 
  379                                                                "tree table: ".$a_table_tree.
" object data table: ".$a_table_obj_data;
 
  380                        $this->log->error($message);
 
  381                        throw new InvalidArgumentException($message);
 
  384                $this->table_tree = $a_table_tree;
 
  385                $this->table_obj_data = $a_table_obj_data;
 
  386                $this->table_obj_reference = $a_table_obj_reference;
 
  402                if (!isset($a_column_name))
 
  404                        $message = 
"No column name given!";
 
  405                        $this->log->error($message);
 
  406                        throw new InvalidArgumentException($message);
 
  409                $this->ref_pk = $a_column_name;
 
  422                if (!isset($a_column_name))
 
  424                        $message = 
"No column name given!";
 
  425                        $this->log->error($message);
 
  426                        throw new InvalidArgumentException($message);
 
  429                $this->obj_pk = $a_column_name;
 
  442                if (!isset($a_column_name))
 
  444                        $message = 
"No column name given!";
 
  445                        $this->log->error($message);
 
  446                        throw new InvalidArgumentException($message);
 
  449                $this->tree_pk = $a_column_name;
 
  460                if ($this->table_obj_reference)
 
  463                        return "JOIN ".$this->table_obj_reference.
" ON ".$this->table_tree.
".child=".$this->table_obj_reference.
".".$this->ref_pk.
" ".
 
  464                                   "JOIN ".$this->table_obj_data.
" ON ".$this->table_obj_reference.
".".$this->obj_pk.
"=".$this->table_obj_data.
".".$this->obj_pk.
" ";
 
  469                        return "JOIN ".$this->table_obj_data.
" ON ".$this->table_tree.
".child=".$this->table_obj_data.
".".$this->obj_pk.
" ";
 
  507                $query = 
'SELECT * FROM '. $this->table_tree . 
' ' .
 
  508                                'WHERE parent = '.$ilDB->quote($a_node,
'integer').
' '.
 
  509                                'AND tree = '.$ilDB->quote($this->tree_id,
'integer' . 
' ' .
 
  516                        $childs[] = 
$row->child;
 
  530        function getChilds($a_node_id, $a_order = 
"", $a_direction = 
"ASC")
 
  534                if (!isset($a_node_id))
 
  536                        $message = 
"No node_id given!";
 
  537                        $this->log->error($message);
 
  538                        throw new InvalidArgumentException($message);
 
  551                if (!empty($a_order))
 
  553                        $order_clause = 
"ORDER BY ".$a_order.
" ".$a_direction;
 
  557                        $order_clause = 
"ORDER BY ".$this->table_tree.
".lft";
 
  563                                "WHERE parent = %s " .
 
  564                                "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
 
  566                                $ilDB->quote($a_node_id,
'integer'),
 
  567                                $ilDB->quote($this->tree_id,
'integer'));
 
  571                if(!$count = 
$res->numRows())
 
  581                        $obj_ids[] = 
$r[
"obj_id"];
 
  586                        is_object(
$ilUser) && $this->lang_code == 
$ilUser->getLanguage() && !$this->oc_preloaded[$a_node_id])
 
  589                        $ilObjDataCache->preloadObjectCache($obj_ids, $this->lang_code);
 
  591                        $this->oc_preloaded[$a_node_id] = 
true;
 
  594                foreach ($rows as 
$row)
 
  601                                #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$row['child'].' = true'); 
  602                                $this->in_tree_cache[
$row[
'child']] = 
$row[
'tree'] == 1;
 
  605                $childs[$count - 1][
"last"] = 
true;
 
  620                $childs = $this->
getChilds($a_node,$a_order,$a_direction);
 
  622                foreach($childs as $child)
 
  624                        if(!in_array($child[
"type"],$a_filter))
 
  626                                $filtered[] = $child;
 
  629                return $filtered ? $filtered : array();
 
  645                if (!isset($a_node_id) or !isset(
$a_type))
 
  647                        $message = 
"Missing parameter! node_id:".$a_node_id.
" type:".
$a_type;
 
  648                        $this->log->error($message);
 
  649                        throw new InvalidArgumentException($message);
 
  652        if (
$a_type==
'rolf' && $this->table_obj_reference) {
 
  656            $ilDB->setLimit(1,0);
 
  659                "WHERE parent = %s ".
 
  660                "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
 
  661                "AND ".$this->table_obj_data.
".type = %s ",
 
  662                $ilDB->quote($a_node_id,
'integer'),
 
  663                $ilDB->quote($this->tree_id,
'integer'),
 
  668                "WHERE parent = %s ".
 
  669                "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
 
  670                "AND ".$this->table_obj_data.
".type = %s ".
 
  671                "ORDER BY ".$this->table_tree.
".lft",
 
  672                $ilDB->quote($a_node_id,
'integer'),
 
  673                $ilDB->quote($this->tree_id,
'integer'),
 
  685                return $childs ? $childs : array();
 
  701                if (!isset($a_node_id) or !$a_types)
 
  703                        $message = 
"Missing parameter! node_id:".$a_node_id.
" type:".$a_types;
 
  704                        $this->log->error($message);
 
  705                        throw new InvalidArgumentException($message);
 
  711                        $filter = 
'AND '.$this->table_obj_data.
'.type IN('.implode(
',',
ilUtil::quoteArray($a_types)).
') ';
 
  715                if (!empty($a_order))
 
  717                        $order_clause = 
"ORDER BY ".$a_order.
" ".$a_direction;
 
  721                        $order_clause = 
"ORDER BY ".$this->table_tree.
".lft";
 
  724                $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
  726                        'WHERE parent = '.$ilDB->quote($a_node_id,
'integer').
' '.
 
  727                        'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = '.
$ilDB->quote($this->tree_id,
'integer').
' '.
 
  737                return $childs ? $childs : array();
 
  757                        if($a_source_id <= 1 or $a_target_id <= 0)
 
  760                                throw new InvalidArgumentException(
'Invalid parameter given for ilTree::insertNodeFromTrash');
 
  763                if (!isset($a_source_id) or !isset($a_target_id))
 
  766                        throw new InvalidArgumentException(
'Missing parameter for ilTree::insertNodeFromTrash');
 
  772                        throw new InvalidArgumentException(
'Node already in tree.');
 
  775                $query = 
'DELETE from tree '.
 
  776                                'WHERE tree = '.$ilDB->quote($a_tree_id,
'integer').
' '.
 
  777                                'AND child = '.$ilDB->quote($a_source_id,
'integer');
 
  800                        if($a_node_id <= 1 or $a_parent_id <= 0)
 
  802                                $message = 
sprintf(
'Invalid parameters! $a_node_id: %s $a_parent_id: %s',
 
  806                                throw new InvalidArgumentException($message);
 
  811                if (!isset($a_node_id) or !isset($a_parent_id))
 
  814                        throw new InvalidArgumentException(
"Missing parameter! ".
 
  815                                "node_id: ".$a_node_id.
" parent_id: ".$a_parent_id);
 
  819                        throw new InvalidArgumentException(
"Node ".$a_node_id.
" already in tree ".
 
  820                                                                         $this->table_tree.
"!");
 
  825                $this->in_tree_cache[$a_node_id] = 
true;
 
  828                if ($a_reset_deletion_date)
 
  834                        $GLOBALS[
'ilAppEventHandler']->raise(
 
  838                                                'tree'          => $this->table_tree,
 
  839                                                'node_id'       => $a_node_id, 
 
  840                                                'parent_id'     => $a_parent_id)
 
  865                        if($depth and $subnode[
'depth'] > $depth)
 
  869                        if(!$first and in_array($subnode[
'type'],$a_filter))
 
  871                                $depth = $subnode[
'depth'];
 
  877                        $filtered[] = $subnode; 
 
  879                return $filtered ? $filtered : array();
 
  906                if (!is_array($a_node))
 
  909                        throw new InvalidArgumentException(__METHOD__.
': wrong datatype for node data given');
 
  935                                $subtree[] = 
$row[
'child'];
 
  938                        if($this->
__isMainTree() || $this->table_tree == 
"lm_tree")
 
  940                                $this->in_tree_cache[
$row[
'child']] = 
true;
 
  943                return $subtree ? $subtree : array();
 
  956                $a_filter = $a_filter ? $a_filter : array();
 
  958                foreach($this->getSubtree($this->
getNodeData($a_node)) as $node)
 
  960                        if(in_array($node[
"type"],$a_filter))
 
  964                        $types[
"$node[type]"] = $node[
"type"];
 
  966                return $types ? $types : array();
 
  980                $this->log->debug(
'Delete tree with node '. $a_node);
 
  982                if (!is_array($a_node))
 
  985                        throw new InvalidArgumentException(__METHOD__.
': Wrong datatype for node data!');
 
  988                $this->log->debug($this->tree_pk);
 
 1027                $pathIds = $this->
getPathId($a_endnode_id, $a_startnode_id);
 
 1033                if (count($pathIds) == 0)
 
 1038                $inClause = 
'child IN (';
 
 1039                for ($i=0; $i < count($pathIds); $i++)
 
 1041                        if ($i > 0) $inClause .= 
',';
 
 1042                        $inClause .= 
$ilDB->quote($pathIds[$i],
'integer');
 
 1047                        'FROM '.$this->table_tree.
' '.
 
 1049                        'WHERE '.$inClause.
' '.
 
 1050            'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = '.$this->
ilDB->
quote($this->tree_id,
'integer').
' '.
 
 1054                $pathFull = array();
 
 1062                                #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$row['child']); 
 1063                                $this->in_tree_cache[
$row[
'child']] = 
$row[
'tree'] == 1;
 
 1085                $res = $ilDB->query(
'SELECT t.depth, t.parent, t.child '.
 
 1086                        'FROM '.$this->table_tree.
' t '.
 
 1087                        'WHERE '.$ilDB->in(
"child", $a_node_ids, 
false, 
"integer").
 
 1088                        'AND '.$this->tree_pk.
' = '.
$ilDB->quote($this->tree_id, 
"integer"));
 
 1091                        $this->depth_cache[
$row[
"child"]] = 
$row[
"depth"];
 
 1092                        $this->parent_cache[
$row[
"child"]] = 
$row[
"parent"];
 
 1105        public function getPathId($a_endnode_id, $a_startnode_id = 0)
 
 1110                        throw new InvalidArgumentException(__METHOD__.
': No endnode given!');
 
 1114                if ($this->
isCacheUsed() && isset($this->path_id_cache[$a_endnode_id][$a_startnode_id]))
 
 1117                        return $this->path_id_cache[$a_endnode_id][$a_startnode_id];
 
 1125                        $this->path_id_cache[$a_endnode_id][$a_startnode_id] = $pathIds;
 
 1154                if ($titlePath == 
null || count($titlePath) == 0)
 
 1156                        if ($a_startnode_id == 0)
 
 1167                if ($a_startnode_id != 
null && $a_startnode_id != 0)
 
 1171                        $parent = $a_startnode_id;
 
 1176                        $nodePath = array();
 
 1184                require_once(
'include/Unicode/UtfNormal.php');
 
 1185                include_once 
'./Services/Utilities/classes/class.ilStr.php';
 
 1186                $inClause = 
'd.title IN (';
 
 1187                for ($i=0; $i < count($titlePath); $i++)
 
 1190                        if ($i > 0) $inClause .= 
',';
 
 1191                        $inClause .= 
$ilDB->quote($titlePath[$i],
'text');
 
 1196                if ($this->table_obj_reference)
 
 1198                        $joinClause = 
'JOIN '.$this->table_obj_reference.
'  r ON t.child = r.'.$this->ref_pk.
' '.
 
 1199                                'JOIN '.$this->table_obj_data.
' d ON r.'.$this->obj_pk.
' = d.'.
$this->obj_pk;
 
 1203                        $joinClause = 
'JOIN '.$this->table_obj_data.
'  d ON t.child = d.'.
$this->obj_pk;
 
 1210                $q = 
'SELECT t.depth, t.parent, t.child, d.'.$this->obj_pk.
' obj_id, d.type, d.title '.
 
 1211                        'FROM '.$this->table_tree.
'  t '.
 
 1213                        'WHERE '.$inClause.
' '.
 
 1214                        'AND t.depth <= '.(count($titlePath)+count($nodePath)).
' '.
 
 1216                        'ORDER BY t.depth, t.child ASC';
 
 1228                for ($i = 0; $i < count($titlePath); $i++) {
 
 1229                        $pathElementFound = 
false; 
 
 1230                        foreach ($rows as 
$row) {
 
 1231                                if (
$row[
'parent'] == $parent && 
 
 1237                                        $parent = 
$row[
'child'];
 
 1238                                        $pathElementFound = 
true;
 
 1243                        if (! $pathElementFound)
 
 1275                $pathIds = $this->
getPathId($a_endnode_id, $a_startnode_id);
 
 1278                if (count($pathIds) == 0)
 
 1286                for ($i = 0; $i < count($pathIds); $i++)
 
 1288                        $types[] = 
'integer';
 
 1289                        $data[] = $pathIds[$i];
 
 1292                $query = 
'SELECT t.depth,t.parent,t.child,d.obj_id,d.type,d.title '.
 
 1293                        'FROM '.$this->table_tree.
' t '.
 
 1294                        'JOIN '.$this->table_obj_reference.
' r ON r.ref_id = t.child '.
 
 1295                        'JOIN '.$this->table_obj_data.
' d ON d.obj_id = r.obj_id '.
 
 1296                        'WHERE '.$ilDB->in(
't.child',
$data,
false,
'integer').
' '.
 
 1297                        'ORDER BY t.depth ';
 
 1301                $titlePath = array();
 
 1304                        $titlePath[] = 
$row;
 
 1321                $types = array(
'integer');
 
 1322                $query = 
'SELECT lft,rgt FROM '.$this->table_tree.
' '.
 
 1323                        'WHERE '.$this->tree_pk.
' = %s ';
 
 1332                $all = array_merge($lft,$rgt);
 
 1333                $uni = array_unique($all);
 
 1335                if (count($all) != count($uni))
 
 1337                        $message = 
'Tree is corrupted!';
 
 1339                        $this->log->error($message);
 
 1357                $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 1358                                'WHERE '.$this->tree_pk.
' = %s '.
 
 1360                $r1 = 
$ilDB->queryF(
$query,array(
'integer'),array($this->tree_id));
 
 1365                        if ((
$row[
"child"] == 0) && $a_no_zero_child)
 
 1367                                $message = 
"Tree contains child with ID 0!";
 
 1368                                $this->log->error($message);
 
 1372                        if ($this->table_obj_reference)
 
 1375                                $query = 
'SELECT * FROM '.$this->table_obj_reference.
' WHERE '.$this->ref_pk.
' = %s ';
 
 1379                                if ($r2->numRows() == 0)
 
 1381                                        $message = 
"No Object-to-Reference entry found for ID ". 
$row[
"child"].
"!";
 
 1382                                        $this->log->error($message);
 
 1385                                if ($r2->numRows() > 1)
 
 1387                                        $message = 
"More Object-to-Reference entries found for ID ". 
$row[
"child"].
"!";
 
 1388                                        $this->log->error($message);
 
 1393                                $obj_ref = 
$ilDB->fetchAssoc($r2);
 
 1395                                $query = 
'SELECT * FROM '.$this->table_obj_data.
' WHERE '.$this->obj_pk.
' = %s';
 
 1396                                $r3 = 
$ilDB->queryF(
$query,array(
'integer'),array($obj_ref[$this->obj_pk]));
 
 1397                                if ($r3->numRows() == 0)
 
 1399                                        $message = 
" No child found for ID ". $obj_ref[
$this->obj_pk].
"!";
 
 1400                                        $this->log->error($message);
 
 1403                                if ($r3->numRows() > 1)
 
 1405                                        $message = 
"More childs found for ID ". $obj_ref[
$this->obj_pk].
"!";
 
 1406                                        $this->log->error($message);
 
 1414                                $query = 
'SELECT * FROM '.$this->table_obj_data.
' WHERE '.$this->obj_pk.
' = %s';
 
 1417                                if ($r2->numRows() == 0)
 
 1419                                        $message = 
"No child found for ID ". 
$row[
"child"].
"!";
 
 1420                                        $this->log->error($message);
 
 1423                                if ($r2->numRows() > 1)
 
 1425                                        $message = 
"More childs found for ID ". 
$row[
"child"].
"!";
 
 1426                                        $this->log->error($message);
 
 1444                $query = 
'SELECT MAX(depth) depth FROM '.$this->table_tree;
 
 1448                return $row[
'depth'];
 
 1463                        $query = 
'SELECT depth FROM '.$this->table_tree.
' '.
 
 1464                                'WHERE child = %s '.
 
 1465                                'AND '.$this->tree_pk.
' = %s ';
 
 1466                        $res = 
$ilDB->queryF(
$query,array(
'integer',
'integer'),array($a_node_id,$this->tree_id));
 
 1491                        throw new InvalidArgumentException(
'Missing or empty parameter $a_node_id: '. $a_node_id);
 
 1494                $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 1495                                'WHERE child = '.$ilDB->quote($a_node_id,
'integer');
 
 1520                if (!isset($a_node_id))
 
 1523                        throw new InvalidArgumentException(
"No node_id given!");
 
 1529                                $message = 
'No valid parameter given! $a_node_id: %s'.$a_node_id;
 
 1531                                $this->log->error($message);
 
 1532                                throw new InvalidArgumentException($message);
 
 1537                $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 1539                        'WHERE '.$this->table_tree.
'.child = %s '.
 
 1540                        'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 1543                        $a_tree_pk === 
null ? $this->tree_id : $a_tree_pk));
 
 1564                $data[
"desc"] = $a_row[
"description"];  
 
 1569                if (is_object($objDefinition))
 
 1571                        $translation_type = $objDefinition->getTranslationType(
$data[
"type"]);
 
 1575                if ($translation_type == 
"sys")
 
 1578                        if (
$data[
"type"] == 
"rolf" and 
$data[
"obj_id"] != ROLE_FOLDER_ID)
 
 1580                                $data[
"description"] = 
$lng->txt(
"obj_".
$data[
"type"].
"_local_desc").$data[
"title"].$data[
"desc"];
 
 1581                                $data[
"desc"] = 
$lng->txt(
"obj_".
$data[
"type"].
"_local_desc").$data[
"title"].$data[
"desc"];
 
 1592                elseif ($translation_type == 
"db")
 
 1597                                array_key_exists(
$data[
"obj_id"].
'.'.$lang_code, $this->translation_cache)) {
 
 1599                                $key = 
$data[
"obj_id"].
'.'.$lang_code;
 
 1600                                $data[
"title"] = $this->translation_cache[$key][
'title'];
 
 1601                                $data[
"description"] = $this->translation_cache[$key][
'description'];
 
 1602                                $data[
"desc"] = $this->translation_cache[$key][
'desc'];
 
 1608                                $query = 
'SELECT title,description FROM object_translation '.
 
 1609                                        'WHERE obj_id = %s '.
 
 1610                                        'AND lang_code = %s '.
 
 1611                                        'AND NOT lang_default = %s';
 
 1628                                if ($this->
isCacheUsed() && count($this->translation_cache) < 1000)
 
 1630                                        $key = 
$data[
"obj_id"].
'.'.$lang_code;
 
 1631                                        $this->translation_cache[$key] = array();
 
 1632                                        $this->translation_cache[$key][
'title'] = 
$data[
"title"] ;
 
 1633                                        $this->translation_cache[$key][
'description'] = 
$data[
"description"];
 
 1634                                        $this->translation_cache[$key][
'desc'] = 
$data[
"desc"];
 
 1640                if(
$data[
'type'] == 
'crsr' or 
$data[
'type'] == 
'catr' or 
$data[
'type'] == 
'grpr')
 
 1642                        include_once(
'./Services/ContainerReference/classes/class.ilContainerReference.php');
 
 1656                global $ilObjDataCache;
 
 1658                if ($this->
isCacheUsed() && is_array($a_obj_ids) && is_object($ilObjDataCache))
 
 1660                        foreach ($a_obj_ids as $id)
 
 1662                                $this->translation_cache[$id.
'.'][
'title'] = $ilObjDataCache->lookupTitle($id);
 
 1663                                $this->translation_cache[$id.
'.'][
'description'] = $ilObjDataCache->lookupDescription($id);;
 
 1664                                $this->translation_cache[$id.
'.'][
'desc'] =
 
 1665                                        $this->translation_cache[$id.
'.'][
'description'];
 
 1682                if (!isset($a_node_id))
 
 1685                        #$this->ilErr->raiseError(get_class($this)."::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
 
 1688                if ($this->
isCacheUsed() && isset($this->in_tree_cache[$a_node_id]))
 
 1690                        #$GLOBALS['ilLog']->write(__METHOD__.': Using in tree cache '.$a_node_id); 
 1692                        return $this->in_tree_cache[$a_node_id];
 
 1695                $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 1696                        'WHERE '.$this->table_tree.
'.child = %s '.
 
 1697                        'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s';
 
 1703                if (
$res->numRows() > 0)
 
 1707                                #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true'); 
 1708                                $this->in_tree_cache[$a_node_id] = 
true;
 
 1716                                #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = false'); 
 1717                                $this->in_tree_cache[$a_node_id] = 
false;
 
 1735                if (!isset($a_node_id))
 
 1738                        throw new InvalidArgumentException(__METHOD__.
': No node_id given!');
 
 1741                if ($this->table_obj_reference)
 
 1744                        $innerjoin = 
"JOIN ".$this->table_obj_reference.
" ON v.child=".$this->table_obj_reference.
".".$this->ref_pk.
" ".
 
 1745                                                "JOIN ".$this->table_obj_data.
" ON ".$this->table_obj_reference.
".".$this->obj_pk.
"=".$this->table_obj_data.
".".$this->obj_pk.
" ";
 
 1750                        $innerjoin = 
"JOIN ".$this->table_obj_data.
" ON v.child=".$this->table_obj_data.
".".$this->obj_pk.
" ";
 
 1753                $query = 
'SELECT * FROM '.$this->table_tree.
' s, '.$this->table_tree.
' v '.
 
 1755                        'WHERE s.child = %s '.
 
 1756                        'AND s.parent = v.child '.
 
 1757                        'AND s.'.$this->tree_pk.
' = %s '.
 
 1758                        'AND v.'.$this->tree_pk.
' = %s';
 
 1759                $res = 
$ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
 
 1795                        $message = 
sprintf(
'Operation not allowed on main tree! $a_tree_if: %s $a_node_id: %s',
 
 1798                        $this->log->error($message);
 
 1799                        throw new InvalidArgumentException($message);
 
 1802                if (!isset($a_tree_id))
 
 1804                        $message  = 
"No tree_id given!";
 
 1805                        $this->log->error($message);
 
 1806                        throw new InvalidArgumentException($message);
 
 1809                if ($a_node_id <= 0)
 
 1811                        $a_node_id = $a_tree_id;
 
 1814                $query = 
'INSERT INTO '.$this->table_tree.
' ('.
 
 1815                        $this->tree_pk.
', child,parent,lft,rgt,depth) '.
 
 1817                        '(%s,%s,%s,%s,%s,%s)';
 
 1818                $res = 
$ilDB->manipulateF(
$query,array(
'integer',
'integer',
'integer',
'integer',
'integer',
'integer'),array(
 
 1845                        throw new InvalidArgumentException(
'Type not given or wrong datatype');
 
 1848                $query = 
'SELECT * FROM ' . $this->table_tree . 
' ' .
 
 1850                        'WHERE ' . $this->table_obj_data . 
'.type = ' . $this->
ilDB->
quote(
$a_type, 
'text').
 
 1851                        'AND ' . $this->table_tree . 
'.' . $this->tree_pk . 
' = ' . $this->
ilDB->
quote($this->tree_id, 
'integer');
 
 1879                        throw new InvalidArgumentException(
'Operation not allowed on main tree');
 
 1884                        throw new InvalidArgumentException(
'Missing parameter tree id');
 
 1887                $query = 
'DELETE FROM '.$this->table_tree.
 
 1888                        ' WHERE '.$this->tree_pk.
' = %s ';
 
 1889                $ilDB->manipulateF(
$query,array(
'integer'),array($a_tree_id));
 
 1907                        throw new InvalidArgumentException(
'No valid parameter given! $a_node_id: '.$a_node_id);
 
 1914                $subnodes = array();
 
 1917                        $subnodes[] = 
$row[
'child'];
 
 1920                if(!count($subnodes))
 
 1928                        include_once 
'./Services/Object/classes/class.ilObject.php';
 
 1950                return $this->
moveToTrash($a_node_id, $a_set_deleted);
 
 1959                return $this->
isSaved($a_node_id);
 
 1972                if ($this->
isCacheUsed() && isset($this->is_saved_cache[$a_node_id]))
 
 1975                        return $this->is_saved_cache[$a_node_id];
 
 1978                $query = 
'SELECT '.$this->tree_pk.
' FROM '.$this->table_tree.
' '.
 
 1979                        'WHERE child = %s ';
 
 1983                if (
$row[$this->tree_pk] < 0)
 
 1987                                $this->is_saved_cache[$a_node_id] = 
true;
 
 1995                                $this->is_saved_cache[$a_node_id] = 
false;
 
 2011                if (!is_array($a_node_ids) || !$this->
isCacheUsed())
 
 2016                $query = 
'SELECT '.$this->tree_pk.
', child FROM '.$this->table_tree.
' '.
 
 2017                        'WHERE '.$ilDB->in(
"child", $a_node_ids, 
false, 
"integer");
 
 2022                        if (
$row[$this->tree_pk] < 0)
 
 2026                                        $this->is_saved_cache[
$row[
"child"]] = 
true;
 
 2033                                        $this->is_saved_cache[
$row[
"child"]] = 
false;
 
 2051                if (!isset($a_parent_id))
 
 2053                        $message = 
"No node_id given!";
 
 2054                        $this->log->error($message);
 
 2055                        throw new InvalidArgumentException($message);
 
 2058                $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2060                        'WHERE '.$this->table_tree.
'.'.$this->tree_pk.
' < %s '.
 
 2061                        'AND '.$this->table_tree.
'.parent = %s';
 
 2071                return $saved ? $saved : array();
 
 2084                $query = 
'SELECT '.$this->table_obj_data.
'.obj_id FROM '.$this->table_tree.
' '.
 
 2086                        'WHERE '.$this->table_tree.
'.'.$this->tree_pk.
' < '.
$ilDB->quote(0, 
'integer').
' '.
 
 2087                        'AND '.$ilDB->in($this->table_obj_data.
'.obj_id', $a_obj_ids, 
'', 
'integer');
 
 2091                        $saved[] = 
$row[
'obj_id'];
 
 2094                return $saved ? $saved : array();
 
 2108                if (!isset($a_node_id))
 
 2110                        $message = 
"No node_id given!";
 
 2111                        $this->log->error($message);
 
 2112                        throw new InvalidArgumentException($message);
 
 2115                $query = 
'SELECT parent FROM '.$this->table_tree.
' '.
 
 2116                        'WHERE child = %s '.
 
 2117                        'AND '.$this->tree_pk.
' = %s ';
 
 2123                return $row->parent;
 
 2137                if (!isset($a_node_id))
 
 2139                        $message = 
"No node_id given!";
 
 2140                        $this->log->error($message);
 
 2141                        throw new InvalidArgumentException($message);
 
 2144                $query = 
'SELECT lft FROM '.$this->table_tree.
' '.
 
 2145                        'WHERE child = %s '.
 
 2146                        'AND '.$this->tree_pk.
' = %s ';
 
 2165                if (!isset($a_node))
 
 2167                        $message = 
"No node_id given!";
 
 2168                        $this->log->error($message);
 
 2169                        throw new InvalidArgumentException($message);
 
 2174                        $query = 
'SELECT count(*) cnt FROM '.$this->table_tree.
' '.
 
 2179                                'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2181                        $res = 
$ilDB->queryF(
$query,array(
'integer',
'text',
'integer',
'integer'),array(
 
 2189                        $query = 
'SELECT count(*) cnt FROM '.$this->table_tree.
' '.
 
 2193                                'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2195                        $res = 
$ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
 
 2215                $query = 
'SELECT child FROM '.$this->table_tree.
' '.
 
 2216                        'WHERE parent = %s '.
 
 2217                        'AND '.$this->tree_pk.
' = %s ';
 
 2222                $this->root_id = 
$row->child;
 
 2237                $this->root_id = $a_root_id;
 
 2257                $this->tree_id = $a_tree_id;
 
 2272                if (!isset($a_node_id))
 
 2274                        $message = 
"No node_id given!";
 
 2275                        $this->log->error($message);
 
 2276                        throw new InvalidArgumentException($message);
 
 2280                $query = 
'SELECT lft FROM '.$this->table_tree.
' '.
 
 2281                        'WHERE '.$this->table_tree.
'.child = %s '.
 
 2282                        'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2290                        $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2293                                'AND '.$this->table_obj_data.
'.type = %s '.
 
 2294                                'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
 
 2304                        $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2307                                'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
 
 2315                if (
$res->numRows() < 1)
 
 2338                if (!isset($a_node_id))
 
 2340                        $message = 
"No node_id given!";
 
 2341                        $this->log->error($message);
 
 2342                        throw new InvalidArgumentException($message);
 
 2346                $query = 
'SELECT lft FROM '.$this->table_tree.
' '.
 
 2347                        'WHERE '.$this->table_tree.
'.child = %s '.
 
 2348                        'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
 
 2357                        $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2360                                'AND '.$this->table_obj_data.
'.type = %s '.
 
 2361                                'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
 
 2362                                'ORDER BY lft DESC';
 
 2371                        $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2374                                'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
 
 2375                                'ORDER BY lft DESC';
 
 2382                if (
$res->numRows() < 1)
 
 2415                        $ilAtomQuery = 
$ilDB->buildAtomQuery();
 
 2416                        $ilAtomQuery->addTableLock( $this->table_tree );
 
 2418                        $ilAtomQuery->addQueryCallable($renumber_callable);
 
 2419                        $ilAtomQuery->run();
 
 2423                        $renumber_callable(
$ilDB);
 
 2442                $query = 
'UPDATE '.$this->table_tree.
' SET lft = %s WHERE child = %s AND tree = %s';
 
 2443                $res = 
$ilDB->manipulateF(
$query,array(
'integer',
'integer',
'integer'),array(
 
 2452                foreach ($childs as $child)
 
 2459                if (count($childs) > 0)
 
 2461                        $i += $this->gap * 2;
 
 2465                $query = 
'UPDATE '.$this->table_tree.
' SET rgt = %s WHERE child = %s AND tree = %s';
 
 2466                $res = 
$ilDB->manipulateF(
$query,array(
'integer',
'integer', 
'integer'),array(
 
 2487                $cache_key = $a_ref_id.
'.'.
$a_type.
'.'.((int)$a_exclude_source_check);
 
 2491                        array_key_exists($cache_key, $this->parent_type_cache)) 
 
 2493                        return $this->parent_type_cache[$cache_key];
 
 2497                $do_cache = ($this->
__isMainTree() && count($this->parent_type_cache) < 1000);
 
 2504                $this->parent_type_cache[$cache_key] = 
false;
 
 2512                if($a_exclude_source_check)
 
 2517                foreach(
$path as $node)
 
 2524                                        $this->parent_type_cache[$cache_key] = $node[
"child"];
 
 2526                                return $node[
"child"];
 
 2532                        $this->parent_type_cache[$cache_key] = 
false;
 
 2551                if($a_db_table === 
'tree')
 
 2553                        if($a_tree == 1 and $a_child == ROOT_FOLDER_ID)
 
 2555                                $message = 
sprintf(
'Tried to delete root node! $a_tree: %s $a_child: %s',
 
 2559                                throw new InvalidArgumentException($message);
 
 2563                $query = 
'DELETE FROM '.$a_db_table.
' '.
 
 2580                return $this->table_tree === 
'tree';
 
 2600                $this->log->debug(
$query);
 
 2603                $counter = (int) $lft_childs = array();
 
 2606                        $lft_childs[
$row->child] = 
$row->parent;
 
 2613                        $message = 
'Duplicate entries for "child" in maintree! $a_node_id: '.$a_node[
'child'];
 
 2615                        $this->log->error($message);
 
 2620                $parent_childs = array();
 
 2641                $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2642                        'WHERE child = %s '.
 
 2651                        $parent_childs[$a_node_id] = 
$row->parent;
 
 2657                        $message = 
'Multiple entries in maintree! $a_node_id: '. $a_node_id;
 
 2659                        $this->log->error($message);
 
 2664                $query = 
'SELECT * FROM '.$this->table_tree.
' '.
 
 2665                        'WHERE parent = %s ';
 
 2687                ksort($parent_childs);
 
 2689                $this->log->debug(
'left childs '. print_r($lft_childs,
true));
 
 2690                $this->log->debug(
'parent childs '. print_r($parent_childs,
true));
 
 2692                if(count($lft_childs) != count($parent_childs))
 
 2694                        $message = 
'(COUNT) Tree is corrupted! Left/Right subtree does not comply with parent relation';
 
 2695                        $this->log->error($message);
 
 2700                foreach($lft_childs as $key => $value)
 
 2702                        if($parent_childs[$key] != $value)
 
 2704                                $message = 
'(COMPARE) Tree is corrupted! Left/Right subtree does not comply with parent relation';
 
 2705                                $this->log->error($message);
 
 2708                        if($key == ROOT_FOLDER_ID)
 
 2710                                $message = 
'(ROOT_FOLDER) Tree is corrupted! Tried to delete root folder';
 
 2711                                $this->log->error($message);
 
 2727        public function moveTree($a_source_id, $a_target_id, $a_location = self::POS_LAST_NODE)
 
 2729                $old_parent_id = $this->
getParentId($a_source_id);
 
 2732                        $GLOBALS[
'ilAppEventHandler']->raise(
 
 2736                                                'tree'                  => $this->table_tree,
 
 2737                                                'source_id'     => $a_source_id, 
 
 2738                                                'target_id'     => $a_target_id,
 
 2739                                                'old_parent_id' => $old_parent_id
 
 2769        public function getSubTreeQuery($a_node_id,$a_fields = array(), $a_types = 
'', $a_force_join_reference = 
false)
 
 2774                                $a_force_join_reference, 
 
 2802                if(count($a_fields))
 
 2804                        $fields = implode(
',',$a_fields);
 
 2807                $query = 
"SELECT ".$fields.
 
 2808                        " FROM ".$this->getTreeTable().
 
 2809                        " ".$this->buildJoin().
 
 2810                        " WHERE ".$this->getTableReference().
".".$this->ref_pk.
" IN (".
$query.
")".
 
 2811                        " AND ".$ilDB->in($this->
getObjectDataTable().
".".$this->obj_pk, $a_obj_ids, 
"", 
"integer");
 
 2823                global 
$ilDB, $ilAppEventHandler;
 
 2825                $query = 
'DELETE FROM tree where '.
 
 2826                                'child = '.$ilDB->quote($a_node_id,
'integer').
' '.
 
 2827                                'AND tree = '.$ilDB->quote($a_tree_id,
'integer');
 
 2830                $ilAppEventHandler->raise(
 
 2833                                        array(
'tree' => $this->table_tree,
 
 2834                                                  'node_id' => $a_node_id,
 
 2835                                                  'tree_id' => $a_tree_id
 
 2849                $query = 
'SELECT DISTINCT(o.type) '.$ilDB->quoteIdentifier(
'type').
' FROM tree t JOIN object_reference r ON child = r.ref_id '.
 
 2850                                'JOIN object_data o on r.obj_id = o.obj_id '.
 
 2851                                'WHERE tree < '.$ilDB->quote(0,
'integer').
' '.
 
 2852                                'AND child = -tree '.
 
 2856                $types_deleted = array();
 
 2859                        $types_deleted[] = 
$row->type;
 
 2861                return $types_deleted;
 
sprintf('%.4f', $callTime)
An exception for terminatinating execution or to throw for unit testing.
static toNFC( $string)
Convert a UTF-8 string to normal form C, canonical composition.
static _lookupTitle($a_obj_id)
Overwitten from base class.
quote($a_query, $a_type=null)
Wrapper for quote method.
Thrown if invalid tree strucutes are found.
static getLogger($a_component_id)
Get component logger.
Base class for materialize path based trees Based on implementation of Werner Randelshofer.
Base class for nested set path based trees.
static setDeletedDates($a_ref_ids)
Set deleted date @global type $ilDB.
static _resetDeletedDate($a_ref_id)
only called in ilObjectGUI::insertSavedNodes
static strToLower($a_string)
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
isCacheUsed()
Check if cache is active.
fetchPredecessorNode($a_node_id, $a_type="")
get node data of predecessor node
lookupTrashedObjectTypes()
Lookup object types in trash @global type $ilDB.
getRelation($a_node_a, $a_node_b)
Get relation of two nodes.
moveToTrash($a_node_id, $a_set_deleted=false)
Wrapper for saveSubTree.
getSubTree($a_node, $a_with_data=true, $a_type="")
get all nodes in the subtree under specified node
getFilteredChilds($a_filter, $a_node, $a_order="", $a_direction="ASC")
get child nodes of given node (exclude filtered obj_types) @access public
isGrandChild($a_startnode_id, $a_querynode_id)
checks if a node is in the path of an other node @access public
getSubTreeTypes($a_node, $a_filter=0)
get types of nodes in the subtree under specified node
getRelationOfNodes($a_node_a_arr, $a_node_b_arr)
get relation of two nodes by node data
setObjectTablePK($a_column_name)
set column containing primary key in object table @access public
getTreePk()
Get tree primary key.
getParentId($a_node_id)
get parent id of given node @access public
getRbacSubtreeInfo($a_endnode_id)
This method is used for change existing objects and returns all necessary information for this action...
getParentCache()
Get parent cache.
setReferenceTablePK($a_column_name)
set column containing primary key in reference table @access public
saveSubTree($a_node_id, $a_set_deleted=false)
Use the wrapper moveToTrash save subtree: delete a subtree (defined by node_id) to a new tree with $t...
checkTreeChilds($a_no_zero_child=true)
check, if all childs of tree nodes exist in object table
getDepth($a_node_id)
return depth of a node in tree @access private
getSavedNodeData($a_parent_id)
get data saved/deleted nodes
getChildSequenceNumber($a_node, $type="")
get sequence number of node in sibling sequence @access public
insertNodeFromTrash($a_source_id, $a_target_id, $a_tree_id, $a_pos=IL_LAST_NODE, $a_reset_deleted_date=false)
Insert node from trash deletes trash entry.
useCache($a_use=true)
Use Cache (usually activated)
deleteTree($a_node)
delete node and the whole subtree under this node @access public
getLeftValue($a_node_id)
get left value of given node @access public
__checkDelete($a_node)
Check for deleteTree() compares a subtree of a given node by checking lft, rgt against parent relatio...
fetchSuccessorNode($a_node_id, $a_type="")
get node data of successor node
getDepthCache()
Get depth cache.
getTreeId()
get tree id @access public
getChildIds($a_node)
Get node child ids @global type $ilDB.
getNodeDataByType($a_type)
get nodes by type
getTreeTable()
Get tree table name.
static _removeEntry($a_tree, $a_child, $a_db_table="tree")
STATIC METHOD Removes a single entry from a tree.
getSubTreeQuery($a_node_id, $a_fields=array(), $a_types='', $a_force_join_reference=false)
Get tree subtree query.
__renumber($node_id=1, $i=1)
This method is private.
setTreeTablePK($a_column_name)
set column containing primary key in tree table @access public
isDeleted($a_node_id)
This is a wrapper for isSaved() with a more useful name.
getNodeTreeData($a_node_id)
return all columns of tabel tree
setTableNames($a_table_tree, $a_table_obj_data, $a_table_obj_reference="")
set table names The primary key of the table containing your object_data must be 'obj_id' You may use...
getTableReference()
Get reference table if available.
fetchTranslationFromObjectDataCache($a_obj_ids)
Get translation data from object cache (trigger in object cache on preload)
readRootId()
read root id from database
removeTree($a_tree_id)
remove an existing tree
fetchNodeData($a_row)
get data of parent node from tree and object_data @access private
checkTree()
check consistence of tree all left & right values are checked if they are exists only once @access pu...
getSubTreeFilteredByObjIds($a_node_id, array $a_obj_ids, array $a_fields=array())
get all node ids in the subtree under specified node id, filter by object ids
renumber($node_id=1, $i=1)
Wrapper for renumber.
getNodePath($a_endnode_id, $a_startnode_id=0)
Returns the node path for the specified object reference.
getChildsByType($a_node_id, $a_type)
get child nodes of given node by object type @access public
getNodeData($a_node_id, $a_tree_pk=null)
get all information of a node.
setTreeId($a_tree_id)
set tree id @access public
getSavedNodeObjIds(array $a_obj_ids)
get object id of saved/deleted nodes
getChildsByTypeFilter($a_node_id, $a_types, $a_order="", $a_direction="ASC")
get child nodes of given node by object type @access public
deleteNode($a_tree_id, $a_node_id)
getMaximumDepth()
Return the current maximum depth in the tree @access public.
moveTree($a_source_id, $a_target_id, $a_location=self::POS_LAST_NODE)
Move Tree Implementation.
preloadDepthParent($a_node_ids)
Preload depth/parent.
isSaved($a_node_id)
Use method isDeleted check if node is saved.
initLangCode()
Store user language.
buildJoin()
build join depending on table settings @access private
getTreeImplementation()
Get tree implementation.
getNodePathForTitlePath($titlePath, $a_startnode_id=null)
Converts a path consisting of object titles into a path consisting of tree nodes.
initTreeImplementation()
Init tree implementation.
preloadDeleted($a_node_ids)
Preload deleted information.
__construct($a_tree_id, $a_root_id=0)
Constructor @access public.
getFilteredSubTree($a_node_id, $a_filter=array())
get filtered subtree
getObjectDataTable()
Get object data table.
getRootId()
get the root id of tree @access public
insertNode($a_node_id, $a_parent_id, $a_pos=IL_LAST_NODE, $a_reset_deletion_date=false)
insert new node with node_id under parent node with parent_id @access public
checkForParentType($a_ref_id, $a_type, $a_exclude_source_check=false)
Check for parent type e.g check if a folder (ref_id 3) is in a parent course obj => checkForParentTyp...
__isMainTree()
Check if operations are done on main tree.
__getSubTreeByParentRelation($a_node_id, &$parent_childs)
@global type $ilDB
isInTree($a_node_id)
get all information of a node.
getGap()
Get default gap *.
__validateSubtrees(&$lft_childs, $parent_childs)
getPathId($a_endnode_id, $a_startnode_id=0)
get path from a given startnode to a given endnode if startnode is not given the rootnode is startnod...
addTree($a_tree_id, $a_node_id=-1)
create a new tree to do: ???
getPathFull($a_endnode_id, $a_startnode_id=0)
get path from a given startnode to a given endnode if startnode is not given the rootnode is startnod...
getParentNodeData($a_node_id)
get data of parent node from tree and object_data @access public
getChilds($a_node_id, $a_order="", $a_direction="ASC")
get child nodes of given node @access public
validateParentRelations()
Validate parent relations of tree.
getSubTreeIds($a_ref_id)
Get all ids of subnodes.
static shortenText($a_str, $a_len, $a_dots=false, $a_next_blank=false, $a_keep_extension=false)
shorten a string to given length.
static quoteArray($a_array)
Quotes all members of an array for usage in DB query statement.
$GLOBALS['loaded']
Global hash that tracks already loaded includes.