4 define(
"IL_LAST_NODE", -2);
5 define(
"IL_FIRST_NODE", -1);
7 include_once
'./Services/Tree/exceptions/class.ilInvalidTreeStructureException.php';
147 function ilTree($a_tree_id, $a_root_id = 0)
164 $this->lang_code =
"en";
166 if (!isset($a_tree_id) or (func_num_args() == 0) )
168 $this->ilErr->raiseError(get_class($this).
"::Constructor(): No tree_id given!",$this->ilErr->WARNING);
171 if (func_num_args() > 2)
173 $this->ilErr->raiseError(get_class($this).
"::Constructor(): Wrong parameter count!",$this->ilErr->WARNING);
180 if (empty($a_root_id))
182 $a_root_id = ROOT_FOLDER_ID;
185 $this->tree_id = $a_tree_id;
186 $this->root_id = $a_root_id;
187 $this->table_tree =
'tree';
188 $this->table_obj_data =
'object_data';
189 $this->table_obj_reference =
'object_reference';
190 $this->ref_pk =
'ref_id';
191 $this->obj_pk =
'obj_id';
192 $this->tree_pk =
'tree';
194 $this->use_cache =
true;
197 $this->translation_cache = array();
198 $this->parent_type_cache = array();
216 if(!is_object(
$GLOBALS[
'ilSetting']) or
$GLOBALS[
'ilSetting']->getModule() !=
'common')
218 include_once
'./Services/Administration/classes/class.ilSetting.php';
228 if($setting->get(
'main_tree_impl',
'ns') ==
'ns')
230 #$GLOBALS['ilLog']->write(__METHOD__.': Using nested set.');
231 include_once
'./Services/Tree/classes/class.ilNestedSetTree.php';
236 #$GLOBALS['ilLog']->write(__METHOD__.': Using materialized path.');
237 include_once
'./Services/Tree/classes/class.ilMaterializedPathTree.php';
243 #$GLOBALS['ilLog']->write(__METHOD__.': Using netsted set for non main tree.');
244 include_once
'./Services/Tree/classes/class.ilNestedSetTree.php';
263 $this->use_cache = $a_use;
302 if (!is_object($ilUser))
304 $this->lang_code =
"en";
308 $this->lang_code = $ilUser->getCurrentLanguage();
360 $this->in_tree_cache = array();
378 function setTableNames($a_table_tree,$a_table_obj_data,$a_table_obj_reference =
"")
380 if (!isset($a_table_tree) or !isset($a_table_obj_data))
382 $this->ilErr->raiseError(get_class($this).
"::setTableNames(): Missing parameter! ".
383 "tree table: ".$a_table_tree.
" object data table: ".$a_table_obj_data,$this->ilErr->WARNING);
386 $this->table_tree = $a_table_tree;
387 $this->table_obj_data = $a_table_obj_data;
388 $this->table_obj_reference = $a_table_obj_reference;
403 if (!isset($a_column_name))
405 $this->ilErr->raiseError(get_class($this).
"::setReferenceTablePK(): No column name given!",$this->ilErr->WARNING);
408 $this->ref_pk = $a_column_name;
420 if (!isset($a_column_name))
422 $this->ilErr->raiseError(get_class($this).
"::setObjectTablePK(): No column name given!",$this->ilErr->WARNING);
425 $this->obj_pk = $a_column_name;
437 if (!isset($a_column_name))
439 $this->ilErr->raiseError(get_class($this).
"::setTreeTablePK(): No column name given!",$this->ilErr->WARNING);
442 $this->tree_pk = $a_column_name;
453 if ($this->table_obj_reference)
456 return "JOIN ".$this->table_obj_reference.
" ON ".$this->table_tree.
".child=".$this->table_obj_reference.
".".$this->ref_pk.
" ".
457 "JOIN ".$this->table_obj_data.
" ON ".$this->table_obj_reference.
".".$this->obj_pk.
"=".$this->table_obj_data.
".".$this->obj_pk.
" ";
462 return "JOIN ".$this->table_obj_data.
" ON ".$this->table_tree.
".child=".$this->table_obj_data.
".".$this->obj_pk.
" ";
498 function getChilds($a_node_id, $a_order =
"", $a_direction =
"ASC")
502 if (!isset($a_node_id))
504 $message = get_class($this).
"::getChilds(): No node_id given!";
505 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
518 if (!empty($a_order))
520 $order_clause =
"ORDER BY ".$a_order.
" ".$a_direction;
524 $order_clause =
"ORDER BY ".$this->table_tree.
".lft";
528 $query = sprintf(
'SELECT * FROM '.$this->table_tree.
' '.
530 "WHERE parent = %s " .
531 "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
533 $ilDB->quote($a_node_id,
'integer'),
534 $ilDB->quote($this->tree_id,
'integer'));
538 if(!$count = $res->numRows())
545 while($r = $ilDB->fetchAssoc($res))
548 $obj_ids[] = $r[
"obj_id"];
553 is_object($ilUser) && $this->lang_code == $ilUser->getLanguage() && !$this->oc_preloaded[$a_node_id])
556 $ilObjDataCache->preloadObjectCache($obj_ids, $this->lang_code);
558 $this->oc_preloaded[$a_node_id] =
true;
561 foreach ($rows as
$row)
568 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$row['child'].' = true');
569 $this->in_tree_cache[$row[
'child']] = $row[
'tree'] == 1;
572 $childs[$count - 1][
"last"] =
true;
587 $childs = $this->
getChilds($a_node,$a_order,$a_direction);
589 foreach($childs as $child)
591 if(!in_array($child[
"type"],$a_filter))
593 $filtered[] = $child;
596 return $filtered ? $filtered : array();
611 if (!isset($a_node_id) or !isset($a_type))
613 $message = get_class($this).
"::getChildsByType(): Missing parameter! node_id:".$a_node_id.
" type:".$a_type;
614 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
617 if ($a_type==
'rolf' && $this->table_obj_reference) {
621 $ilDB->setLimit(1,0);
622 $query = sprintf(
"SELECT * FROM ".$this->table_tree.
" ".
624 "WHERE parent = %s ".
625 "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
626 "AND ".$this->table_obj_data.
".type = %s ",
627 $ilDB->quote($a_node_id,
'integer'),
628 $ilDB->quote($this->tree_id,
'integer'),
629 $ilDB->quote($a_type,
'text'));
631 $query = sprintf(
"SELECT * FROM ".$this->table_tree.
" ".
633 "WHERE parent = %s ".
634 "AND ".$this->table_tree.
".".$this->tree_pk.
" = %s ".
635 "AND ".$this->table_obj_data.
".type = %s ".
636 "ORDER BY ".$this->table_tree.
".lft",
637 $ilDB->quote($a_node_id,
'integer'),
638 $ilDB->quote($this->tree_id,
'integer'),
639 $ilDB->quote($a_type,
'text'));
645 while(
$row = $ilDB->fetchAssoc(
$res))
650 return $childs ? $childs : array();
665 if (!isset($a_node_id) or !$a_types)
667 $message = get_class($this).
"::getChildsByType(): Missing parameter! node_id:".$a_node_id.
" type:".$a_types;
668 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
674 $filter =
'AND '.$this->table_obj_data.
'.type IN('.implode(
',',
ilUtil::quoteArray($a_types)).
') ';
678 if (!empty($a_order))
680 $order_clause =
"ORDER BY ".$a_order.
" ".$a_direction;
684 $order_clause =
"ORDER BY ".$this->table_tree.
".lft";
687 $query =
'SELECT * FROM '.$this->table_tree.
' '.
689 'WHERE parent = '.$ilDB->quote($a_node_id,
'integer').
' '.
690 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = '.$ilDB->quote($this->tree_id,
'integer').
' '.
695 while(
$row = $ilDB->fetchAssoc(
$res))
700 return $childs ? $childs : array();
718 if($a_node_id <= 1 or $a_parent_id <= 0)
721 $message = sprintf(
'%s::insertNode(): Invalid parameters! $a_node_id: %s $a_parent_id: %s',
725 $this->log->write($message,$this->log->FATAL);
726 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
731 if (!isset($a_node_id) or !isset($a_parent_id))
734 $this->ilErr->raiseError(get_class($this).
"::insertNode(): Missing parameter! ".
735 "node_id: ".$a_node_id.
" parent_id: ".$a_parent_id,$this->ilErr->WARNING);
739 $this->ilErr->raiseError(get_class($this).
"::insertNode(): Node ".$a_node_id.
" already in tree ".
740 $this->table_tree.
"!",$this->ilErr->WARNING);
745 $this->in_tree_cache[$a_node_id] =
true;
748 if ($a_reset_deletion_date)
774 if($depth and $subnode[
'depth'] > $depth)
778 if(!$first and in_array($subnode[
'type'],$a_filter))
780 $depth = $subnode[
'depth'];
786 $filtered[] = $subnode;
788 return $filtered ? $filtered : array();
811 function getSubTree($a_node,$a_with_data =
true, $a_type =
"")
815 if (!is_array($a_node))
818 throw new InvalidArgumentException(__METHOD__.
': wrong datatype for node data given');
836 while(
$row = $ilDB->fetchAssoc(
$res))
844 $subtree[] =
$row[
'child'];
847 if($this->
__isMainTree() || $this->table_tree ==
"lm_tree")
849 $this->in_tree_cache[
$row[
'child']] =
true;
852 return $subtree ? $subtree : array();
865 $a_filter = $a_filter ? $a_filter : array();
867 foreach($this->getSubtree($this->
getNodeData($a_node)) as $node)
869 if(in_array($node[
"type"],$a_filter))
873 $types[
"$node[type]"] = $node[
"type"];
875 return $types ? $types : array();
888 $GLOBALS[
'ilLog']->write(__METHOD__.
': Delete tree with node '. $a_node);
890 if (!is_array($a_node))
893 throw new InvalidArgumentException(__METHOD__.
': Wrong datatype for node data!');
896 $GLOBALS[
'ilLog']->write(__METHOD__.
': '. $this->tree_pk);
927 $pathIds =& $this->
getPathId($a_endnode_id, $a_startnode_id);
933 if (count($pathIds) == 0)
938 $inClause =
'child IN (';
939 for ($i=0; $i < count($pathIds); $i++)
941 if ($i > 0) $inClause .=
',';
942 $inClause .= $ilDB->quote($pathIds[$i],
'integer');
947 'FROM '.$this->table_tree.
' '.
949 'WHERE '.$inClause.
' '.
950 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = '.$this->
ilDB->
quote($this->tree_id,
'integer').
' '.
952 $r = $ilDB->query($q);
962 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$row['child']);
963 $this->in_tree_cache[
$row[
'child']] = $row[
'tree'] == 1;
985 $res = $ilDB->query(
'SELECT t.depth, t.parent, t.child '.
986 'FROM '.$this->table_tree.
' t '.
987 'WHERE '.$ilDB->in(
"child", $a_node_ids,
false,
"integer").
988 'AND '.$this->tree_pk.
' = '.$ilDB->quote($this->tree_id,
"integer"));
989 while (
$row = $ilDB->fetchAssoc(
$res))
991 $this->depth_cache[
$row[
"child"]] = $row[
"depth"];
992 $this->parent_cache[$row[
"child"]] = $row[
"parent"];
1005 public function getPathId($a_endnode_id, $a_startnode_id = 0)
1010 throw new InvalidArgumentException(__METHOD__.
': No endnode given!');
1014 if ($this->
isCacheUsed() && isset($this->path_id_cache[$a_endnode_id][$a_startnode_id]))
1017 return $this->path_id_cache[$a_endnode_id][$a_startnode_id];
1025 $this->path_id_cache[$a_endnode_id][$a_startnode_id] = $pathIds;
1054 if ($titlePath == null || count($titlePath) == 0)
1056 if ($a_startnode_id == 0)
1067 if ($a_startnode_id != null && $a_startnode_id != 0)
1071 $parent = $a_startnode_id;
1076 $nodePath = array();
1084 require_once(
'include/Unicode/UtfNormal.php');
1085 include_once
'./Services/Utilities/classes/class.ilStr.php';
1086 $inClause =
'd.title IN (';
1087 for ($i=0; $i < count($titlePath); $i++)
1090 if ($i > 0) $inClause .=
',';
1091 $inClause .= $ilDB->quote($titlePath[$i],
'text');
1096 if ($this->table_obj_reference)
1098 $joinClause =
'JOIN '.$this->table_obj_reference.
' r ON t.child = r.'.$this->ref_pk.
' '.
1099 'JOIN '.$this->table_obj_data.
' d ON r.'.$this->obj_pk.
' = d.'.
$this->obj_pk;
1103 $joinClause =
'JOIN '.$this->table_obj_data.
' d ON t.child = d.'.
$this->obj_pk;
1110 $q =
'SELECT t.depth, t.parent, t.child, d.'.$this->obj_pk.
' obj_id, d.type, d.title '.
1111 'FROM '.$this->table_tree.
' t '.
1113 'WHERE '.$inClause.
' '.
1114 'AND t.depth <= '.(count($titlePath)+count($nodePath)).
' '.
1116 'ORDER BY t.depth, t.child ASC';
1117 $r = $ilDB->query($q);
1128 for ($i = 0; $i < count($titlePath); $i++) {
1129 $pathElementFound =
false;
1130 foreach ($rows as
$row) {
1131 if ($row[
'parent'] == $parent &&
1137 $parent = $row[
'child'];
1138 $pathElementFound =
true;
1143 if (! $pathElementFound)
1175 $pathIds = $this->
getPathId($a_endnode_id, $a_startnode_id);
1178 if (count($pathIds) == 0)
1186 for ($i = 0; $i < count($pathIds); $i++)
1188 $types[] =
'integer';
1189 $data[] = $pathIds[$i];
1192 $query =
'SELECT t.depth,t.parent,t.child,d.obj_id,d.type,d.title '.
1193 'FROM '.$this->table_tree.
' t '.
1194 'JOIN '.$this->table_obj_reference.
' r ON r.ref_id = t.child '.
1195 'JOIN '.$this->table_obj_data.
' d ON d.obj_id = r.obj_id '.
1196 'WHERE '.$ilDB->in(
't.child',$data,
false,
'integer').
' '.
1197 'ORDER BY t.depth ';
1201 $titlePath = array();
1202 while (
$row = $ilDB->fetchAssoc(
$res))
1204 $titlePath[] =
$row;
1220 $types = array(
'integer');
1221 $query =
'SELECT lft,rgt FROM '.$this->table_tree.
' '.
1222 'WHERE '.$this->tree_pk.
' = %s ';
1224 $res = $ilDB->queryF(
$query,$types,array($this->tree_id));
1225 while (
$row = $ilDB->fetchObject(
$res))
1231 $all = array_merge($lft,$rgt);
1232 $uni = array_unique($all);
1234 if (count($all) != count($uni))
1236 $message = sprintf(
'%s::checkTree(): Tree is corrupted!',
1239 $this->log->write($message,$this->log->FATAL);
1240 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1253 $query =
'SELECT * FROM '.$this->table_tree.
' '.
1254 'WHERE '.$this->tree_pk.
' = %s '.
1256 $r1 = $ilDB->queryF(
$query,array(
'integer'),array($this->tree_id));
1258 while (
$row = $ilDB->fetchAssoc($r1))
1261 if ((
$row[
"child"] == 0) && $a_no_zero_child)
1263 $this->ilErr->raiseError(get_class($this).
"::checkTreeChilds(): Tree contains child with ID 0!",$this->ilErr->WARNING);
1266 if ($this->table_obj_reference)
1269 $query =
'SELECT * FROM '.$this->table_obj_reference.
' WHERE '.$this->ref_pk.
' = %s ';
1270 $r2 = $ilDB->queryF(
$query,array(
'integer'),array(
$row[
'child']));
1273 if ($r2->numRows() == 0)
1275 $this->ilErr->raiseError(get_class($this).
"::checkTree(): No Object-to-Reference entry found for ID ".
1276 $row[
"child"].
"!",$this->ilErr->WARNING);
1278 if ($r2->numRows() > 1)
1280 $this->ilErr->raiseError(get_class($this).
"::checkTree(): More Object-to-Reference entries found for ID ".
1281 $row[
"child"].
"!",$this->ilErr->WARNING);
1285 $obj_ref = $ilDB->fetchAssoc($r2);
1287 $query =
'SELECT * FROM '.$this->table_obj_data.
' WHERE '.$this->obj_pk.
' = %s';
1288 $r3 = $ilDB->queryF(
$query,array(
'integer'),array($obj_ref[$this->obj_pk]));
1289 if ($r3->numRows() == 0)
1291 $this->ilErr->raiseError(get_class($this).
"::checkTree(): No child found for ID ".
1292 $obj_ref[$this->obj_pk].
"!",$this->ilErr->WARNING);
1294 if ($r3->numRows() > 1)
1296 $this->ilErr->raiseError(get_class($this).
"::checkTree(): More childs found for ID ".
1297 $obj_ref[$this->obj_pk].
"!",$this->ilErr->WARNING);
1304 $query =
'SELECT * FROM '.$this->table_obj_data.
' WHERE '.$this->obj_pk.
' = %s';
1305 $r2 = $ilDB->queryF(
$query,array(
'integer'),array(
$row[
'child']));
1307 if ($r2->numRows() == 0)
1309 $this->ilErr->raiseError(get_class($this).
"::checkTree(): No child found for ID ".
1310 $row[
"child"].
"!",$this->ilErr->WARNING);
1312 if ($r2->numRows() > 1)
1314 $this->ilErr->raiseError(get_class($this).
"::checkTree(): More childs found for ID ".
1315 $row[
"child"].
"!",$this->ilErr->WARNING);
1332 $query =
'SELECT MAX(depth) depth FROM '.$this->table_tree;
1336 return $row[
'depth'];
1351 $query =
'SELECT depth FROM '.$this->table_tree.
' '.
1352 'WHERE child = %s '.
1353 'AND '.$this->tree_pk.
' = %s ';
1354 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array($a_node_id,$this->tree_id));
1379 throw new InvalidArgumentException(
'Missing or empty parameter $a_node_id: '. $a_node_id);
1382 $query =
'SELECT * FROM '.$this->table_tree.
' '.
1383 'WHERE child = '.$ilDB->quote($a_node_id,
'integer');
1407 if (!isset($a_node_id))
1410 $this->ilErr->raiseError(get_class($this).
"::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
1416 $message = sprintf(
'%s::getNodeData(): No valid parameter given! $a_node_id: %s',
1420 $this->log->write($message,$this->log->FATAL);
1421 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1426 $query =
'SELECT * FROM '.$this->table_tree.
' '.
1428 'WHERE '.$this->table_tree.
'.child = %s '.
1429 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
1430 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
1432 $a_tree_pk === null ? $this->tree_id : $a_tree_pk));
1453 $data[
"desc"] = $a_row[
"description"];
1458 if (is_object($objDefinition))
1460 $translation_type = $objDefinition->getTranslationType($data[
"type"]);
1464 if ($translation_type ==
"sys")
1467 if ($data[
"type"] ==
"rolf" and $data[
"obj_id"] != ROLE_FOLDER_ID)
1469 $data[
"description"] = $lng->txt(
"obj_".$data[
"type"].
"_local_desc").$data[
"title"].$data[
"desc"];
1470 $data[
"desc"] = $lng->txt(
"obj_".$data[
"type"].
"_local_desc").$data[
"title"].$data[
"desc"];
1471 $data[
"title"] = $lng->txt(
"obj_".$data[
"type"].
"_local");
1475 $data[
"title"] = $lng->txt(
"obj_".$data[
"type"]);
1476 $data[
"description"] = $lng->txt(
"obj_".$data[
"type"].
"_desc");
1477 $data[
"desc"] = $lng->txt(
"obj_".$data[
"type"].
"_desc");
1481 elseif ($translation_type ==
"db")
1486 array_key_exists($data[
"obj_id"].
'.'.$lang_code, $this->translation_cache)) {
1488 $key = $data[
"obj_id"].
'.'.$lang_code;
1489 $data[
"title"] = $this->translation_cache[$key][
'title'];
1490 $data[
"description"] = $this->translation_cache[$key][
'description'];
1491 $data[
"desc"] = $this->translation_cache[$key][
'desc'];
1497 $query =
'SELECT title,description FROM object_translation '.
1498 'WHERE obj_id = %s '.
1499 'AND lang_code = %s '.
1500 'AND NOT lang_default = %s';
1502 $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer'),array(
1510 $data[
"title"] =
$row->title;
1512 $data[
"desc"] =
$row->description;
1517 if ($this->
isCacheUsed() && count($this->translation_cache) < 1000)
1519 $key = $data[
"obj_id"].
'.'.$lang_code;
1520 $this->translation_cache[$key] = array();
1521 $this->translation_cache[$key][
'title'] = $data[
"title"] ;
1522 $this->translation_cache[$key][
'description'] = $data[
"description"];
1523 $this->translation_cache[$key][
'desc'] = $data[
"desc"];
1529 if($data[
'type'] ==
'crsr' or $data[
'type'] ==
'catr')
1531 include_once(
'./Services/ContainerReference/classes/class.ilContainerReference.php');
1535 return $data ? $data : array();
1545 global $ilObjDataCache;
1547 if ($this->
isCacheUsed() && is_array($a_obj_ids) && is_object($ilObjDataCache))
1549 foreach ($a_obj_ids as $id)
1551 $this->translation_cache[$id.
'.'][
'title'] = $ilObjDataCache->lookupTitle($id);
1552 $this->translation_cache[$id.
'.'][
'description'] = $ilObjDataCache->lookupDescription($id);;
1553 $this->translation_cache[$id.
'.'][
'desc'] =
1554 $this->translation_cache[$id.
'.'][
'description'];
1571 if (!isset($a_node_id))
1574 #$this->ilErr->raiseError(get_class($this)."::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
1577 if ($this->
isCacheUsed() && isset($this->in_tree_cache[$a_node_id]))
1579 #$GLOBALS['ilLog']->write(__METHOD__.': Using in tree cache '.$a_node_id);
1581 return $this->in_tree_cache[$a_node_id];
1584 $query =
'SELECT * FROM '.$this->table_tree.
' '.
1585 'WHERE '.$this->table_tree.
'.child = %s '.
1586 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s';
1588 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
1592 if (
$res->numRows() > 0)
1596 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true');
1597 $this->in_tree_cache[$a_node_id] =
true;
1605 #$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = false');
1606 $this->in_tree_cache[$a_node_id] =
false;
1624 if (!isset($a_node_id))
1627 throw new InvalidArgumentException(__METHOD__.
': No node_id given!');
1630 if ($this->table_obj_reference)
1633 $innerjoin =
"JOIN ".$this->table_obj_reference.
" ON v.child=".$this->table_obj_reference.
".".$this->ref_pk.
" ".
1634 "JOIN ".$this->table_obj_data.
" ON ".$this->table_obj_reference.
".".$this->obj_pk.
"=".$this->table_obj_data.
".".$this->obj_pk.
" ";
1639 $innerjoin =
"JOIN ".$this->table_obj_data.
" ON v.child=".$this->table_obj_data.
".".$this->obj_pk.
" ";
1642 $query =
'SELECT * FROM '.$this->table_tree.
' s, '.$this->table_tree.
' v '.
1644 'WHERE s.child = %s '.
1645 'AND s.parent = v.child '.
1646 'AND s.'.$this->tree_pk.
' = %s '.
1647 'AND v.'.$this->tree_pk.
' = %s';
1648 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
1683 $message = sprintf(
'%s::addTree(): Operation not allowed on main tree! $a_tree_if: %s $a_node_id: %s',
1687 $this->log->write($message,$this->log->FATAL);
1688 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
1691 if (!isset($a_tree_id))
1693 $this->ilErr->raiseError(get_class($this).
"::addTree(): No tree_id given! ",$this->ilErr->WARNING);
1696 if ($a_node_id <= 0)
1698 $a_node_id = $a_tree_id;
1701 $query =
'INSERT INTO '.$this->table_tree.
' ('.
1702 $this->tree_pk.
', child,parent,lft,rgt,depth) '.
1704 '(%s,%s,%s,%s,%s,%s)';
1705 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer',
'integer',
'integer',
'integer',
'integer'),array(
1728 if(!isset($a_type) or (!is_string($a_type)))
1731 throw new InvalidArgumentException(
'Type not given or wrong datatype');
1734 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
1736 'WHERE ' . $this->table_obj_data .
'.type = ' . $this->
ilDB->
quote($a_type,
'text').
1737 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = ' . $this->
ilDB->
quote($this->tree_id,
'integer');
1741 while(
$row = $ilDB->fetchAssoc(
$res))
1764 throw new InvalidArgumentException(
'Operation not allowed on main tree');
1769 throw new InvalidArgumentException(
'Missing parameter tree id');
1772 $query =
'DELETE FROM '.$this->table_tree.
1773 ' WHERE '.$this->tree_pk.
' = %s ';
1774 $ilDB->manipulateF(
$query,array(
'integer'),array($a_tree_id));
1786 return $this->
saveSubTree($a_node_id, $a_set_deleted);
1806 throw new InvalidArgumentException(
'No valid parameter given! $a_node_id: '.$a_node_id);
1821 $subnodes = array();
1824 $subnodes[] =
$row[
'child'];
1827 if(!count($subnodes))
1833 $ilDB->unlockTables();
1840 include_once
'./Services/Object/classes/class.ilObject.php';
1849 $ilDB->unlockTables();
1862 return $this->
isSaved($a_node_id);
1875 if ($this->
isCacheUsed() && isset($this->is_saved_cache[$a_node_id]))
1878 return $this->is_saved_cache[$a_node_id];
1881 $query =
'SELECT '.$this->tree_pk.
' FROM '.$this->table_tree.
' '.
1882 'WHERE child = %s ';
1883 $res = $ilDB->queryF(
$query,array(
'integer'),array($a_node_id));
1886 if (
$row[$this->tree_pk] < 0)
1890 $this->is_saved_cache[$a_node_id] =
true;
1898 $this->is_saved_cache[$a_node_id] =
false;
1914 if (!is_array($a_node_ids) || !$this->
isCacheUsed())
1919 $query =
'SELECT '.$this->tree_pk.
', child FROM '.$this->table_tree.
' '.
1920 'WHERE '.$ilDB->in(
"child", $a_node_ids,
false,
"integer");
1923 while (
$row = $ilDB->fetchAssoc(
$res))
1925 if (
$row[$this->tree_pk] < 0)
1929 $this->is_saved_cache[
$row[
"child"]] =
true;
1936 $this->is_saved_cache[
$row[
"child"]] =
false;
1953 if (!isset($a_parent_id))
1955 $this->ilErr->raiseError(get_class($this).
"::getSavedNodeData(): No node_id given!",$this->ilErr->WARNING);
1958 $query =
'SELECT * FROM '.$this->table_tree.
' '.
1960 'WHERE '.$this->table_tree.
'.'.$this->tree_pk.
' < %s '.
1961 'AND '.$this->table_tree.
'.parent = %s';
1962 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
1966 while(
$row = $ilDB->fetchAssoc(
$res))
1971 return $saved ? $saved : array();
1984 $query =
'SELECT '.$this->table_obj_data.
'.obj_id FROM '.$this->table_tree.
' '.
1986 'WHERE '.$this->table_tree.
'.'.$this->tree_pk.
' < '.$ilDB->quote(0,
'integer').
' '.
1987 'AND '.$ilDB->in($this->table_obj_data.
'.obj_id', $a_obj_ids,
'',
'integer');
1989 while(
$row = $ilDB->fetchAssoc(
$res))
1991 $saved[] =
$row[
'obj_id'];
1994 return $saved ? $saved : array();
2007 if (!isset($a_node_id))
2009 $this->ilErr->raiseError(get_class($this).
"::getParentId(): No node_id given! ",$this->ilErr->WARNING);
2012 $query =
'SELECT parent FROM '.$this->table_tree.
' '.
2013 'WHERE child = %s '.
2014 'AND '.$this->tree_pk.
' = %s ';
2015 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2020 return $row->parent;
2033 if (!isset($a_node_id))
2035 $this->ilErr->raiseError(get_class($this).
"::getLeftValued(): No node_id given! ",$this->ilErr->WARNING);
2038 $query =
'SELECT lft FROM '.$this->table_tree.
' '.
2039 'WHERE child = %s '.
2040 'AND '.$this->tree_pk.
' = %s ';
2041 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2058 if (!isset($a_node))
2060 $this->ilErr->raiseError(get_class($this).
"::getChildSequenceNumber(): No node_id given! ",$this->ilErr->WARNING);
2065 $query =
'SELECT count(*) cnt FROM '.$this->table_tree.
' '.
2070 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
2072 $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer',
'integer'),array(
2080 $query =
'SELECT count(*) cnt FROM '.$this->table_tree.
' '.
2084 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
2086 $res = $ilDB->queryF(
$query,array(
'integer',
'integer',
'integer'),array(
2106 $query =
'SELECT child FROM '.$this->table_tree.
' '.
2107 'WHERE parent = %s '.
2108 'AND '.$this->tree_pk.
' = %s ';
2109 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2113 $this->root_id =
$row->child;
2128 $this->root_id = $a_root_id;
2148 $this->tree_id = $a_tree_id;
2162 if (!isset($a_node_id))
2164 $this->ilErr->raiseError(get_class($this).
"::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
2168 $query =
'SELECT lft FROM '.$this->table_tree.
' '.
2169 'WHERE '.$this->table_tree.
'.child = %s '.
2170 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
2171 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2174 $curr_node = $ilDB->fetchAssoc(
$res);
2178 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2181 'AND '.$this->table_obj_data.
'.type = %s '.
2182 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
2185 $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer'),array(
2192 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2195 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
2198 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2203 if (
$res->numRows() < 1)
2225 if (!isset($a_node_id))
2227 $this->ilErr->raiseError(get_class($this).
"::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
2231 $query =
'SELECT lft FROM '.$this->table_tree.
' '.
2232 'WHERE '.$this->table_tree.
'.child = %s '.
2233 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s ';
2234 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2238 $curr_node = $ilDB->fetchAssoc(
$res);
2242 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2245 'AND '.$this->table_obj_data.
'.type = %s '.
2246 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
2247 'ORDER BY lft DESC';
2249 $res = $ilDB->queryF(
$query,array(
'integer',
'text',
'integer'),array(
2256 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2259 'AND '.$this->table_tree.
'.'.$this->tree_pk.
' = %s '.
2260 'ORDER BY lft DESC';
2262 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2267 if (
$res->numRows() < 1)
2305 2 => array(
'name' => $this->table_obj_reference,
'type' =>
ilDB::LOCK_WRITE),
2307 4 => array(
'name' =>
'object_data',
'type' =>
ilDB::LOCK_WRITE,
'alias' =>
'od'),
2308 5 => array(
'name' =>
'container_reference',
'type' =>
ilDB::LOCK_WRITE,
'alias' =>
'cr')
2314 $ilDB->unlockTables();
2334 $query =
'UPDATE '.$this->table_tree.
' SET lft = %s WHERE child = %s';
2335 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer'),array(
2341 foreach ($childs as $child)
2343 $i = $this->
__renumber($child[
"child"],$i+1);
2348 if (count($childs) > 0)
2350 $i += $this->gap * 2;
2354 $query =
'UPDATE '.$this->table_tree.
' SET rgt = %s WHERE child = %s';
2355 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer'),array(
2375 $cache_key = $a_ref_id.
'.'.$a_type.
'.'.((int)$a_exclude_source_check);
2379 array_key_exists($cache_key, $this->parent_type_cache))
2381 return $this->parent_type_cache[$cache_key];
2385 $do_cache = ($this->
__isMainTree() && count($this->parent_type_cache) < 1000);
2392 $this->parent_type_cache[$cache_key] =
false;
2400 if($a_exclude_source_check)
2405 foreach(
$path as $node)
2408 if($node[
"type"] == $a_type)
2412 $this->parent_type_cache[$cache_key] = $node[
"child"];
2414 return $node[
"child"];
2420 $this->parent_type_cache[$cache_key] =
false;
2438 if($a_db_table ===
'tree')
2440 if($a_tree == 1 and $a_child == ROOT_FOLDER_ID)
2442 $message = sprintf(
'%s::_removeEntry(): Tried to delete root node! $a_tree: %s $a_child: %s',
2446 $ilLog->write($message,$ilLog->FATAL);
2447 $ilErr->raiseError($message,$ilErr->WARNING);
2451 $query =
'DELETE FROM '.$a_db_table.
' '.
2454 $res = $ilDB->manipulateF(
$query,array(
'integer',
'integer'),array(
2468 return $this->table_tree ===
'tree';
2490 $counter = (int) $lft_childs = array();
2491 while(
$row = $ilDB->fetchObject(
$res))
2493 $lft_childs[
$row->child] =
$row->parent;
2498 if($counter != count($lft_childs))
2500 $message = sprintf(
'%s::__checkTree(): Duplicate entries for "child" in maintree! $a_node_id: %s',
2503 $this->log->write($message,$this->log->FATAL);
2504 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
2508 $parent_childs = array();
2528 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2529 'WHERE child = %s '.
2531 $res = $ilDB->queryF(
$query,array(
'integer',
'integer'),array(
2536 while(
$row = $ilDB->fetchObject(
$res))
2538 $parent_childs[$a_node_id] =
$row->parent;
2544 $message = sprintf(
'%s::__getSubTreeByParentRelation(): Multiple entries in maintree! $a_node_id: %s',
2547 $this->log->write($message,$this->log->FATAL);
2548 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
2552 $query =
'SELECT * FROM '.$this->table_tree.
' '.
2553 'WHERE parent = %s ';
2554 $res = $ilDB->queryF(
$query,array(
'integer'),array($a_node_id));
2556 while(
$row = $ilDB->fetchObject(
$res))
2568 ksort($parent_childs);
2570 $GLOBALS[
'ilLog']->write(__METHOD__.
': left childs '. print_r($lft_childs,
true));
2571 $GLOBALS[
'ilLog']->write(__METHOD__.
': parent childs '. print_r($parent_childs,
true));
2573 if(count($lft_childs) != count($parent_childs))
2575 $message = sprintf(
'%s::__validateSubtrees(): (COUNT) Tree is corrupted! Left/Right subtree does not comply .'.
2576 'with parent relation',
2578 $this->log->write($message,$this->log->FATAL);
2579 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
2583 foreach($lft_childs as $key => $value)
2585 if($parent_childs[$key] != $value)
2587 $message = sprintf(
'%s::__validateSubtrees(): (COMPARE) Tree is corrupted! Left/Right subtree does not comply '.
2588 'with parent relation',
2590 $this->log->write($message,$this->log->FATAL);
2591 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
2593 if($key == ROOT_FOLDER_ID)
2595 $message = sprintf(
'%s::__validateSubtrees(): (ROOT_FOLDER) Tree is corrupted! Tried to delete root folder',
2597 $this->log->write($message,$this->log->FATAL);
2598 $this->ilErr->raiseError($message,$this->ilErr->WARNING);
2613 public function moveTree($a_source_id, $a_target_id, $a_location = self::POS_LAST_NODE)
2616 $GLOBALS[
'ilAppEventHandler']->raise(
2620 'tree' => $this->table_tree,
2621 'source_id' => $a_source_id,
2622 'target_id' => $a_target_id)
2650 public function getSubTreeQuery($a_node_id,$a_fields = array(), $a_types =
'', $a_force_join_reference =
false)
2655 $a_force_join_reference,