4 define(
"IL_LAST_NODE", -2);
5 define(
"IL_FIRST_NODE", -1);
7 include_once
'./Services/Tree/exceptions/class.ilInvalidTreeStructureException.php';
152 $ilDB = $DIC[
'ilDB'];
157 $this->lang_code =
"en";
162 if (!isset($a_tree_id)
or (func_num_args() == 0)) {
163 $this->log->error(
"No tree_id given!");
168 if (func_num_args() > 2) {
169 $this->log->error(
"Wrong parameter count!");
174 if (empty($a_root_id)) {
175 $a_root_id = ROOT_FOLDER_ID;
178 $this->tree_id = $a_tree_id;
179 $this->root_id = $a_root_id;
180 $this->table_tree =
'tree';
181 $this->table_obj_data =
'object_data';
182 $this->table_obj_reference =
'object_reference';
183 $this->ref_pk =
'ref_id';
184 $this->obj_pk =
'obj_id';
185 $this->tree_pk =
'tree';
187 $this->use_cache =
true;
190 $this->translation_cache = array();
191 $this->parent_type_cache = array();
208 if (!$DIC->isDependencyAvailable(
'settings') || $DIC->settings()->getModule() !=
'common') {
209 include_once
'./Services/Administration/classes/class.ilSetting.php';
212 $setting = $DIC->settings();
216 if ($setting->get(
'main_tree_impl',
'ns') ==
'ns') {
217 #$GLOBALS['DIC']['ilLog']->write(__METHOD__.': Using nested set.'); 218 include_once
'./Services/Tree/classes/class.ilNestedSetTree.php';
221 #$GLOBALS['DIC']['ilLog']->write(__METHOD__.': Using materialized path.'); 222 include_once
'./Services/Tree/classes/class.ilMaterializedPathTree.php';
226 #$GLOBALS['DIC']['ilLog']->write(__METHOD__.': Using netsted set for non main tree.'); 227 include_once
'./Services/Tree/classes/class.ilNestedSetTree.php';
246 $this->use_cache = $a_use;
287 $this->lang_code =
$ilUser->getCurrentLanguage();
289 $this->lang_code =
"en";
341 $this->in_tree_cache = array();
361 public function setTableNames($a_table_tree, $a_table_obj_data, $a_table_obj_reference =
"")
363 if (!isset($a_table_tree)
or !isset($a_table_obj_data)) {
365 "tree table: " . $a_table_tree .
" object data table: " . $a_table_obj_data;
370 $this->table_tree = $a_table_tree;
371 $this->table_obj_data = $a_table_obj_data;
372 $this->table_obj_reference = $a_table_obj_reference;
388 if (!isset($a_column_name)) {
394 $this->ref_pk = $a_column_name;
407 if (!isset($a_column_name)) {
413 $this->obj_pk = $a_column_name;
426 if (!isset($a_column_name)) {
432 $this->tree_pk = $a_column_name;
443 if ($this->table_obj_reference) {
445 return "JOIN " . $this->table_obj_reference .
" ON " . $this->table_tree .
".child=" . $this->table_obj_reference .
"." . $this->ref_pk .
" " .
446 "JOIN " . $this->table_obj_data .
" ON " . $this->table_obj_reference .
"." . $this->obj_pk .
"=" . $this->table_obj_data .
"." . $this->obj_pk .
" ";
449 return "JOIN " . $this->table_obj_data .
" ON " . $this->table_tree .
".child=" . $this->table_obj_data .
"." . $this->obj_pk .
" ";
487 $ilDB = $DIC[
'ilDB'];
489 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
490 'WHERE parent = ' .
$ilDB->quote($a_node,
'integer') .
' ' .
491 'AND tree = ' .
$ilDB->quote($this->tree_id,
'integer' .
' ' .
497 $childs[] =
$row->child;
511 public function getChilds($a_node_id, $a_order =
"", $a_direction =
"ASC")
516 $ilDB = $DIC[
'ilDB'];
517 $ilObjDataCache = $DIC[
'ilObjDataCache'];
520 if (!isset($a_node_id)) {
536 if (!empty($a_order)) {
537 $order_clause =
"ORDER BY " . $a_order .
" " . $a_direction;
539 $order_clause =
"ORDER BY " . $this->table_tree .
".lft";
544 'SELECT * FROM ' . $this->table_tree .
' ' .
546 "WHERE parent = %s " .
547 "AND " . $this->table_tree .
"." . $this->tree_pk .
" = %s " .
549 $ilDB->quote($a_node_id,
'integer'),
550 $ilDB->quote($this->tree_id,
'integer')
555 if (!$count = $res->numRows()) {
561 while (
$r =
$ilDB->fetchAssoc($res)) {
563 $obj_ids[] =
$r[
"obj_id"];
568 is_object(
$ilUser) && $this->lang_code ==
$ilUser->getLanguage() && !$this->oc_preloaded[$a_node_id]) {
570 $ilObjDataCache->preloadObjectCache($obj_ids, $this->lang_code);
572 $this->oc_preloaded[$a_node_id] =
true;
580 #$GLOBALS['DIC']['ilLog']->write(__METHOD__.': Storing in tree cache '.$row['child'].' = true'); 581 $this->in_tree_cache[$row[
'child']] = $row[
'tree'] == 1;
584 $childs[$count - 1][
"last"] =
true;
599 $childs = $this->
getChilds($a_node, $a_order, $a_direction);
601 foreach ($childs as $child) {
602 if (!in_array($child[
"type"], $a_filter)) {
603 $filtered[] = $child;
606 return $filtered ? $filtered : array();
622 $ilDB = $DIC[
'ilDB'];
624 if (!isset($a_node_id)
or !isset(
$a_type)) {
625 $message =
"Missing parameter! node_id:" . $a_node_id .
" type:" .
$a_type;
630 if (
$a_type ==
'rolf' && $this->table_obj_reference) {
634 $ilDB->setLimit(1, 0);
636 "SELECT * FROM " . $this->table_tree .
" " .
638 "WHERE parent = %s " .
639 "AND " . $this->table_tree .
"." . $this->tree_pk .
" = %s " .
640 "AND " . $this->table_obj_data .
".type = %s ",
641 $ilDB->quote($a_node_id,
'integer'),
642 $ilDB->quote($this->tree_id,
'integer'),
647 "SELECT * FROM " . $this->table_tree .
" " .
649 "WHERE parent = %s " .
650 "AND " . $this->table_tree .
"." . $this->tree_pk .
" = %s " .
651 "AND " . $this->table_obj_data .
".type = %s " .
652 "ORDER BY " . $this->table_tree .
".lft",
653 $ilDB->quote($a_node_id,
'integer'),
654 $ilDB->quote($this->tree_id,
'integer'),
666 return $childs ? $childs : array();
682 $ilDB = $DIC[
'ilDB'];
684 if (!isset($a_node_id)
or !$a_types) {
685 $message =
"Missing parameter! node_id:" . $a_node_id .
" type:" . $a_types;
692 $filter =
'AND ' . $this->table_obj_data .
'.type IN(' . implode(
',',
ilUtil::quoteArray($a_types)) .
') ';
696 if (!empty($a_order)) {
697 $order_clause =
"ORDER BY " . $a_order .
" " . $a_direction;
699 $order_clause =
"ORDER BY " . $this->table_tree .
".lft";
702 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
704 'WHERE parent = ' .
$ilDB->quote($a_node_id,
'integer') .
' ' .
705 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = ' .
$ilDB->quote($this->tree_id,
'integer') .
' ' .
714 return $childs ? $childs : array();
732 $ilDB = $DIC[
'ilDB'];
735 if ($a_source_id <= 1
or $a_target_id <= 0) {
740 if (!isset($a_source_id)
or !isset($a_target_id)) {
744 if ($this->
isInTree($a_source_id)) {
750 $query =
'DELETE from tree ' .
751 'WHERE tree = ' .
$ilDB->quote($a_tree_id,
'integer') .
' ' .
752 'AND child = ' .
$ilDB->quote($a_source_id,
'integer');
771 $ilDB = $DIC[
'ilDB'];
776 if ($a_node_id <= 1
or $a_parent_id <= 0) {
778 'Invalid parameters! $a_node_id: %s $a_parent_id: %s',
788 if (!isset($a_node_id)
or !isset($a_parent_id)) {
791 "node_id: " . $a_node_id .
" parent_id: " . $a_parent_id);
795 $this->table_tree .
"!");
800 $this->in_tree_cache[$a_node_id] =
true;
803 if ($a_reset_deletion_date) {
808 $GLOBALS[
'DIC'][
'ilAppEventHandler']->raise(
812 'tree' => $this->table_tree,
813 'node_id' => $a_node_id,
814 'parent_id' => $a_parent_id)
837 foreach ($this->
getSubTree($node) as $subnode) {
838 if ($depth
and $subnode[
'depth'] > $depth) {
841 if (!$first
and in_array($subnode[
'type'], $a_filter)) {
842 $depth = $subnode[
'depth'];
848 $filtered[] = $subnode;
850 return $filtered ? $filtered : array();
877 $ilDB = $DIC[
'ilDB'];
879 if (!is_array($a_node)) {
903 $subtree[] =
$row[
'child'];
906 if ($this->
__isMainTree() || $this->table_tree ==
"lm_tree") {
907 $this->in_tree_cache[
$row[
'child']] =
true;
910 return $subtree ? $subtree : array();
923 $a_filter = $a_filter ? $a_filter : array();
925 foreach ($this->getSubtree($this->
getNodeData($a_node)) as $node) {
926 if (in_array($node[
"type"], $a_filter)) {
929 $types[
"$node[type]"] = $node[
"type"];
931 return $types ? $types : array();
945 $ilDB = $DIC[
'ilDB'];
947 $this->log->debug(
'Delete tree with node ' . $a_node);
949 if (!is_array($a_node)) {
954 $this->log->debug($this->tree_pk);
991 $pathIds = $this->
getPathId($a_endnode_id, $a_startnode_id);
996 $ilDB = $DIC[
'ilDB'];
999 if (count($pathIds) == 0) {
1003 $inClause =
'child IN (';
1004 for (
$i = 0;
$i < count($pathIds);
$i++) {
1008 $inClause .=
$ilDB->quote($pathIds[
$i],
'integer');
1013 'FROM ' . $this->table_tree .
' ' .
1015 'WHERE ' . $inClause .
' ' .
1016 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = ' . $this->ilDB->quote($this->tree_id,
'integer') .
' ' .
1020 $pathFull = array();
1026 #$GLOBALS['DIC']['ilLog']->write(__METHOD__.': Storing in tree cache '.$row['child']); 1027 $this->in_tree_cache[
$row[
'child']] = $row[
'tree'] == 1;
1044 $ilDB = $DIC[
'ilDB'];
1050 $res =
$ilDB->query(
'SELECT t.depth, t.parent, t.child ' .
1051 'FROM ' . $this->table_tree .
' t ' .
1052 'WHERE ' .
$ilDB->in(
"child", $a_node_ids,
false,
"integer") .
1053 'AND ' . $this->tree_pk .
' = ' .
$ilDB->quote($this->tree_id,
"integer"));
1055 $this->depth_cache[
$row[
"child"]] = $row[
"depth"];
1056 $this->parent_cache[$row[
"child"]] = $row[
"parent"];
1069 public function getPathId($a_endnode_id, $a_startnode_id = 0)
1071 if (!$a_endnode_id) {
1077 if ($this->
isCacheUsed() && isset($this->path_id_cache[$a_endnode_id][$a_startnode_id])) {
1079 return $this->path_id_cache[$a_endnode_id][$a_startnode_id];
1086 $this->path_id_cache[$a_endnode_id][$a_startnode_id] = $pathIds;
1113 $ilDB = $DIC[
'ilDB'];
1118 if ($titlePath == null || count($titlePath) == 0) {
1119 if ($a_startnode_id == 0) {
1127 if ($a_startnode_id != null && $a_startnode_id != 0) {
1130 $parent = $a_startnode_id;
1133 $nodePath = array();
1141 require_once(
'include/Unicode/UtfNormal.php');
1142 include_once
'./Services/Utilities/classes/class.ilStr.php';
1143 $inClause =
'd.title IN (';
1144 for (
$i = 0;
$i < count($titlePath);
$i++) {
1149 $inClause .=
$ilDB->quote($titlePath[$i],
'text');
1154 if ($this->table_obj_reference) {
1155 $joinClause =
'JOIN ' . $this->table_obj_reference .
' r ON t.child = r.' . $this->ref_pk .
' ' .
1156 'JOIN ' . $this->table_obj_data .
' d ON r.' . $this->obj_pk .
' = d.' .
$this->obj_pk;
1158 $joinClause =
'JOIN ' . $this->table_obj_data .
' d ON t.child = d.' .
$this->obj_pk;
1165 $q =
'SELECT t.depth, t.parent, t.child, d.' . $this->obj_pk .
' obj_id, d.type, d.title ' .
1166 'FROM ' . $this->table_tree .
' t ' .
1168 'WHERE ' . $inClause .
' ' .
1169 'AND t.depth <= ' . (count($titlePath) + count($nodePath)) .
' ' .
1171 'ORDER BY t.depth, t.child ASC';
1182 for (
$i = 0;
$i < count($titlePath);
$i++) {
1183 $pathElementFound =
false;
1185 if ($row[
'parent'] == $parent &&
1190 $parent = $row[
'child'];
1191 $pathElementFound =
true;
1196 if (!$pathElementFound) {
1227 $ilDB = $DIC[
'ilDB'];
1229 $pathIds = $this->
getPathId($a_endnode_id, $a_startnode_id);
1232 if (count($pathIds) == 0) {
1239 for (
$i = 0;
$i < count($pathIds);
$i++) {
1240 $types[] =
'integer';
1244 $query =
'SELECT t.depth,t.parent,t.child,d.obj_id,d.type,d.title ' .
1245 'FROM ' . $this->table_tree .
' t ' .
1246 'JOIN ' . $this->table_obj_reference .
' r ON r.ref_id = t.child ' .
1247 'JOIN ' . $this->table_obj_data .
' d ON d.obj_id = r.obj_id ' .
1248 'WHERE ' .
$ilDB->in(
't.child',
$data,
false,
'integer') .
' ' .
1249 'ORDER BY t.depth ';
1253 $titlePath = array();
1255 $titlePath[] =
$row;
1272 $ilDB = $DIC[
'ilDB'];
1274 $types = array(
'integer');
1275 $query =
'SELECT lft,rgt FROM ' . $this->table_tree .
' ' .
1276 'WHERE ' . $this->tree_pk .
' = %s ';
1284 $all = array_merge($lft, $rgt);
1285 $uni = array_unique($all);
1287 if (count($all) != count($uni)) {
1308 $ilDB = $DIC[
'ilDB'];
1310 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
1311 'WHERE ' . $this->tree_pk .
' = %s ' .
1313 $r1 =
$ilDB->queryF(
$query, array(
'integer'), array($this->tree_id));
1317 if ((
$row[
"child"] == 0) && $a_no_zero_child) {
1318 $message =
"Tree contains child with ID 0!";
1323 if ($this->table_obj_reference) {
1325 $query =
'SELECT * FROM ' . $this->table_obj_reference .
' WHERE ' . $this->ref_pk .
' = %s ';
1329 if ($r2->numRows() == 0) {
1330 $message =
"No Object-to-Reference entry found for ID " .
$row[
"child"] .
"!";
1334 if ($r2->numRows() > 1) {
1335 $message =
"More Object-to-Reference entries found for ID " .
$row[
"child"] .
"!";
1341 $obj_ref =
$ilDB->fetchAssoc($r2);
1343 $query =
'SELECT * FROM ' . $this->table_obj_data .
' WHERE ' . $this->obj_pk .
' = %s';
1344 $r3 =
$ilDB->queryF(
$query, array(
'integer'), array($obj_ref[$this->obj_pk]));
1345 if ($r3->numRows() == 0) {
1350 if ($r3->numRows() > 1) {
1357 $query =
'SELECT * FROM ' . $this->table_obj_data .
' WHERE ' . $this->obj_pk .
' = %s';
1360 if ($r2->numRows() == 0) {
1361 $message =
"No child found for ID " .
$row[
"child"] .
"!";
1365 if ($r2->numRows() > 1) {
1366 $message =
"More childs found for ID " .
$row[
"child"] .
"!";
1385 $ilDB = $DIC[
'ilDB'];
1391 return $row[
'depth'];
1404 $ilDB = $DIC[
'ilDB'];
1407 $query =
'SELECT depth FROM ' . $this->table_tree .
' ' .
1408 'WHERE child = %s ' .
1409 'AND ' . $this->tree_pk .
' = %s ';
1410 $res =
$ilDB->queryF(
$query, array(
'integer',
'integer'), array($a_node_id,$this->tree_id));
1430 $ilDB = $DIC[
'ilDB'];
1437 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
1438 'WHERE child = ' .
$ilDB->quote($a_node_id,
'integer');
1462 $ilDB = $DIC[
'ilDB'];
1464 if (!isset($a_node_id)) {
1469 if ($a_node_id < 1) {
1470 $message =
'No valid parameter given! $a_node_id: %s' . $a_node_id;
1478 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
1480 'WHERE ' . $this->table_tree .
'.child = %s ' .
1481 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = %s ';
1484 $a_tree_pk === null ? $this->tree_id : $a_tree_pk));
1503 $objDefinition = $DIC[
'objDefinition'];
1506 $ilDB = $DIC[
'ilDB'];
1510 $data[
"desc"] = $a_row[
"description"];
1515 if (is_object($objDefinition)) {
1516 $translation_type = $objDefinition->getTranslationType(
$data[
"type"]);
1520 if ($translation_type ==
"sys") {
1522 if (
$data[
"type"] ==
"rolf" and $data[
"obj_id"] != ROLE_FOLDER_ID) {
1528 $data[
"description"] =
$lng->txt(
"obj_" .
$data[
"type"] .
"_desc");
1532 } elseif ($translation_type ==
"db") {
1536 array_key_exists(
$data[
"obj_id"] .
'.' . $lang_code, $this->translation_cache)) {
1537 $key =
$data[
"obj_id"] .
'.' . $lang_code;
1538 $data[
"title"] = $this->translation_cache[
$key][
'title'];
1539 $data[
"description"] = $this->translation_cache[
$key][
'description'];
1540 $data[
"desc"] = $this->translation_cache[
$key][
'desc'];
1544 $query =
'SELECT title,description FROM object_translation ' .
1545 'WHERE obj_id = %s ' .
1546 'AND lang_code = %s ' .
1547 'AND NOT lang_default = %s';
1549 $res =
$ilDB->queryF(
$query, array(
'integer',
'text',
'integer'), array(
1563 if ($this->
isCacheUsed() && count($this->translation_cache) < 1000) {
1564 $key =
$data[
"obj_id"] .
'.' . $lang_code;
1565 $this->translation_cache[
$key] = array();
1566 $this->translation_cache[
$key][
'title'] =
$data[
"title"] ;
1567 $this->translation_cache[
$key][
'description'] =
$data[
"description"];
1568 $this->translation_cache[
$key][
'desc'] =
$data[
"desc"];
1575 include_once(
'./Services/ContainerReference/classes/class.ilContainerReference.php');
1591 $ilObjDataCache = $DIC[
'ilObjDataCache'];
1593 if ($this->
isCacheUsed() && is_array($a_obj_ids) && is_object($ilObjDataCache)) {
1594 foreach ($a_obj_ids as
$id) {
1595 $this->translation_cache[$id .
'.'][
'title'] = $ilObjDataCache->lookupTitle($id);
1596 $this->translation_cache[$id .
'.'][
'description'] = $ilObjDataCache->lookupDescription($id);
1598 $this->translation_cache[$id .
'.'][
'desc'] =
1599 $this->translation_cache[$id .
'.'][
'description'];
1616 $ilDB = $DIC[
'ilDB'];
1618 if (!isset($a_node_id)) {
1620 #$this->ilErr->raiseError(get_class($this)."::getNodeData(): No node_id given! ",$this->ilErr->WARNING); 1623 if ($this->
isCacheUsed() && isset($this->in_tree_cache[$a_node_id])) {
1624 #$GLOBALS['DIC']['ilLog']->write(__METHOD__.': Using in tree cache '.$a_node_id); 1626 return $this->in_tree_cache[$a_node_id];
1629 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
1630 'WHERE ' . $this->table_tree .
'.child = %s ' .
1631 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = %s';
1637 if (
$res->numRows() > 0) {
1639 #$GLOBALS['DIC']['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true'); 1640 $this->in_tree_cache[$a_node_id] =
true;
1645 #$GLOBALS['DIC']['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = false'); 1646 $this->in_tree_cache[$a_node_id] =
false;
1663 $ilDB = $DIC[
'ilDB'];
1668 if (!isset($a_node_id)) {
1673 if ($this->table_obj_reference) {
1675 $innerjoin =
"JOIN " . $this->table_obj_reference .
" ON v.child=" . $this->table_obj_reference .
"." . $this->ref_pk .
" " .
1676 "JOIN " . $this->table_obj_data .
" ON " . $this->table_obj_reference .
"." . $this->obj_pk .
"=" . $this->table_obj_data .
"." . $this->obj_pk .
" ";
1679 $innerjoin =
"JOIN " . $this->table_obj_data .
" ON v.child=" . $this->table_obj_data .
"." . $this->obj_pk .
" ";
1682 $query =
'SELECT * FROM ' . $this->table_tree .
' s, ' . $this->table_tree .
' v ' .
1684 'WHERE s.child = %s ' .
1685 'AND s.parent = v.child ' .
1686 'AND s.' . $this->tree_pk .
' = %s ' .
1687 'AND v.' . $this->tree_pk .
' = %s';
1688 $res =
$ilDB->queryF(
$query, array(
'integer',
'integer',
'integer'), array(
1705 return $this->
getRelation($a_startnode_id, $a_querynode_id) == self::RELATION_PARENT;
1717 public function addTree($a_tree_id, $a_node_id = -1)
1721 $ilDB = $DIC[
'ilDB'];
1726 'Operation not allowed on main tree! $a_tree_if: %s $a_node_id: %s',
1734 if (!isset($a_tree_id)) {
1740 if ($a_node_id <= 0) {
1741 $a_node_id = $a_tree_id;
1744 $query =
'INSERT INTO ' . $this->table_tree .
' (' .
1745 $this->tree_pk .
', child,parent,lft,rgt,depth) ' .
1747 '(%s,%s,%s,%s,%s,%s)';
1748 $res =
$ilDB->manipulateF(
$query, array(
'integer',
'integer',
'integer',
'integer',
'integer',
'integer'), array(
1772 $ilDB = $DIC[
'ilDB'];
1779 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
1781 'WHERE ' . $this->table_obj_data .
'.type = ' . $this->ilDB->quote(
$a_type,
'text') .
1782 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = ' . $this->ilDB->quote($this->tree_id,
'integer');
1805 $ilDB = $DIC[
'ilDB'];
1817 $query =
'DELETE FROM ' . $this->table_tree .
1818 ' WHERE ' . $this->tree_pk .
' = %s ';
1819 $ilDB->manipulateF(
$query, array(
'integer'), array($a_tree_id));
1834 $ilDB = $DIC[
'ilDB'];
1845 $subnodes = array();
1847 $subnodes[] =
$row[
'child'];
1850 if (!count($subnodes)) {
1855 if ($a_set_deleted) {
1856 include_once
'./Services/Object/classes/class.ilObject.php';
1878 return $this->
moveToTrash($a_node_id, $a_set_deleted);
1887 return $this->
isSaved($a_node_id);
1899 $ilDB = $DIC[
'ilDB'];
1902 if ($this->
isCacheUsed() && isset($this->is_saved_cache[$a_node_id])) {
1904 return $this->is_saved_cache[$a_node_id];
1907 $query =
'SELECT ' . $this->tree_pk .
' FROM ' . $this->table_tree .
' ' .
1908 'WHERE child = %s ';
1912 if (
$row[$this->tree_pk] < 0) {
1914 $this->is_saved_cache[$a_node_id] =
true;
1919 $this->is_saved_cache[$a_node_id] =
false;
1935 $ilDB = $DIC[
'ilDB'];
1937 if (!is_array($a_node_ids) || !$this->
isCacheUsed()) {
1941 $query =
'SELECT ' . $this->tree_pk .
', child FROM ' . $this->table_tree .
' ' .
1942 'WHERE ' .
$ilDB->in(
"child", $a_node_ids,
false,
"integer");
1946 if (
$row[$this->tree_pk] < 0) {
1948 $this->is_saved_cache[
$row[
"child"]] =
true;
1952 $this->is_saved_cache[
$row[
"child"]] =
false;
1970 $ilDB = $DIC[
'ilDB'];
1972 if (!isset($a_parent_id)) {
1978 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
1980 'WHERE ' . $this->table_tree .
'.' . $this->tree_pk .
' < %s ' .
1981 'AND ' . $this->table_tree .
'.parent = %s';
1990 return $saved ? $saved : array();
2003 $ilDB = $DIC[
'ilDB'];
2005 $query =
'SELECT ' . $this->table_obj_data .
'.obj_id FROM ' . $this->table_tree .
' ' .
2007 'WHERE ' . $this->table_tree .
'.' . $this->tree_pk .
' < ' .
$ilDB->quote(0,
'integer') .
' ' .
2008 'AND ' .
$ilDB->in($this->table_obj_data .
'.obj_id', $a_obj_ids,
'',
'integer');
2011 $saved[] =
$row[
'obj_id'];
2014 return $saved ? $saved : array();
2028 $ilDB = $DIC[
'ilDB'];
2030 if (!isset($a_node_id)) {
2036 $query =
'SELECT parent FROM ' . $this->table_tree .
' ' .
2037 'WHERE child = %s ' .
2038 'AND ' . $this->tree_pk .
' = %s ';
2044 return $row->parent;
2058 $ilDB = $DIC[
'ilDB'];
2060 if (!isset($a_node_id)) {
2066 $query =
'SELECT lft FROM ' . $this->table_tree .
' ' .
2067 'WHERE child = %s ' .
2068 'AND ' . $this->tree_pk .
' = %s ';
2087 $ilDB = $DIC[
'ilDB'];
2089 if (!isset($a_node)) {
2096 $query =
'SELECT count(*) cnt FROM ' . $this->table_tree .
' ' .
2098 'WHERE lft <= %s ' .
2100 'AND parent = %s ' .
2101 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = %s ';
2103 $res =
$ilDB->queryF(
$query, array(
'integer',
'text',
'integer',
'integer'), array(
2109 $query =
'SELECT count(*) cnt FROM ' . $this->table_tree .
' ' .
2111 'WHERE lft <= %s ' .
2112 'AND parent = %s ' .
2113 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = %s ';
2115 $res =
$ilDB->queryF(
$query, array(
'integer',
'integer',
'integer'), array(
2134 $ilDB = $DIC[
'ilDB'];
2136 $query =
'SELECT child FROM ' . $this->table_tree .
' ' .
2137 'WHERE parent = %s ' .
2138 'AND ' . $this->tree_pk .
' = %s ';
2143 $this->root_id =
$row->child;
2158 $this->root_id = $a_root_id;
2178 $this->tree_id = $a_tree_id;
2193 $ilDB = $DIC[
'ilDB'];
2195 if (!isset($a_node_id)) {
2202 $query =
'SELECT lft FROM ' . $this->table_tree .
' ' .
2203 'WHERE ' . $this->table_tree .
'.child = %s ' .
2204 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = %s ';
2211 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
2214 'AND ' . $this->table_obj_data .
'.type = %s ' .
2215 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = %s ' .
2218 $res =
$ilDB->queryF(
$query, array(
'integer',
'text',
'integer'), array(
2223 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
2226 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = %s ' .
2234 if (
$res->numRows() < 1) {
2254 $ilDB = $DIC[
'ilDB'];
2256 if (!isset($a_node_id)) {
2263 $query =
'SELECT lft FROM ' . $this->table_tree .
' ' .
2264 'WHERE ' . $this->table_tree .
'.child = %s ' .
2265 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = %s ';
2273 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
2276 'AND ' . $this->table_obj_data .
'.type = %s ' .
2277 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = %s ' .
2278 'ORDER BY lft DESC';
2280 $res =
$ilDB->queryF(
$query, array(
'integer',
'text',
'integer'), array(
2285 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
2288 'AND ' . $this->table_tree .
'.' . $this->tree_pk .
' = %s ' .
2289 'ORDER BY lft DESC';
2296 if (
$res->numRows() < 1) {
2316 $ilDB = $DIC[
'ilDB'];
2324 $ilAtomQuery =
$ilDB->buildAtomQuery();
2325 $ilAtomQuery->addTableLock($this->table_tree);
2327 $ilAtomQuery->addQueryCallable($renumber_callable);
2328 $ilAtomQuery->run();
2330 $renumber_callable(
$ilDB);
2349 $ilDB = $DIC[
'ilDB'];
2351 $query =
'UPDATE ' . $this->table_tree .
' SET lft = %s WHERE child = %s AND tree = %s';
2352 $res =
$ilDB->manipulateF(
$query, array(
'integer',
'integer',
'integer'), array(
2361 foreach ($childs as $child) {
2367 if (count($childs) > 0) {
2368 $i += $this->gap * 2;
2372 $query =
'UPDATE ' . $this->table_tree .
' SET rgt = %s WHERE child = %s AND tree = %s';
2373 $res =
$ilDB->manipulateF(
$query, array(
'integer',
'integer',
'integer'), array(
2394 $cache_key = $a_ref_id .
'.' .
$a_type .
'.' . ((int) $a_exclude_source_check);
2398 array_key_exists($cache_key, $this->parent_type_cache)) {
2399 return $this->parent_type_cache[$cache_key];
2403 $do_cache = ($this->
__isMainTree() && count($this->parent_type_cache) < 1000);
2408 $this->parent_type_cache[$cache_key] =
false;
2416 if ($a_exclude_source_check) {
2420 foreach (
$path as $node) {
2422 if ($node[
"type"] ==
$a_type) {
2424 $this->parent_type_cache[$cache_key] = $node[
"child"];
2426 return $node[
"child"];
2431 $this->parent_type_cache[$cache_key] =
false;
2446 public static function _removeEntry($a_tree, $a_child, $a_db_table =
"tree")
2450 $ilDB = $DIC[
'ilDB'];
2452 if ($a_db_table ===
'tree') {
2453 if ($a_tree == 1
and $a_child == ROOT_FOLDER_ID) {
2455 'Tried to delete root node! $a_tree: %s $a_child: %s',
2464 $query =
'DELETE FROM ' . $a_db_table .
' ' .
2465 'WHERE tree = %s ' .
2480 return $this->table_tree ===
'tree';
2498 $ilDB = $DIC[
'ilDB'];
2502 $this->log->debug(
$query);
2505 $counter = (int) $lft_childs = array();
2507 $lft_childs[
$row->child] =
$row->parent;
2512 if ($counter != count($lft_childs)) {
2513 $message =
'Duplicate entries for "child" in maintree! $a_node_id: ' . $a_node[
'child'];
2520 $parent_childs = array();
2540 $ilDB = $DIC[
'ilDB'];
2543 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
2544 'WHERE child = %s ' .
2552 $parent_childs[$a_node_id] =
$row->parent;
2557 $message =
'Multiple entries in maintree! $a_node_id: ' . $a_node_id;
2564 $query =
'SELECT * FROM ' . $this->table_tree .
' ' .
2565 'WHERE parent = %s ';
2586 ksort($parent_childs);
2588 $this->log->debug(
'left childs ' . print_r($lft_childs,
true));
2589 $this->log->debug(
'parent childs ' . print_r($parent_childs,
true));
2591 if (count($lft_childs) != count($parent_childs)) {
2592 $message =
'(COUNT) Tree is corrupted! Left/Right subtree does not comply with parent relation';
2598 foreach ($lft_childs as
$key => $value) {
2599 if ($parent_childs[
$key] != $value) {
2600 $message =
'(COMPARE) Tree is corrupted! Left/Right subtree does not comply with parent relation';
2604 if (
$key == ROOT_FOLDER_ID) {
2605 $message =
'(ROOT_FOLDER) Tree is corrupted! Tried to delete root folder';
2622 public function moveTree($a_source_id, $a_target_id, $a_location = self::POS_LAST_NODE)
2624 $old_parent_id = $this->
getParentId($a_source_id);
2627 $GLOBALS[
'DIC'][
'ilAppEventHandler']->raise(
2631 'tree' => $this->table_tree,
2632 'source_id' => $a_source_id,
2633 'target_id' => $a_target_id,
2634 'old_parent_id' => $old_parent_id
2664 public function getSubTreeQuery($a_node_id, $a_fields = array(), $a_types =
'', $a_force_join_reference =
false)
2669 $a_force_join_reference,
2687 $ilDB = $DIC[
'ilDB'];
2690 if (!
sizeof($node)) {
2699 if (count($a_fields)) {
2700 $fields = implode(
',', $a_fields);
2703 $query =
"SELECT " . $fields .
2709 while (
$row =
$ilDB->fetchAssoc($set)) {
2720 $ilDB = $DIC[
'ilDB'];
2721 $ilAppEventHandler = $DIC[
'ilAppEventHandler'];
2723 $query =
'DELETE FROM tree where ' .
2724 'child = ' .
$ilDB->quote($a_node_id,
'integer') .
' ' .
2725 'AND tree = ' .
$ilDB->quote($a_tree_id,
'integer');
2728 $ilAppEventHandler->raise(
2731 array(
'tree' => $this->table_tree,
2732 'node_id' => $a_node_id,
2733 'tree_id' => $a_tree_id
2747 $ilDB = $DIC[
'ilDB'];
2749 $query =
'SELECT DISTINCT(o.type) ' .
$ilDB->quoteIdentifier(
'type') .
' FROM tree t JOIN object_reference r ON child = r.ref_id ' .
2750 'JOIN object_data o on r.obj_id = o.obj_id ' .
2751 'WHERE tree < ' .
$ilDB->quote(0,
'integer') .
' ' .
2752 'AND child = -tree ' .
2756 $types_deleted = array();
2758 $types_deleted[] =
$row->type;
2760 return $types_deleted;
removeTree($a_tree_id)
remove an existing tree
Thrown if invalid tree strucutes are found.
static setDeletedDates($a_ref_ids)
Set deleted date.
static _resetDeletedDate($a_ref_id)
only called in ilObjectGUI::insertSavedNodes
getSubTreeFilteredByObjIds($a_node_id, array $a_obj_ids, array $a_fields=array())
get all node ids in the subtree under specified node id, filter by object ids
initTreeImplementation()
Init tree implementation.
getChilds($a_node_id, $a_order="", $a_direction="ASC")
get child nodes of given node public
static shortenText( $a_str, $a_len, $a_dots=false, $a_next_blank=false, $a_keep_extension=false)
shorten a string to given length.
preloadDeleted($a_node_ids)
Preload deleted information.
isGrandChild($a_startnode_id, $a_querynode_id)
checks if a node is in the path of an other node public
isDeleted($a_node_id)
This is a wrapper for isSaved() with a more useful name.
renumber($node_id=1, $i=1)
Wrapper for renumber.
getFilteredChilds($a_filter, $a_node, $a_order="", $a_direction="ASC")
get child nodes of given node (exclude filtered obj_types) public
getSavedNodeObjIds(array $a_obj_ids)
get object id of saved/deleted nodes
fetchNodeData($a_row)
get data of parent node from tree and object_data private
static _removeEntry($a_tree, $a_child, $a_db_table="tree")
STATIC METHOD Removes a single entry from a tree.
getNodeTreeData($a_node_id)
return all columns of tabel tree
getRelation($a_node_a, $a_node_b)
Get relation of two nodes.
fetchPredecessorNode($a_node_id, $a_type="")
get node data of predecessor node
getTreeId()
get tree id public
getParentCache()
Get parent cache.
if(!array_key_exists('StateId', $_REQUEST)) $id
buildJoin()
build join depending on table settings private
getChildsByType($a_node_id, $a_type)
get child nodes of given node by object type public
getDepth($a_node_id)
return depth of a node in tree private
deleteTree($a_node)
delete node and the whole subtree under this node public
setObjectTablePK($a_column_name)
set column containing primary key in object table public
saveSubTree($a_node_id, $a_set_deleted=false)
Use the wrapper moveToTrash save subtree: delete a subtree (defined by node_id) to a new tree with $t...
getPathId($a_endnode_id, $a_startnode_id=0)
get path from a given startnode to a given endnode if startnode is not given the rootnode is startnod...
static strToLower($a_string)
getTreePk()
Get tree primary key.
__validateSubtrees(&$lft_childs, $parent_childs)
Base class for nested set path based trees.
deleteNode($a_tree_id, $a_node_id)
getSubTreeTypes($a_node, $a_filter=0)
get types of nodes in the subtree under specified node
__construct($a_tree_id, $a_root_id=0)
Constructor public.
getChildsByTypeFilter($a_node_id, $a_types, $a_order="", $a_direction="ASC")
get child nodes of given node by object type public
getFilteredSubTree($a_node_id, $a_filter=array())
get filtered subtree
getObjectDataTable()
Get object data table.
validateParentRelations()
Validate parent relations of tree.
__checkDelete($a_node)
Check for deleteTree() compares a subtree of a given node by checking lft, rgt against parent relatio...
static toNFC($string)
Convert a UTF-8 string to normal form C, canonical composition.
getPathFull($a_endnode_id, $a_startnode_id=0)
get path from a given startnode to a given endnode if startnode is not given the rootnode is startnod...
catch(Exception $e) $message
foreach($_POST as $key=> $value) $res
getLeftValue($a_node_id)
get left value of given node public
static _lookupTitle($a_obj_id)
Overwitten from base class.
getTreeTable()
Get tree table name.
checkTree()
check consistence of tree all left & right values are checked if they are exists only once public ...
getRootId()
get the root id of tree public
setTreeId($a_tree_id)
set tree id public
getNodeData($a_node_id, $a_tree_pk=null)
get all information of a node.
getNodePath($a_endnode_id, $a_startnode_id=0)
Returns the node path for the specified object reference.
lookupTrashedObjectTypes()
Lookup object types in trash type $ilDB.
getParentId($a_node_id)
get parent id of given node public
getTableReference()
Get reference table if available.
setTableNames($a_table_tree, $a_table_obj_data, $a_table_obj_reference="")
set table names The primary key of the table containing your object_data must be 'obj_id' You may use...
insertNodeFromTrash($a_source_id, $a_target_id, $a_tree_id, $a_pos=IL_LAST_NODE, $a_reset_deleted_date=false)
Insert node from trash deletes trash entry.
preloadDepthParent($a_node_ids)
Preload depth/parent.
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
moveToTrash($a_node_id, $a_set_deleted=false)
Wrapper for saveSubTree.
__renumber($node_id=1, $i=1)
This method is private.
setTreeTablePK($a_column_name)
set column containing primary key in tree table public
setReferenceTablePK($a_column_name)
set column containing primary key in reference table public
__getSubTreeByParentRelation($a_node_id, &$parent_childs)
type $ilDB
getDepthCache()
Get depth cache.
static quoteArray($a_array)
Quotes all members of an array for usage in DB query statement.
initLangCode()
Store user language.
getNodePathForTitlePath($titlePath, $a_startnode_id=null)
Converts a path consisting of object titles into a path consisting of tree nodes. ...
getChildIds($a_node)
Get node child ids type $ilDB.
getMaximumDepth()
Return the current maximum depth in the tree public.
insertNode($a_node_id, $a_parent_id, $a_pos=IL_LAST_NODE, $a_reset_deletion_date=false)
insert new node with node_id under parent node with parent_id public
getRbacSubtreeInfo($a_endnode_id)
This method is used for change existing objects and returns all necessary information for this action...
getGap()
Get default gap *.
fetchTranslationFromObjectDataCache($a_obj_ids)
Get translation data from object cache (trigger in object cache on preload)
getSubTreeQuery($a_node_id, $a_fields=array(), $a_types='', $a_force_join_reference=false)
Get tree subtree query.
Base class for materialize path based trees Based on implementation of Werner Randelshofer.
getParentNodeData($a_node_id)
get data of parent node from tree and object_data public
getSubTree($a_node, $a_with_data=true, $a_type="")
get all nodes in the subtree under specified node
getNodeDataByType($a_type)
get nodes by type
static getLogger($a_component_id)
Get component logger.
isCacheUsed()
Check if cache is active.
getSubTreeIds($a_ref_id)
Get all ids of subnodes.
getChildSequenceNumber($a_node, $type="")
get sequence number of node in sibling sequence public
getRelationOfNodes($a_node_a_arr, $a_node_b_arr)
get relation of two nodes by node data
fetchSuccessorNode($a_node_id, $a_type="")
get node data of successor node
useCache($a_use=true)
Use Cache (usually activated)
__isMainTree()
Check if operations are done on main tree.
getTreeImplementation()
Get tree implementation.
isSaved($a_node_id)
Use method isDeleted check if node is saved.
addTree($a_tree_id, $a_node_id=-1)
create a new tree to do: ???
checkTreeChilds($a_no_zero_child=true)
check, if all childs of tree nodes exist in object table
isInTree($a_node_id)
get all information of a node.
$GLOBALS['JPEG_Segment_Names']
Global Variable: XMP_tag_captions.
moveTree($a_source_id, $a_target_id, $a_location=self::POS_LAST_NODE)
Move Tree Implementation.
checkForParentType($a_ref_id, $a_type, $a_exclude_source_check=false)
Check for parent type e.g check if a folder (ref_id 3) is in a parent course obj => checkForParentTyp...
getSavedNodeData($a_parent_id)
get data saved/deleted nodes
readRootId()
read root id from database