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