4 define(
"IL_LAST_NODE", -2);
5 define(
"IL_FIRST_NODE", -1);
126 function ilTree($a_tree_id, $a_root_id = 0)
143 $this->lang_code =
"en";
145 if (!isset($a_tree_id) or (func_num_args() == 0) )
147 $this->ilErr->raiseError(get_class($this).
"::Constructor(): No tree_id given!",$this->ilErr->WARNING);
150 if (func_num_args() > 2)
152 $this->ilErr->raiseError(get_class($this).
"::Constructor(): Wrong parameter count!",$this->ilErr->WARNING);
159 if (empty($a_root_id))
161 $a_root_id = ROOT_FOLDER_ID;
164 $this->tree_id = $a_tree_id;
165 $this->root_id = $a_root_id;
166 $this->table_tree =
'tree';
167 $this->table_obj_data =
'object_data';
168 $this->table_obj_reference =
'object_reference';
169 $this->ref_pk =
'ref_id';
170 $this->obj_pk =
'obj_id';
171 $this->tree_pk =
'tree';
173 $this->use_cache =
true;
176 $this->translation_cache = array();
177 $this->parent_type_cache = array();
188 $this->use_cache = $a_use;
209 if (!is_object($ilUser))
211 $this->lang_code =
"en";
215 $this->lang_code = $ilUser->getCurrentLanguage();
234 function setTableNames($a_table_tree,$a_table_obj_data,$a_table_obj_reference =
"")
236 if (!isset($a_table_tree) or !isset($a_table_obj_data))
238 $this->ilErr->raiseError(get_class($this).
"::setTableNames(): Missing parameter! ".
239 "tree table: ".$a_table_tree.
" object data table: ".$a_table_obj_data,$this->ilErr->WARNING);
242 $this->table_tree = $a_table_tree;
243 $this->table_obj_data = $a_table_obj_data;
244 $this->table_obj_reference = $a_table_obj_reference;
257 if (!isset($a_column_name))
259 $this->ilErr->raiseError(get_class($this).
"::setReferenceTablePK(): No column name given!",$this->ilErr->WARNING);
262 $this->ref_pk = $a_column_name;
274 if (!isset($a_column_name))
276 $this->ilErr->raiseError(get_class($this).
"::setObjectTablePK(): No column name given!",$this->ilErr->WARNING);
279 $this->obj_pk = $a_column_name;
291 if (!isset($a_column_name))
293 $this->ilErr->raiseError(get_class($this).
"::setTreeTablePK(): No column name given!",$this->ilErr->WARNING);
296 $this->tree_pk = $a_column_name;
307 if ($this->table_obj_reference)
310 return "JOIN ".$this->table_obj_reference.
" ON ".$this->table_tree.
".child=".$this->table_obj_reference.
".".$this->ref_pk.
" ".
311 "JOIN ".$this->table_obj_data.
" ON ".$this->table_obj_reference.
".".$this->obj_pk.
"=".$this->table_obj_data.
".".$this->obj_pk.
" ";
316 return "JOIN ".$this->table_obj_data.
" ON ".$this->table_tree.
".child=".$this->table_obj_data.
".".$this->obj_pk.
" ";
328 function getChilds($a_node_id, $a_order =
"", $a_direction =
"ASC")
332 if (!isset($a_node_id))
334 $message = get_class($this).
"::getChilds(): No node_id given!";
335 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
348 if (!empty($a_order))
350 $order_clause =
"ORDER BY ".$a_order.
" ".$a_direction;
354 $order_clause =
"ORDER BY ".$this->table_tree.
".lft";
358 $query = sprintf(
'SELECT * FROM '.$this->table_tree.
' '.
360 "WHERE parent = %s " .
361 "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
363 $ilDB->quote($a_node_id,
'integer'),
364 $ilDB->quote($this->tree_id,
'integer'));
368 if(!$count = $res->numRows())
373 while(
$row = $ilDB->fetchAssoc($res))
380 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$row['child'].' = true');
381 $this->in_tree_cache[
$row[
'child']] = $row[
'tree'] == 1;
384 $childs[$count - 1][
"last"] =
true;
399 $childs = $this->
getChilds($a_node,$a_order,$a_direction);
401 foreach($childs as $child)
403 if(!in_array($child[
"type"],$a_filter))
405 $filtered[] = $child;
408 return $filtered ? $filtered : array();
423 if (!isset($a_node_id) or !isset($a_type))
425 $message = get_class($this).
"::getChildsByType(): Missing parameter! node_id:".$a_node_id.
" type:".$a_type;
426 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
429 if ($a_type==
'rolf' && $this->table_obj_reference) {
433 $ilDB->setLimit(1,0);
434 $query = sprintf(
"SELECT * FROM ".$this->table_tree.
" ".
436 "WHERE parent = %s ".
437 "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
438 "AND ".$this->table_obj_data.
".type = %s ",
439 $ilDB->quote($a_node_id,
'integer'),
440 $ilDB->quote($this->tree_id,
'integer'),
441 $ilDB->quote($a_type,
'text'));
443 $query = sprintf(
"SELECT * FROM ".$this->table_tree.
" ".
445 "WHERE parent = %s ".
446 "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
447 "AND ".$this->table_obj_data.
".type = %s ".
448 "ORDER BY ".$this->table_tree.
".lft",
449 $ilDB->quote($a_node_id,
'integer'),
450 $ilDB->quote($this->tree_id,
'integer'),
451 $ilDB->quote($a_type,
'text'));
457 while(
$row = $ilDB->fetchAssoc(
$res))
462 return $childs ? $childs : array();
477 if (!isset($a_node_id) or !$a_types)
479 $message = get_class($this).
"::getChildsByType(): Missing parameter! node_id:".$a_node_id.
" type:".$a_types;
480 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
489 $query =
'SELECT * FROM '.$this->table_tree.
' '.
491 'WHERE parent = '.$ilDB->quote($a_node_id,
'integer').
' '.
492 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = '.$ilDB->quote($this->tree_id,
'integer').
' '.
494 'ORDER BY '.$this->table_tree.
'.lft';
497 while(
$row = $ilDB->fetchAssoc(
$res))
502 return $childs ? $childs : array();
520 if($a_node_id <= 1 or $a_parent_id <= 0)
522 $message = sprintf(
'%s::insertNode(): Invalid parameters! $a_node_id: %s $a_parent_id: %s',
526 $this->log->write($message,$this->log->FATAL);
527 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
532 if (!isset($a_node_id) or !isset($a_parent_id))
534 $this->ilErr->raiseError(get_class($this).
"::insertNode(): Missing parameter! ".
535 "node_id: ".$a_node_id.
" parent_id: ".$a_parent_id,$this->ilErr->WARNING);
539 $this->ilErr->raiseError(get_class($this).
"::insertNode(): Node ".$a_node_id.
" already in tree ".
540 $this->table_tree.
"!",$this->ilErr->WARNING);
550 #ilDB::_lockTables(array('tree' => 'WRITE'));
557 $query = sprintf(
'SELECT * FROM '.$this->table_tree.
' '.
559 'AND '.$this->tree_pk.
' = %s ',
560 $ilDB->quote($a_parent_id,
'integer'),
561 $ilDB->quote($this->tree_id,
'integer'));
564 $r = $ilDB->fetchObject($res);
566 if ($r->parent == NULL)
570 $ilDB->unlockTables();
572 $this->ilErr->raiseError(get_class($this).
"::insertNode(): Parent with ID ".$a_parent_id.
" not found in ".
573 $this->table_tree.
"!",$this->ilErr->WARNING);
581 $query = sprintf(
'UPDATE '.$this->table_tree.
' SET '.
582 'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, '.
583 'rgt = CASE WHEN rgt > %s THEN rgt + 2 ELSE rgt END '.
584 'WHERE '.$this->tree_pk.
' = %s ',
585 $ilDB->quote($left,
'integer'),
586 $ilDB->quote($left,
'integer'),
587 $ilDB->quote($this->tree_id,
'integer'));
588 $res = $ilDB->manipulate(
$query);
597 #ilDB::_lockTables(array('tree' => 'WRITE'));
605 $query = sprintf(
'SELECT rgt,lft,parent FROM '.$this->table_tree.
' '.
607 'AND '.$this->tree_pk.
' = %s',
608 $ilDB->quote($a_parent_id,
'integer'),
609 $ilDB->quote($this->tree_id,
'integer'));
610 $res = $ilDB->query(
$query);
611 $r = $ilDB->fetchAssoc($res);
613 if ($r[
'parent'] == null)
617 $ilDB->unlockTables();
619 $this->ilErr->raiseError(get_class($this).
"::insertNode(): Parent with ID ".
620 $a_parent_id.
" not found in ".$this->table_tree.
"!",$this->ilErr->WARNING);
622 $parentRgt = $r[
'rgt'];
623 $parentLft = $r[
'lft'];
626 $availableSpace = $parentRgt - $parentLft;
627 if ($availableSpace < 2)
638 $query = sprintf(
'SELECT MAX(rgt) max_rgt FROM '.$this->table_tree.
' '.
639 'WHERE parent = %s '.
640 'AND '.$this->tree_pk.
' = %s',
641 $ilDB->quote($a_parent_id,
'integer'),
642 $ilDB->quote($this->tree_id,
'integer'));
643 $res = $ilDB->query(
$query);
644 $r = $ilDB->fetchAssoc($res);
646 if (isset($r[
'max_rgt']))
650 $availableSpace = $parentRgt - $r[
'max_rgt'];
651 $lft = $r[
'max_rgt'] + 1;
658 $lft = $parentLft + 1;
665 if ($availableSpace < 2)
668 $query = sprintf(
'UPDATE '.$this->table_tree.
' SET '.
669 'lft = CASE WHEN lft > %s THEN lft + %s ELSE lft END, '.
670 'rgt = CASE WHEN rgt >= %s THEN rgt + %s ELSE rgt END '.
671 'WHERE '.$this->tree_pk.
' = %s ',
672 $ilDB->quote($parentRgt,
'integer'),
673 $ilDB->quote((2 + $this->gap * 2),
'integer'),
674 $ilDB->quote($parentRgt,
'integer'),
675 $ilDB->quote((2 + $this->gap * 2),
'integer'),
676 $ilDB->quote($this->tree_id,
'integer'));
677 $res = $ilDB->manipulate(
$query);
689 #ilDB::_lockTables(array('tree' => 'WRITE'));
697 $query = sprintf(
'SELECT * FROM '.$this->table_tree.
' '.
699 'AND '.$this->tree_pk.
' = %s ',
700 $ilDB->quote($a_parent_id,
'integer'),
701 $ilDB->quote($this->tree_id,
'integer'));
702 $res = $ilDB->query(
$query);
703 $r = $ilDB->fetchObject($res);
705 if ($r->parent == null)
709 $ilDB->unlockTables();
711 $this->ilErr->raiseError(get_class($this).
"::insertNode(): Parent with ID ".
712 $a_parent_id.
" not found in ".$this->table_tree.
"!",$this->ilErr->WARNING);
720 $query = sprintf(
'UPDATE '.$this->table_tree.
' SET '.
721 'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, '.
722 'rgt = CASE WHEN rgt >= %s THEN rgt + 2 ELSE rgt END '.
723 'WHERE '.$this->tree_pk.
' = %s',
724 $ilDB->quote($right,
'integer'),
725 $ilDB->quote($right,
'integer'),
726 $ilDB->quote($this->tree_id,
'integer'));
727 $res = $ilDB->manipulate(
$query);
737 #ilDB::_lockTables(array('tree' => 'WRITE'));
745 $query = sprintf(
'SELECT * FROM '.$this->table_tree.
' '.
747 'AND '.$this->tree_pk.
' = %s ',
748 $ilDB->quote($a_pos,
'integer'),
749 $ilDB->quote($this->tree_id,
'integer'));
750 $res = $ilDB->query(
$query);
751 $r = $ilDB->fetchObject($res);
754 if ($r->parent != $a_parent_id)
758 $ilDB->unlockTables();
760 $this->ilErr->raiseError(get_class($this).
"::insertNode(): Parents mismatch! ".
761 "new node parent: ".$a_parent_id.
" sibling parent: ".$r->parent,$this->ilErr->WARNING);
769 $query = sprintf(
'UPDATE '.$this->table_tree.
' SET '.
770 'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, '.
771 'rgt = CASE WHEN rgt > %s THEN rgt + 2 ELSE rgt END '.
772 'WHERE '.$this->tree_pk.
' = %s',
773 $ilDB->quote($right,
'integer'),
774 $ilDB->quote($right,
'integer'),
775 $ilDB->quote($this->tree_id,
'integer'));
776 $res = $ilDB->manipulate(
$query);
782 $depth = $this->
getDepth($a_parent_id) + 1;
786 $query = sprintf(
'INSERT INTO '.$this->table_tree.
' ('.$this->tree_pk.
',child,parent,lft,rgt,depth) '.
787 'VALUES (%s,%s,%s,%s,%s,%s)',
788 $ilDB->quote($this->tree_id,
'integer'),
789 $ilDB->quote($a_node_id,
'integer'),
790 $ilDB->quote($a_parent_id,
'integer'),
791 $ilDB->quote($lft,
'integer'),
792 $ilDB->quote($rgt,
'integer'),
793 $ilDB->quote($depth,
'integer'));
799 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true');
800 $this->in_tree_cache[$a_node_id] =
true;
801 $ilDB->unlockTables();
805 if ($a_reset_deletion_date)
831 if($depth and $subnode[
'depth'] > $depth)
835 if(!$first and in_array($subnode[
'type'],$a_filter))
837 $depth = $subnode[
'depth'];
843 $filtered[] = $subnode;
845 return $filtered ? $filtered : array();
857 $query =
'SELECT s.child FROM '.$this->table_tree.
' s, '.$this->table_tree.
' t '.
858 'WHERE t.child = %s '.
859 'AND s.lft > t.lft '.
860 'AND s.rgt < t.rgt '.
861 'AND s.'.$this->tree_pk.
' = %s';
863 $res = $ilDB->queryF(
865 array(
'integer',
'integer'),
866 array($a_ref_id,$this->tree_id)
870 $childs[] =
$row->child;
872 return $childs ? $childs : array();
884 function getSubTree($a_node,$a_with_data =
true, $a_type =
"")
888 if (!is_array($a_node))
890 $this->ilErr->raiseError(get_class($this).
"::getSubTree(): Wrong datatype for node_data! ",$this->ilErr->WARNING);
893 if($a_node[
'lft'] < 1 or $a_node[
'rgt'] < 2)
895 $message = sprintf(
'%s::getSubTree(): Invalid node given! $a_node["lft"]: %s $a_node["rgt"]: %s',
900 $this->log->write($message,$this->log->FATAL);
902 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
906 $fields = array(
'integer',
'integer',
'integer');
907 $data = array($a_node[
'lft'],$a_node[
'rgt'],$this->tree_id);
914 $type_str =
"AND ".$this->table_obj_data.
".type= %s ";
917 $query =
"SELECT * FROM ".$this->table_tree.
" ".
919 "WHERE ".$this->table_tree.
".lft BETWEEN %s AND %s ".
920 "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
922 "ORDER BY ".$this->table_tree.
".lft";
924 while(
$row = $ilDB->fetchAssoc(
$res))
932 $subtree[] =
$row[
'child'];
936 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true');
937 $this->in_tree_cache[
$row[
'child']] =
true;
941 return $subtree ? $subtree : array();
954 $a_filter = $a_filter ? $a_filter : array();
956 foreach($this->getSubtree($this->
getNodeData($a_node)) as $node)
958 if(in_array($node[
"type"],$a_filter))
962 $types[
"$node[type]"] = $node[
"type"];
964 return $types ? $types : array();
976 if (!is_array($a_node))
978 $this->ilErr->raiseError(get_class($this).
"::deleteTree(): Wrong datatype for node_data! ",$this->ilErr->WARNING);
980 if($this->
__isMainTree() and $a_node[$this->tree_pk] === 1)
982 if($a_node[
'lft'] <= 1 or $a_node[
'rgt'] <= 2)
984 $message = sprintf(
'%s::deleteTree(): Invalid parameters given: $a_node["lft"]: %s, $a_node["rgt"] %s',
989 $this->log->write($message,$this->log->FATAL);
990 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
994 $message = sprintf(
'%s::deleteTree(): Check delete failed: $a_node["lft"]: %s, $a_node["rgt"] %s',
998 $this->log->write($message,$this->log->FATAL);
999 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1003 $diff = $a_node[
"rgt"] - $a_node[
"lft"] + 1;
1010 #ilDB::_lockTables(array('tree' => 'WRITE'));
1017 $query = sprintf(
'SELECT * FROM '.$this->table_tree.
' '.
1018 'WHERE child = %s '.
1019 'AND '.$this->tree_pk.
' = %s ',
1020 $ilDB->quote($a_node[
'child'],
'integer'),
1021 $ilDB->quote($a_node[$this->tree_pk],
'integer'));
1023 while(
$row = $ilDB->fetchObject($res))
1025 $a_node[
'lft'] =
$row->lft;
1026 $a_node[
'rgt'] =
$row->rgt;
1027 $diff = $a_node[
"rgt"] - $a_node[
"lft"] + 1;
1031 $query = sprintf(
'DELETE FROM '.$this->table_tree.
' '.
1032 'WHERE lft BETWEEN %s AND %s '.
1033 'AND rgt BETWEEN %s AND %s '.
1034 'AND '.$this->tree_pk.
' = %s',
1035 $ilDB->quote($a_node[
'lft'],
'integer'),
1036 $ilDB->quote($a_node[
'rgt'],
'integer'),
1037 $ilDB->quote($a_node[
'lft'],
'integer'),
1038 $ilDB->quote($a_node[
'rgt'],
'integer'),
1039 $ilDB->quote($a_node[$this->tree_pk],
'integer'));
1040 $res = $ilDB->manipulate(
$query);
1045 if ($a_node[$this->tree_pk] >= 0 && $a_node[
'rgt'] - $a_node[
'lft'] >= $this->gap * 2)
1049 $query = sprintf(
'UPDATE '.$this->table_tree.
' SET '.
1050 'lft = CASE WHEN lft > %s THEN lft - %s ELSE lft END, '.
1051 'rgt = CASE WHEN rgt > %s THEN rgt - %s ELSE rgt END '.
1052 'WHERE '.$this->tree_pk.
' = %s ',
1053 $ilDB->quote($a_node[
'lft'],
'integer'),
1054 $ilDB->quote(
$diff,
'integer'),
1055 $ilDB->quote($a_node[
'lft'],
'integer'),
1056 $ilDB->quote(
$diff,
'integer'),
1057 $ilDB->quote($a_node[$this->tree_pk],
'integer'));
1059 $res = $ilDB->manipulate(
$query);
1068 #$GLOBALS['ilLog']->write(__METHOD__.': Resetting in tree cache ');
1069 $ilDB->unlockTables();
1070 $this->in_tree_cache = array();
1087 $pathIds =& $this->
getPathId($a_endnode_id, $a_startnode_id);
1093 if (count($pathIds) == 0)
1098 $inClause =
'child IN (';
1099 for ($i=0; $i < count($pathIds); $i++)
1101 if ($i > 0) $inClause .=
',';
1102 $inClause .= $ilDB->quote($pathIds[$i],
'integer');
1107 'FROM '.$this->table_tree.
' '.
1109 'WHERE '.$inClause.
' '.
1110 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = '.$this->
ilDB->
quote($this->tree_id,
'integer').
' '.
1112 $r = $ilDB->query(
$q);
1114 $pathFull = array();
1122 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$row['child']);
1123 $this->in_tree_cache[
$row[
'child']] = $row[
'tree'] == 1;
1146 if (!isset($a_endnode_id))
1148 $this->ilErr->raiseError(get_class($this).
"::getPathId(): No endnode_id given! ",$this->ilErr->WARNING);
1151 $fields = array(
'integer',
'integer',
'integer');
1152 $data = array($a_endnode_id,$this->tree_id,$this->tree_id);
1154 $query =
"SELECT T2.child ".
1155 "FROM ".$this->table_tree.
" T1, ".$this->table_tree.
" T2 ".
1156 "WHERE T1.child = %s ".
1157 "AND T1.lft BETWEEN T2.lft AND T2.rgt ".
1158 "AND T1.".$this->tree_pk.
" = %s ".
1159 "AND T2.".$this->tree_pk.
" = %s ".
1160 "ORDER BY T2.depth";
1163 $takeId = $a_startnode_id == 0;
1164 while(
$row = $ilDB->fetchAssoc(
$res))
1166 if ($takeId ||
$row[
'child'] == $a_startnode_id)
1169 $pathIds[] =
$row[
'child'];
1172 return $pathIds ? $pathIds : array();
1190 $takeId = $a_startnode_id == 0;
1192 if (!isset($a_endnode_id))
1194 $this->ilErr->raiseError(get_class($this).
"::getPathId(): No endnode_id given! ",$this->ilErr->WARNING);
1199 $types = array(
'integer',
'integer');
1200 $data = array($a_endnode_id,$this->tree_id);
1202 $query =
'SELECT t.depth, t.parent '.
1203 'FROM '.$this->table_tree.
' t '.
1204 'WHERE child = %s '.
1205 'AND '.$this->tree_pk.
' = %s ';
1208 if(
$res->numRows() == 0)
1214 $nodeDepth =
$row[
'depth'];
1215 $parentId =
$row[
'parent'];
1220 if ($nodeDepth == 1)
1222 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
1223 if ($takeId) $pathIds[] = $a_endnode_id;
1225 else if ($nodeDepth == 2)
1227 $takeId = $takeId || $parentId == $a_startnode_id;
1228 if ($takeId) $pathIds[] = $parentId;
1229 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
1230 if ($takeId) $pathIds[] = $a_endnode_id;
1232 else if ($nodeDepth == 3)
1234 $takeId = $takeId || $this->root_id == $a_startnode_id;
1236 $takeId = $takeId || $parentId == $a_startnode_id;
1237 if ($takeId) $pathIds[] = $parentId;
1238 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
1239 if ($takeId) $pathIds[] = $a_endnode_id;
1241 else if ($nodeDepth < 32)
1252 $qSelect =
't1.child c0';
1254 for ($i = 1; $i < $nodeDepth - 2; $i++)
1256 $qSelect .=
', t'.$i.
'.parent c'.$i;
1257 $qJoin .=
' JOIN '.$this->table_tree.
' t'.$i.
' ON '.
1258 't'.$i.
'.child=t'.($i - 1).
'.parent AND '.
1262 $types = array(
'integer',
'integer');
1263 $data = array($this->tree_id,$parentId);
1264 $query =
'SELECT '.$qSelect.
' '.
1265 'FROM '.$this->table_tree.
' t0 '.$qJoin.
' '.
1266 'WHERE t0.'.$this->tree_pk.
' = %s '.
1267 'AND t0.child = %s ';
1272 if (
$res->numRows() == 0)
1278 $takeId = $takeId || $this->root_id == $a_startnode_id;
1280 for ($i = $nodeDepth - 4; $i >=0; $i--)
1282 $takeId = $takeId ||
$row[
'c'.$i] == $a_startnode_id;
1283 if ($takeId) $pathIds[] =
$row[
'c'.$i];
1285 $takeId = $takeId || $parentId == $a_startnode_id;
1286 if ($takeId) $pathIds[] = $parentId;
1287 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
1288 if ($takeId) $pathIds[] = $a_endnode_id;
1310 if ($this->
isCacheUsed() && isset($this->path_id_cache[$a_endnode_id][$a_startnode_id]))
1313 return $this->path_id_cache[$a_endnode_id][$a_startnode_id];
1321 $this->path_id_cache[$a_endnode_id][$a_startnode_id] = $pathIds;
1350 if ($titlePath == null || count($titlePath) == 0)
1352 if ($a_startnode_id == 0)
1363 if ($a_startnode_id != null && $a_startnode_id != 0)
1367 $parent = $a_startnode_id;
1372 $nodePath = array();
1380 require_once(
'include/Unicode/UtfNormal.php');
1381 include_once
'./Services/Utilities/classes/class.ilStr.php';
1382 $inClause =
'd.title IN (';
1383 for ($i=0; $i < count($titlePath); $i++)
1386 if ($i > 0) $inClause .=
',';
1387 $inClause .= $ilDB->quote($titlePath[$i],
'text');
1392 if ($this->table_obj_reference)
1394 $joinClause =
'JOIN '.$this->table_obj_reference.
' r ON t.child = r.'.$this->ref_pk.
' '.
1395 'JOIN '.$this->table_obj_data.
' d ON r.'.$this->obj_pk.
' = d.'.
$this->obj_pk;
1399 $joinClause =
'JOIN '.$this->table_obj_data.
' d ON t.child = d.'.
$this->obj_pk;
1406 $q =
'SELECT t.depth, t.parent, t.child, d.'.$this->obj_pk.
' obj_id, d.type, d.title '.
1407 'FROM '.$this->table_tree.
' t '.
1409 'WHERE '.$inClause.
' '.
1410 'AND t.depth <= '.(count($titlePath)+count($nodePath)).
' '.
1412 'ORDER BY t.depth, t.child ASC';
1413 $r = $ilDB->query(
$q);
1424 for ($i = 0; $i < count($titlePath); $i++) {
1425 $pathElementFound =
false;
1426 foreach ($rows as
$row) {
1427 if ($row[
'parent'] == $parent &&
1433 $parent = $row[
'child'];
1434 $pathElementFound =
true;
1439 if (! $pathElementFound)
1471 $pathIds = $this->
getPathId($a_endnode_id, $a_startnode_id);
1474 if (count($pathIds) == 0)
1482 for ($i = 0; $i < count($pathIds); $i++)
1484 $types[] =
'integer';
1485 $data[] = $pathIds[$i];
1488 $query =
'SELECT t.depth,t.parent,t.child,d.obj_id,d.type,d.title '.
1489 'FROM '.$this->table_tree.
' t '.
1490 'JOIN '.$this->table_obj_reference.
' r ON r.ref_id = t.child '.
1491 'JOIN '.$this->table_obj_data.
' d ON d.obj_id = r.obj_id '.
1492 'WHERE '.$ilDB->in(
't.child',
$data,
false,
'integer').
' '.
1493 'ORDER BY t.depth ';
1497 $titlePath = array();
1498 while (
$row = $ilDB->fetchAssoc(
$res))
1500 $titlePath[] =
$row;
1516 $types = array(
'integer');
1517 $query =
'SELECT lft,rgt FROM '.$this->table_tree.
' '.
1518 'WHERE '.$this->tree_pk.
' = %s ';
1520 $res = $ilDB->queryF(
$query,$types,array($this->tree_id));
1521 while (
$row = $ilDB->fetchObject(
$res))
1527 $all = array_merge($lft,$rgt);
1528 $uni = array_unique($all);
1530 if (count($all) != count($uni))
1532 $message = sprintf(
'%s::checkTree(): Tree is corrupted!',
1535 $this->log->write($message,$this->log->FATAL);
1536 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1549 $query =
'SELECT * FROM '.$this->table_tree.
' '.
1550 'WHERE '.$this->tree_pk.
' = %s '.
1552 $r1 = $ilDB->queryF(
$query,array(
'integer'),array($this->tree_id));
1554 while (
$row = $ilDB->fetchAssoc($r1))
1557 if ((
$row[
"child"] == 0) && $a_no_zero_child)
1559 $this->ilErr->raiseError(get_class($this).
"::checkTreeChilds(): Tree contains child with ID 0!",$this->ilErr->WARNING);
1562 if ($this->table_obj_reference)
1565 $query =
'SELECT * FROM '.$this->table_obj_reference.
' WHERE '.$this->ref_pk.
' = %s ';
1566 $r2 = $ilDB->queryF(
$query,array(
'integer'),array(
$row[
'child']));
1569 if ($r2->numRows() == 0)
1571 $this->ilErr->raiseError(get_class($this).
"::checkTree(): No Object-to-Reference entry found for ID ".
1572 $row[
"child"].
"!",$this->ilErr->WARNING);
1574 if ($r2->numRows() > 1)
1576 $this->ilErr->raiseError(get_class($this).
"::checkTree(): More Object-to-Reference entries found for ID ".
1577 $row[
"child"].
"!",$this->ilErr->WARNING);
1581 $obj_ref = $ilDB->fetchAssoc($r2);
1583 $query =
'SELECT * FROM '.$this->table_obj_data.
' WHERE '.$this->obj_pk.
' = %s';
1584 $r3 = $ilDB->queryF(
$query,array(
'integer'),array($obj_ref[$this->obj_pk]));
1585 if ($r3->numRows() == 0)
1587 $this->ilErr->raiseError(get_class($this).
"::checkTree(): No child found for ID ".
1588 $obj_ref[$this->obj_pk].
"!",$this->ilErr->WARNING);
1590 if ($r3->numRows() > 1)
1592 $this->ilErr->raiseError(get_class($this).
"::checkTree(): More childs found for ID ".
1593 $obj_ref[$this->obj_pk].
"!",$this->ilErr->WARNING);
1600 $query =
'SELECT * FROM '.$this->table_obj_data.
' WHERE '.$this->obj_pk.
' = %s';
1601 $r2 = $ilDB->queryF(
$query,array(
'integer'),array(
$row[
'child']));
1603 if ($r2->numRows() == 0)
1605 $this->ilErr->raiseError(get_class($this).
"::checkTree(): No child found for ID ".
1606 $row[
"child"].
"!",$this->ilErr->WARNING);
1608 if ($r2->numRows() > 1)
1610 $this->ilErr->raiseError(get_class($this).
"::checkTree(): More childs found for ID ".
1611 $row[
"child"].
"!",$this->ilErr->WARNING);
1628 $query =
'SELECT MAX(depth) depth FROM '.$this->table_tree;
1632 return $row[
'depth'];
1647 $query =
'SELECT depth FROM '.$this->table_tree.
' '.
1648 'WHERE child = %s '.
1649 'AND '.$this->tree_pk.
' = %s ';
1650 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array($a_node_id,$this->tree_id));
1676 if (!isset($a_node_id))
1678 $this->ilErr->raiseError(get_class($this).
"::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
1684 $message = sprintf(
'%s::getNodeData(): No valid parameter given! $a_node_id: %s',
1688 $this->log->write($message,$this->log->FATAL);
1689 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1694 $query =
'SELECT * FROM '.$this->table_tree.
' '.
1696 'WHERE '.$this->table_tree.
'.child = %s '.
1697 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
1698 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
1700 $a_tree_pk === null ? $this->tree_id : $a_tree_pk));
1721 $data[
"desc"] = $a_row[
"description"];
1726 if (is_object($objDefinition))
1728 $translation_type = $objDefinition->getTranslationType(
$data[
"type"]);
1732 if ($translation_type ==
"sys")
1735 if (
$data[
"type"] ==
"rolf" and
$data[
"obj_id"] != ROLE_FOLDER_ID)
1737 $data[
"description"] = $lng->txt(
"obj_".
$data[
"type"].
"_local_desc").$data[
"title"].$data[
"desc"];
1738 $data[
"desc"] = $lng->txt(
"obj_".
$data[
"type"].
"_local_desc").$data[
"title"].$data[
"desc"];
1739 $data[
"title"] = $lng->txt(
"obj_".
$data[
"type"].
"_local");
1743 $data[
"title"] = $lng->txt(
"obj_".
$data[
"type"]);
1744 $data[
"description"] = $lng->txt(
"obj_".
$data[
"type"].
"_desc");
1745 $data[
"desc"] = $lng->txt(
"obj_".
$data[
"type"].
"_desc");
1749 elseif ($translation_type ==
"db")
1754 array_key_exists(
$data[
"obj_id"].
'.'.$lang_code, $this->translation_cache)) {
1757 $data[
"title"] = $this->translation_cache[
$key][
'title'];
1758 $data[
"description"] = $this->translation_cache[
$key][
'description'];
1759 $data[
"desc"] = $this->translation_cache[
$key][
'desc'];
1764 $query =
'SELECT title,description FROM object_translation '.
1765 'WHERE obj_id = %s '.
1766 'AND lang_code = %s '.
1767 'AND NOT lang_default = %s';
1769 $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer'),array(
1784 if ($this->
isCacheUsed() && count($this->translation_cache) < 1000)
1787 $this->translation_cache[
$key] = array();
1788 $this->translation_cache[
$key][
'title'] =
$data[
"title"] ;
1789 $this->translation_cache[
$key][
'description'] =
$data[
"description"];
1790 $this->translation_cache[
$key][
'desc'] =
$data[
"desc"];
1796 if(
$data[
'type'] ==
'crsr' or
$data[
'type'] ==
'catr')
1798 include_once(
'./Services/ContainerReference/classes/class.ilContainerReference.php');
1817 if (!isset($a_node_id))
1820 #$this->ilErr->raiseError(get_class($this)."::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
1824 if ($this->
isCacheUsed() && isset($this->in_tree_cache[$a_node_id]))
1826 #$GLOBALS['ilLog']->write(__METHOD__.': Using in tree cache '.$a_node_id);
1828 return $this->in_tree_cache[$a_node_id];
1831 $query =
'SELECT * FROM '.$this->table_tree.
' '.
1832 'WHERE '.$this->table_tree.
'.child = %s '.
1833 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s';
1835 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
1839 if (
$res->numRows() > 0)
1843 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true');
1844 $this->in_tree_cache[$a_node_id] =
true;
1852 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = false');
1853 $this->in_tree_cache[$a_node_id] =
false;
1870 if (!isset($a_node_id))
1873 $this->ilErr->raiseError(get_class($this).
"::getParentNodeData(): No node_id given! ",$this->ilErr->WARNING);
1876 if ($this->table_obj_reference)
1879 $innerjoin =
"JOIN ".$this->table_obj_reference.
" ON v.child=".$this->table_obj_reference.
".".$this->ref_pk.
" ".
1880 "JOIN ".$this->table_obj_data.
" ON ".$this->table_obj_reference.
".".$this->obj_pk.
"=".$this->table_obj_data.
".".$this->obj_pk.
" ";
1885 $innerjoin =
"JOIN ".$this->table_obj_data.
" ON v.child=".$this->table_obj_data.
".".$this->obj_pk.
" ";
1888 $query =
'SELECT * FROM '.$this->table_tree.
' s, '.$this->table_tree.
' v '.
1890 'WHERE s.child = %s '.
1891 'AND s.parent = v.child '.
1892 'AND s.lft > v.lft '.
1893 'AND s.rgt < v.rgt '.
1894 'AND s.'.$this->tree_pk.
' = %s '.
1895 'AND v.'.$this->tree_pk.
' = %s';
1896 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
1915 if (!isset($a_startnode_id) or !isset($a_querynode_id))
1920 $query =
'SELECT * FROM '.$this->table_tree.
' s, '.$this->table_tree.
' v '.
1921 'WHERE s.child = %s '.
1922 'AND v.child = %s '.
1923 'AND s.'.$this->tree_pk.
' = %s '.
1924 'AND v.'.$this->tree_pk.
' = %s '.
1925 'AND v.lft BETWEEN s.lft AND s.rgt '.
1926 'AND v.rgt BETWEEN s.lft AND s.rgt';
1927 $res = $ilDB->queryF(
1929 array(
'integer',
'integer',
'integer',
'integer'),
1936 return $res->numRows();
1954 $message = sprintf(
'%s::addTree(): Operation not allowed on main tree! $a_tree_if: %s $a_node_id: %s',
1958 $this->log->write($message,$this->log->FATAL);
1959 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1962 if (!isset($a_tree_id))
1964 $this->ilErr->raiseError(get_class($this).
"::addTree(): No tree_id given! ",$this->ilErr->WARNING);
1967 if ($a_node_id <= 0)
1969 $a_node_id = $a_tree_id;
1972 $query =
'INSERT INTO '.$this->table_tree.
' ('.
1973 $this->tree_pk.
', child,parent,lft,rgt,depth) '.
1975 '(%s,%s,%s,%s,%s,%s)';
1976 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer',
'integer',
'integer',
'integer',
'integer'),array(
1998 if (!isset($a_type) or (!is_string($a_type)))
2000 $this->ilErr->raiseError(get_class($this).
"::getNodeDataByType(): Type not given or wrong datatype!",$this->ilErr->WARNING);
2008 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2009 'WHERE '.$this->tree_pk.
' = %s '.
2011 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2015 while (
$row = $ilDB->fetchObject(
$res))
2021 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2023 'WHERE '.$this->table_obj_data.
'.type = %s '.
2024 'AND '.$this->table_tree.
'.lft BETWEEN %s AND %s '.
2025 'AND '.$this->table_tree.
'.rgt BETWEEN %s AND %s '.
2026 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
2027 $res = $ilDB->queryF(
$query,array(
'text',
'integer',
'integer',
'integer',
'integer',
'integer'),array(
2035 while(
$row = $ilDB->fetchAssoc(
$res))
2057 $message = sprintf(
'%s::removeTree(): Operation not allowed on main tree! $a_tree_if: %s',
2060 $this->log->write($message,$this->log->FATAL);
2061 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
2065 $this->ilErr->raiseError(get_class($this).
"::removeTree(): No tree_id given! Action aborted",$this->ilErr->MESSAGE);
2068 $query =
'DELETE FROM '.$this->table_tree.
2069 ' WHERE '.$this->tree_pk.
' = %s ';
2070 $res = $ilDB->manipulateF(
$query,array(
'integer'),array($a_tree_id));
2087 $message = sprintf(
'%s::saveSubTree(): No valid parameter given! $a_node_id: %s',
2090 $this->log->write($message,$this->log->FATAL);
2091 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
2102 #ilDB::_lockTables(array('tree' => 'WRITE',
2103 # 'object_reference' => 'WRITE'));
2108 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2109 'WHERE '.$this->tree_pk.
' = %s '.
2111 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2115 while(
$row = $ilDB->fetchObject(
$res))
2122 $query =
'SELECT child FROM '.$this->table_tree.
' '.
2123 'WHERE '.$this->tree_pk.
' = %s '.
2124 'AND lft BETWEEN %s AND %s ';
2125 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
2130 $subnodes = array();
2131 while(
$row = $ilDB->fetchAssoc(
$res))
2133 $subnodes[] =
$row[
'child'];
2136 if(!count($subnodes))
2143 $ilDB->unlockTables();
2150 foreach($subnodes as $child)
2161 $query =
'UPDATE '.$this->table_tree.
' '.
2163 'WHERE '.$this->tree_pk.
' = %s '.
2164 'AND lft BETWEEN %s AND %s ';
2165 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer',
'integer',
'integer'),array(
2173 $ilDB->unlockTables();
2185 return $this->
isSaved($a_node_id);
2196 if ($this->
isCacheUsed() && isset($this->is_saved_cache[$a_node_id]))
2199 return $this->is_saved_cache[$a_node_id];
2202 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2203 'WHERE child = %s ';
2204 $res = $ilDB->queryF(
$query,array(
'integer'),array($a_node_id));
2207 if (
$row[$this->tree_pk] < 0)
2211 $this->is_saved_cache[$a_node_id] =
true;
2219 $this->is_saved_cache[$a_node_id] =
false;
2237 if (!isset($a_parent_id))
2239 $this->ilErr->raiseError(get_class($this).
"::getSavedNodeData(): No node_id given!",$this->ilErr->WARNING);
2242 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2244 'WHERE '.$this->table_tree.
'.'.$this->tree_pk.
' < %s '.
2245 'AND '.$this->table_tree.
'.parent = %s';
2246 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2250 while(
$row = $ilDB->fetchAssoc(
$res))
2255 return $saved ? $saved : array();
2268 if (!isset($a_node_id))
2270 $this->ilErr->raiseError(get_class($this).
"::getParentId(): No node_id given! ",$this->ilErr->WARNING);
2273 $query =
'SELECT parent FROM '.$this->table_tree.
' '.
2274 'WHERE child = %s '.
2275 'AND '.$this->tree_pk.
' = %s ';
2276 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2281 return $row->parent;
2294 if (!isset($a_node_id))
2296 $this->ilErr->raiseError(get_class($this).
"::getLeftValued(): No node_id given! ",$this->ilErr->WARNING);
2299 $query =
'SELECT lft FROM '.$this->table_tree.
' '.
2300 'WHERE child = %s '.
2301 'AND '.$this->tree_pk.
' = %s ';
2302 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2319 if (!isset($a_node))
2321 $this->ilErr->raiseError(get_class($this).
"::getChildSequenceNumber(): No node_id given! ",$this->ilErr->WARNING);
2326 $query =
'SELECT count(*) cnt FROM '.$this->table_tree.
' '.
2331 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
2333 $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer',
'integer'),array(
2341 $query =
'SELECT count(*) cnt FROM '.$this->table_tree.
' '.
2345 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
2347 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
2367 $query =
'SELECT child FROM '.$this->table_tree.
' '.
2368 'WHERE parent = %s '.
2369 'AND '.$this->tree_pk.
' = %s ';
2370 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2374 $this->root_id =
$row->child;
2389 $this->root_id = $a_root_id;
2409 $this->tree_id = $a_tree_id;
2423 if (!isset($a_node_id))
2425 $this->ilErr->raiseError(get_class($this).
"::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
2429 $query =
'SELECT lft FROM '.$this->table_tree.
' '.
2430 'WHERE '.$this->table_tree.
'.child = %s '.
2431 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
2432 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2436 $curr_node = $ilDB->fetchAssoc(
$res);
2440 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2443 'AND '.$this->table_obj_data.
'.type = %s '.
2444 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
2447 $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer'),array(
2454 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2457 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
2460 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2465 if (
$res->numRows() < 1)
2487 if (!isset($a_node_id))
2489 $this->ilErr->raiseError(get_class($this).
"::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
2493 $query =
'SELECT lft FROM '.$this->table_tree.
' '.
2494 'WHERE '.$this->table_tree.
'.child = %s '.
2495 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
2496 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2500 $curr_node = $ilDB->fetchAssoc(
$res);
2504 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2507 'AND '.$this->table_obj_data.
'.type = %s '.
2508 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
2509 'ORDER BY lft DESC';
2511 $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer'),array(
2518 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2521 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
2522 'ORDER BY lft DESC';
2524 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2529 if (
$res->numRows() < 1)
2567 2 => array(
'name' => $this->table_obj_reference,
'type' =>
ilDB::LOCK_WRITE),
2569 4 => array(
'name' =>
'object_data',
'type' =>
ilDB::LOCK_WRITE,
'alias' =>
'od'),
2570 5 => array(
'name' =>
'container_reference',
'type' =>
ilDB::LOCK_WRITE,
'alias' =>
'cr')
2576 $ilDB->unlockTables();
2596 $query =
'UPDATE '.$this->table_tree.
' SET lft = %s WHERE child = %s';
2597 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer'),array(
2603 foreach ($childs as $child)
2605 $i = $this->
__renumber($child[
"child"],$i+1);
2610 if (count($childs) > 0)
2612 $i += $this->gap * 2;
2616 $query =
'UPDATE '.$this->table_tree.
' SET rgt = %s WHERE child = %s';
2617 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer'),array(
2638 array_key_exists($a_ref_id.
'.'.$a_type, $this->parent_type_cache)) {
2639 return $this->parent_type_cache[$a_ref_id.
'.'.$a_type];
2645 if ($this->
__isMainTree() && count($this->parent_type_cache) < 1000) {
2646 $this->parent_type_cache[$a_ref_id.
'.'.$a_type] =
false;
2650 $path = array_reverse($this->
getPathFull($a_ref_id));
2652 foreach($path as $node)
2654 if($node[
"type"] == $a_type)
2657 if ($this->
__isMainTree() && count($this->parent_type_cache) < 1000) {
2658 $this->parent_type_cache[$a_ref_id.
'.'.$a_type] = $node[
"child"];
2660 return $node[
"child"];
2664 if ($this->
__isMainTree() && count($this->parent_type_cache) < 1000) {
2665 $this->parent_type_cache[$a_ref_id.
'.'.$a_type] =
false;
2683 if($a_db_table ===
'tree')
2685 if($a_tree == 1 and $a_child == ROOT_FOLDER_ID)
2687 $message = sprintf(
'%s::_removeEntry(): Tried to delete root node! $a_tree: %s $a_child: %s',
2691 $ilLog->write($message,$ilLog->FATAL);
2692 $ilErr->raiseError($message,$ilErr->WARNING);
2696 $query =
'DELETE FROM '.$a_db_table.
' '.
2699 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer'),array(
2714 return $this->table_tree ===
'tree';
2730 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2733 'AND '.$this->tree_pk.
' = %s ';
2734 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
2737 $a_node[$this->tree_pk]));
2739 $counter = (int) $lft_childs = array();
2740 while(
$row = $ilDB->fetchObject(
$res))
2742 $lft_childs[
$row->child] =
$row->parent;
2747 if($counter != count($lft_childs))
2749 $message = sprintf(
'%s::__checkTree(): Duplicate entries for "child" in maintree! $a_node_id: %s',
2752 $this->log->write($message,$this->log->FATAL);
2753 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
2757 $parent_childs = array();
2769 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2770 'WHERE child = %s '.
2772 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2777 while(
$row = $ilDB->fetchObject(
$res))
2779 $parent_childs[$a_node_id] =
$row->parent;
2785 $message = sprintf(
'%s::__getSubTreeByParentRelation(): Multiple entries in maintree! $a_node_id: %s',
2788 $this->log->write($message,$this->log->FATAL);
2789 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
2793 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2794 'WHERE parent = %s ';
2795 $res = $ilDB->queryF(
$query,array(
'integer'),array($a_node_id));
2797 while(
$row = $ilDB->fetchObject(
$res))
2809 ksort($parent_childs);
2811 if(count($lft_childs) != count($parent_childs))
2813 $message = sprintf(
'%s::__validateSubtrees(): (COUNT) Tree is corrupted! Left/Right subtree does not comply .'.
2814 'with parent relation',
2816 $this->log->write($message,$this->log->FATAL);
2817 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
2820 foreach($lft_childs as
$key => $value)
2822 if($parent_childs[
$key] != $value)
2824 $message = sprintf(
'%s::__validateSubtrees(): (COMPARE) Tree is corrupted! Left/Right subtree does not comply '.
2825 'with parent relation',
2827 $this->log->write($message,$this->log->FATAL);
2828 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
2830 if(
$key == ROOT_FOLDER_ID)
2832 $message = sprintf(
'%s::__validateSubtrees(): (ROOT_FOLDER) Tree is corrupted! Tried to delete root folder',
2834 $this->log->write($message,$this->log->FATAL);
2835 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
2856 #ilDB::_lockTables(array('tree' => 'WRITE'));
2863 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2864 'WHERE ( child = %s OR child = %s ) '.
2866 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
2872 if(
$res->numRows() != 2)
2876 $ilDB->unlockTables();
2878 $this->log->write(__METHOD__.
' Objects not found in tree!',$this->log->FATAL);
2879 $this->ilErr->raiseError(
'Error moving node',$this->ilErr->WARNING);
2881 while(
$row = $ilDB->fetchObject(
$res))
2883 if(
$row->child == $a_source_id)
2885 $source_lft =
$row->lft;
2886 $source_rgt =
$row->rgt;
2887 $source_depth =
$row->depth;
2888 $source_parent =
$row->parent;
2892 $target_lft =
$row->lft;
2893 $target_rgt =
$row->rgt;
2894 $target_depth =
$row->depth;
2898 #var_dump("<pre>",$source_lft,$source_rgt,$source_depth,$target_lft,$target_rgt,$target_depth,"<pre>");
2900 if($target_lft >= $source_lft and $target_rgt <= $source_rgt)
2904 $ilDB->unlockTables();
2906 $this->log->write(__METHOD__.
' Target is child of source',$this->log->FATAL);
2907 $this->ilErr->raiseError(
'Error moving node',$this->ilErr->WARNING);
2912 $spread_diff = $source_rgt - $source_lft + 1;
2913 #var_dump("<pre>","SPREAD_DIFF: ",$spread_diff,"<pre>");
2915 $query =
'UPDATE '.$this->table_tree.
' SET '.
2916 'lft = CASE WHEN lft > %s THEN lft + %s ELSE lft END, '.
2917 'rgt = CASE WHEN rgt >= %s THEN rgt + %s ELSE rgt END '.
2919 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer',
'integer',
'integer',
'integer'),array(
2928 if($source_lft > $target_rgt)
2930 $where_offset = $spread_diff;
2931 $move_diff = $target_rgt - $source_lft - $spread_diff;
2936 $move_diff = $target_rgt - $source_lft;
2938 $depth_diff = $target_depth - $source_depth + 1;
2941 $query =
'UPDATE '.$this->table_tree.
' SET '.
2942 'parent = CASE WHEN parent = %s THEN %s ELSE parent END, '.
2945 'depth = depth + %s '.
2950 array(
'integer',
'integer',
'integer',
'integer',
'integer',
'integer',
'integer',
'integer'),
2957 $source_lft + $where_offset,
2958 $source_rgt + $where_offset,
2962 $query =
'UPDATE '.$this->table_tree.
' SET '.
2963 'lft = CASE WHEN lft >= %s THEN lft - %s ELSE lft END, '.
2964 'rgt = CASE WHEN rgt >= %s THEN rgt - %s ELSE rgt END '.
2968 array(
'integer',
'integer',
'integer',
'integer',
'integer'),
2970 $source_lft + $where_offset,
2972 $source_rgt +$where_offset,
2978 $ilDB->unlockTables();
2994 $query =
"SELECT t2.lft lft, t2.rgt rgt, t2.child child, type ".
2995 "FROM ".$this->table_tree.
" t1 ".
2996 "JOIN ".$this->table_tree.
" t2 ON (t2.lft BETWEEN t1.lft AND t1.rgt) ".
2997 "JOIN ".$this->table_obj_reference.
" obr ON t2.child = obr.ref_id ".
2998 "JOIN ".$this->table_obj_data.
" obd ON obr.obj_id = obd.obj_id ".
2999 "WHERE t1.child = ".$ilDB->quote($a_endnode_id,
'integer').
" ".
3000 "AND t1.".$this->tree_pk.
" = ".$ilDB->quote($this->tree_id,
'integer').
" ".
3001 "AND t2.".$this->tree_pk.
" = ".$ilDB->quote($this->tree_id,
'integer').
" ".
3007 $nodes[
$row->child][
'lft'] =
$row->lft;
3008 $nodes[
$row->child][
'rgt'] =
$row->rgt;
3009 $nodes[
$row->child][
'child']=
$row->child;
3010 $nodes[
$row->child][
'type'] =
$row->type;
3013 return (array) $nodes;