3 declare(strict_types=1);
24 $this->tree = $a_tree;
25 $this->db = $DIC->database();
39 $query =
'SELECT s.child FROM ' .
40 $this->
getTree()->getTreeTable() .
' s, ' .
41 $this->
getTree()->getTreeTable() .
' t ' .
42 'WHERE t.child = %s ' .
43 'AND s.lft > t.lft ' .
44 'AND s.rgt < t.rgt ' .
45 'AND s.' . $this->
getTree()->getTreePk() .
' = %s';
47 $res = $this->db->queryF(
49 array(
'integer',
'integer'),
50 array($a_node_id, $this->
getTree()->getTreeId())
54 $childs[] = (
int) $row->child;
65 bool $a_force_join_reference =
true,
69 if (is_array($a_types)) {
71 $type_str =
"AND " . $this->db->in(
72 $this->
getTree()->getObjectDataTable() .
".type",
81 if ($type_str || $a_force_join_reference) {
82 $join = $this->
getTree()->buildJoin();
86 if (count($a_fields)) {
87 $fields = implode(
',', $a_fields);
92 "FROM " . $this->
getTree()->getTreeTable() .
" " .
94 "WHERE " . $this->
getTree()->getTreeTable() .
'.lft ' .
95 'BETWEEN ' . $this->db->quote($a_node[
'lft'],
'integer') .
' ' .
96 'AND ' . $this->db->quote($a_node[
'rgt'],
'integer') .
' ' .
97 "AND " . $this->
getTree()->getTreeTable() .
"." . $this->
getTree()->getTreePk() .
' < 0 ' .
99 "ORDER BY " . $this->
getTree()->getTreeTable() .
".lft";
110 bool $a_force_join_reference =
true,
114 if (count($a_types)) {
116 $type_str =
"AND " . $this->db->in(
117 $this->
getTree()->getObjectDataTable() .
".type",
127 if ($type_str || $a_force_join_reference) {
128 $join = $this->
getTree()->buildJoin();
132 if (count($a_fields)) {
133 $fields = implode(
',', $a_fields);
138 "FROM " . $this->
getTree()->getTreeTable() .
" " .
140 "WHERE " . $this->
getTree()->getTreeTable() .
'.lft ' .
141 'BETWEEN ' . $this->db->quote($a_node[
'lft'],
'integer') .
' ' .
142 'AND ' . $this->db->quote($a_node[
'rgt'],
'integer') .
' ' .
143 "AND " . $this->
getTree()->getTreeTable() .
"." . $this->
getTree()->getTreePk() .
" = " . $this->db->quote(
148 "ORDER BY " . $this->
getTree()->getTreeTable() .
".lft";
157 if ($a_node_a === [] || $a_node_b === []) {
160 if ($a_node_a[
'child'] == $a_node_b[
'child']) {
163 if ($a_node_a[
'lft'] < $a_node_b[
'lft'] && $a_node_a[
'rgt'] > $a_node_b[
'rgt']) {
166 if ($a_node_b[
'lft'] < $a_node_a[
'lft'] && $a_node_b[
'rgt'] > $a_node_a[
'rgt']) {
171 if ($a_node_a[
'parent'] == $a_node_b[
'parent']) {
177 public function getPathIds(
int $a_endnode,
int $a_startnode = 0): array
185 public function insertNode(
int $a_node_id,
int $a_parent_id,
int $a_pos): void
187 $insert_node_callable =
function (
ilDBInterface $db) use ($a_node_id, $a_parent_id, $a_pos):
void {
193 'SELECT * FROM ' . $this->
getTree()->getTreeTable() .
' ' .
194 'WHERE child = %s ' .
195 'AND ' . $this->
getTree()->getTreePk() .
' = %s ',
196 $this->db->quote($a_parent_id,
'integer'),
197 $this->db->quote($this->
getTree()->getTreeId(),
'integer')
201 $r = $this->db->fetchObject($res);
203 if ($r->parent === null) {
212 if ($this->
getTree()->__isMainTree()) {
214 'UPDATE ' . $this->
getTree()->getTreeTable() .
' SET ' .
215 'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, ' .
216 'rgt = CASE WHEN rgt > %s THEN rgt + 2 ELSE rgt END ',
217 $this->db->quote($left,
'integer'),
218 $this->db->quote($left,
'integer')
220 $res = $this->db->manipulate(
$query);
223 'UPDATE ' . $this->
getTree()->getTreeTable() .
' SET ' .
224 'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, ' .
225 'rgt = CASE WHEN rgt > %s THEN rgt + 2 ELSE rgt END ' .
226 'WHERE ' . $this->
getTree()->getTreePk() .
' = %s ',
227 $this->db->quote($left,
'integer'),
228 $this->db->quote($left,
'integer'),
229 $this->db->quote($this->
getTree()->getTreeId(),
'integer')
231 $res = $this->db->manipulate(
$query);
238 if ($this->
getTree()->getGap() > 0) {
241 'SELECT rgt,lft,parent FROM ' . $this->
getTree()->getTreeTable() .
' ' .
242 'WHERE child = %s ' .
243 'AND ' . $this->
getTree()->getTreePk() .
' = %s',
244 $this->db->quote($a_parent_id,
'integer'),
245 $this->db->quote($this->
getTree()->getTreeId(),
'integer')
247 $res = $this->db->query(
$query);
248 $r = $this->db->fetchAssoc($res);
250 if ($r[
'parent'] === null) {
254 $parentRgt = (
int) $r[
'rgt'];
255 $parentLft = (
int) $r[
'lft'];
258 $availableSpace = $parentRgt - $parentLft;
259 if ($availableSpace < 2) {
267 if ($this->
getTree()->__isMainTree()) {
269 'SELECT MAX(rgt) max_rgt FROM ' . $this->
getTree()->getTreeTable() .
' ' .
270 'WHERE parent = %s ',
271 $this->db->quote($a_parent_id,
'integer')
273 $res = $this->db->query(
$query);
274 $r = $this->db->fetchAssoc($res);
277 'SELECT MAX(rgt) max_rgt FROM ' . $this->
getTree()->getTreeTable() .
' ' .
278 'WHERE parent = %s ' .
279 'AND ' . $this->
getTree()->getTreePk() .
' = %s',
280 $this->db->quote($a_parent_id,
'integer'),
281 $this->db->quote($this->
getTree()->getTreeId(),
'integer')
283 $res = $this->db->query(
$query);
284 $r = $this->db->fetchAssoc($res);
287 if (isset($r[
'max_rgt'])) {
290 $availableSpace = $parentRgt - $r[
'max_rgt'];
291 $lft = $r[
'max_rgt'] + 1;
296 $lft = $parentLft + 1;
302 if ($availableSpace < 2) {
303 if ($this->
getTree()->__isMainTree()) {
305 'UPDATE ' . $this->
getTree()->getTreeTable() .
' SET ' .
306 'lft = CASE WHEN lft > %s THEN lft + %s ELSE lft END, ' .
307 'rgt = CASE WHEN rgt >= %s THEN rgt + %s ELSE rgt END ',
308 $this->db->quote($parentRgt,
'integer'),
309 $this->db->quote((2 + $this->
getTree()->getGap() * 2),
'integer'),
310 $this->db->quote($parentRgt,
'integer'),
311 $this->db->quote((2 + $this->
getTree()->getGap() * 2),
'integer')
313 $res = $this->db->manipulate(
$query);
316 'UPDATE ' . $this->
getTree()->getTreeTable() .
' SET ' .
317 'lft = CASE WHEN lft > %s THEN lft + %s ELSE lft END, ' .
318 'rgt = CASE WHEN rgt >= %s THEN rgt + %s ELSE rgt END ' .
319 'WHERE ' . $this->
getTree()->getTreePk() .
' = %s ',
320 $this->db->quote($parentRgt,
'integer'),
321 $this->db->quote((2 + $this->
getTree()->getGap() * 2),
'integer'),
322 $this->db->quote($parentRgt,
'integer'),
323 $this->db->quote((2 + $this->
getTree()->getGap() * 2),
'integer'),
324 $this->db->quote($this->
getTree()->getTreeId(),
'integer')
326 $res = $this->db->manipulate(
$query);
333 if ($this->
getTree()->__isMainTree()) {
335 'SELECT * FROM ' . $this->
getTree()->getTreeTable() .
' ' .
337 $this->db->quote($a_parent_id,
'integer')
339 $res = $this->db->query(
$query);
342 'SELECT * FROM ' . $this->
getTree()->getTreeTable() .
' ' .
343 'WHERE child = %s ' .
344 'AND ' . $this->
getTree()->getTreePk() .
' = %s ',
345 $this->db->quote($a_parent_id,
'integer'),
346 $this->db->quote($this->
getTree()->getTreeId(),
'integer')
348 $res = $this->db->query(
$query);
350 $r = $this->db->fetchObject($res);
352 if ($r->parent === null) {
362 if ($this->
getTree()->__isMainTree()) {
364 'UPDATE ' . $this->
getTree()->getTreeTable() .
' SET ' .
365 'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, ' .
366 'rgt = CASE WHEN rgt >= %s THEN rgt + 2 ELSE rgt END ',
367 $this->db->quote($right,
'integer'),
368 $this->db->quote($right,
'integer')
370 $res = $this->db->manipulate(
$query);
373 'UPDATE ' . $this->
getTree()->getTreeTable() .
' SET ' .
374 'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, ' .
375 'rgt = CASE WHEN rgt >= %s THEN rgt + 2 ELSE rgt END ' .
376 'WHERE ' . $this->
getTree()->getTreePk() .
' = %s',
377 $this->db->quote($right,
'integer'),
378 $this->db->quote($right,
'integer'),
379 $this->db->quote($this->
getTree()->getTreeId(),
'integer')
381 $res = $this->db->manipulate(
$query);
391 'SELECT * FROM ' . $this->
getTree()->getTreeTable() .
' ' .
392 'WHERE child = %s ' .
393 'AND ' . $this->
getTree()->getTreePk() .
' = %s ',
394 $this->db->quote($a_pos,
'integer'),
395 $this->db->quote($this->
getTree()->getTreeId(),
'integer')
397 $res = $this->db->query(
$query);
398 $r = $this->db->fetchObject($res);
401 if ($r->parent != $a_parent_id) {
410 if ($this->
getTree()->__isMainTree()) {
412 'UPDATE ' . $this->
getTree()->getTreeTable() .
' SET ' .
413 'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, ' .
414 'rgt = CASE WHEN rgt > %s THEN rgt + 2 ELSE rgt END ',
415 $this->db->quote($right,
'integer'),
416 $this->db->quote($right,
'integer')
418 $res = $this->db->manipulate(
$query);
421 'UPDATE ' . $this->
getTree()->getTreeTable() .
' SET ' .
422 'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, ' .
423 'rgt = CASE WHEN rgt > %s THEN rgt + 2 ELSE rgt END ' .
424 'WHERE ' . $this->
getTree()->getTreePk() .
' = %s',
425 $this->db->quote($right,
'integer'),
426 $this->db->quote($right,
'integer'),
427 $this->db->quote($this->
getTree()->getTreeId(),
'integer')
429 $res = $this->db->manipulate(
$query);
437 $depth = $this->
getTree()->getDepth($a_parent_id) + 1;
441 'INSERT INTO ' . $this->
getTree()->getTreeTable() .
' (' . $this->
getTree()->getTreePk() .
',child,parent,lft,rgt,depth) ' .
442 'VALUES (%s,%s,%s,%s,%s,%s)',
443 $this->db->quote($this->getTree()->getTreeId(),
'integer'),
444 $this->db->quote($a_node_id,
'integer'),
445 $this->db->quote($a_parent_id,
'integer'),
446 $this->db->quote($lft,
'integer'),
447 $this->db->quote($rgt,
'integer'),
448 $this->db->quote($depth,
'integer')
453 if ($this->
getTree()->__isMainTree()) {
454 $ilAtomQuery = $this->db->buildAtomQuery();
455 $ilAtomQuery->addTableLock(
'tree');
456 $ilAtomQuery->addQueryCallable($insert_node_callable);
459 $insert_node_callable($this->db);
468 $delete_tree_callable =
function (
ilDBInterface $db) use ($a_node_id):
void {
472 $query =
'SELECT * FROM ' . $this->
getTree()->getTreeTable() .
' ' .
473 'WHERE child = ' . $this->db->quote($a_node_id,
'integer') .
' ' .
474 'AND ' . $this->
getTree()->getTreePk() .
' = ' . $this->db->quote(
487 'DELETE FROM ' . $this->
getTree()->getTreeTable() .
' ' .
488 'WHERE lft BETWEEN %s AND %s ' .
489 'AND rgt BETWEEN %s AND %s ' .
490 'AND ' . $this->
getTree()->getTreePk() .
' = %s',
491 $this->db->quote($node[
'lft'],
'integer'),
492 $this->db->quote($node[
'rgt'],
'integer'),
493 $this->db->quote($node[
'lft'],
'integer'),
494 $this->db->quote($node[
'rgt'],
'integer'),
495 $this->db->quote($node[$this->
getTree()->getTreePk()],
'integer')
503 $diff = $node[
"rgt"] - $node[
"lft"] + 1;
505 $node[$this->
getTree()->getTreePk()] >= 0 &&
506 $node[
'rgt'] - $node[
'lft'] >= $this->
getTree()->getGap() * 2
508 if ($this->
getTree()->__isMainTree()) {
510 'UPDATE ' . $this->
getTree()->getTreeTable() .
' SET ' .
511 'lft = CASE WHEN lft > %s THEN lft - %s ELSE lft END, ' .
512 'rgt = CASE WHEN rgt > %s THEN rgt - %s ELSE rgt END ',
513 $this->db->quote($node[
'lft'],
'integer'),
514 $this->db->quote($diff,
'integer'),
515 $this->db->quote($node[
'lft'],
'integer'),
516 $this->db->quote($diff,
'integer')
518 $res = $this->db->manipulate(
$query);
521 'UPDATE ' . $this->
getTree()->getTreeTable() .
' SET ' .
522 'lft = CASE WHEN lft > %s THEN lft - %s ELSE lft END, ' .
523 'rgt = CASE WHEN rgt > %s THEN rgt - %s ELSE rgt END ' .
524 'WHERE ' . $this->
getTree()->getTreePk() .
' = %s ',
525 $this->db->quote($node[
'lft'],
'integer'),
526 $this->db->quote($diff,
'integer'),
527 $this->db->quote($node[
'lft'],
'integer'),
528 $this->db->quote($diff,
'integer'),
529 $this->db->quote($node[$this->
getTree()->getTreePk()],
'integer')
531 $res = $this->db->manipulate(
$query);
537 if ($this->
getTree()->__isMainTree()) {
538 $ilAtomQuery = $this->db->buildAtomQuery();
539 $ilAtomQuery->addTableLock(
'tree');
540 $ilAtomQuery->addQueryCallable($delete_tree_callable);
543 $delete_tree_callable($this->db);
552 $move_to_trash_callable =
function (
ilDBInterface $db) use ($a_node_id):
void {
553 $node = $this->
getTree()->getNodeTreeData($a_node_id);
555 $query =
'UPDATE ' . $this->
getTree()->getTreeTable() .
' ' .
556 'SET tree = ' . $this->db->quote(-1 * $node[
'child'],
'integer') .
' ' .
557 'WHERE ' . $this->
getTree()->getTreePk() .
' = ' . $this->db->quote(
561 'AND lft BETWEEN ' . $this->db->quote(
564 ) .
' AND ' . $this->db->quote($node[
'rgt'],
'integer') .
' ';
566 $this->db->manipulate(
$query);
571 if ($this->
getTree()->__isMainTree()) {
572 $ilAtomQuery = $this->db->buildAtomQuery();
573 $ilAtomQuery->addTableLock(
"tree");
574 $ilAtomQuery->addQueryCallable($move_to_trash_callable);
577 $move_to_trash_callable($this->db);
594 $takeId = $a_startnode_id == 0;
596 $depth_cache = $this->
getTree()->getDepthCache();
597 $parent_cache = $this->
getTree()->getParentCache();
600 $this->
getTree()->__isMainTree() &&
601 isset($depth_cache[$a_endnode_id]) &&
602 isset($parent_cache[$a_endnode_id])) {
603 $nodeDepth = $depth_cache[$a_endnode_id];
604 $parentId = $parent_cache[$a_endnode_id];
606 $nodeDepth = $this->
getTree()->getDepth($a_endnode_id);
607 $parentId = $this->
getTree()->getParentId($a_endnode_id);
616 } elseif ($nodeDepth == 1) {
617 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
619 $pathIds[] = $a_endnode_id;
621 } elseif ($nodeDepth == 2) {
622 $takeId = $takeId || $parentId == $a_startnode_id;
624 $pathIds[] = $parentId;
626 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
628 $pathIds[] = $a_endnode_id;
630 } elseif ($nodeDepth == 3) {
631 $takeId = $takeId || $this->
getTree()->getRootId() == $a_startnode_id;
633 $pathIds[] = $this->
getTree()->getRootId();
635 $takeId = $takeId || $parentId == $a_startnode_id;
637 $pathIds[] = $parentId;
639 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
641 $pathIds[] = $a_endnode_id;
643 } elseif ($nodeDepth < 32) {
653 $qSelect =
't1.child c0';
655 for (
$i = 1;
$i < $nodeDepth - 2;
$i++) {
656 $qSelect .=
', t' .
$i .
'.parent c' .
$i;
657 if ($this->
getTree()->__isMainTree()) {
658 $qJoin .=
' JOIN ' . $this->
getTree()->getTreeTable() .
' t' .
$i .
' ON ' .
659 't' .
$i .
'.child=t' . (
$i - 1) .
'.parent ';
661 $qJoin .=
' JOIN ' . $this->
getTree()->getTreeTable() .
' t' .
$i .
' ON ' .
662 't' .
$i .
'.child=t' . (
$i - 1) .
'.parent AND ' .
663 't' .
$i .
'.' . $this->
getTree()->getTreePk() .
' = ' . $this->
getTree()->getTreeId();
667 if ($this->
getTree()->__isMainTree()) {
668 $types = array(
'integer');
669 $data = array($parentId);
670 $query =
'SELECT ' . $qSelect .
' ' .
671 'FROM ' . $this->
getTree()->getTreeTable() .
' t0 ' . $qJoin .
' ' .
672 'WHERE t0.child = %s ';
674 $types = array(
'integer',
'integer');
675 $data = array($this->
getTree()->getTreeId(), $parentId);
676 $query =
'SELECT ' . $qSelect .
' ' .
677 'FROM ' . $this->
getTree()->getTreeTable() .
' t0 ' . $qJoin .
' ' .
678 'WHERE t0.' . $this->
getTree()->getTreePk() .
' = %s ' .
679 'AND t0.child = %s ';
682 $this->db->setLimit(1, 0);
685 if (
$res->numRows() == 0) {
689 $row = $this->db->fetchAssoc(
$res);
691 $takeId = $takeId || $this->
getTree()->getRootId() == $a_startnode_id;
693 $pathIds[] = $this->
getTree()->getRootId();
695 for (
$i = $nodeDepth - 4;
$i >= 0;
$i--) {
696 $takeId = $takeId || $row[
'c' .
$i] == $a_startnode_id;
698 $pathIds[] = (
int) $row[
'c' .
$i];
701 $takeId = $takeId || $parentId == $a_startnode_id;
703 $pathIds[] = $parentId;
705 $takeId = $takeId || $a_endnode_id == $a_startnode_id;
707 $pathIds[] = $a_endnode_id;
729 if ($this->
getTree()->__isMainTree()) {
730 $fields = array(
'integer');
731 $data = array($a_endnode_id);
732 $query =
"SELECT T2.child " .
733 "FROM " . $this->
getTree()->getTreeTable() .
" T1, " . $this->
getTree()->getTreeTable() .
" T2 " .
734 "WHERE T1.child = %s " .
735 "AND T1.lft BETWEEN T2.lft AND T2.rgt " .
738 $fields = array(
'integer',
'integer',
'integer');
739 $data = array($a_endnode_id, $this->
getTree()->getTreeId(), $this->
getTree()->getTreeId());
740 $query =
"SELECT T2.child " .
741 "FROM " . $this->
getTree()->getTreeTable() .
" T1, " . $this->
getTree()->getTreeTable() .
" T2 " .
742 "WHERE T1.child = %s " .
743 "AND T1.lft BETWEEN T2.lft AND T2.rgt " .
744 "AND T1." . $this->
getTree()->getTreePk() .
" = %s " .
745 "AND T2." . $this->
getTree()->getTreePk() .
" = %s " .
751 $takeId = $a_startnode_id == 0;
753 while ($row = $this->db->fetchAssoc(
$res)) {
754 if ($takeId || $row[
'child'] == $a_startnode_id) {
756 $pathIds[] = (
int) $row[
'child'];
765 public function moveTree(
int $a_source_id,
int $a_target_id,
int $a_position): void
767 $move_tree_callable =
function (
ilDBInterface $ilDB) use ($a_source_id, $a_target_id, $a_position):
void {
769 $query =
'SELECT * FROM ' . $this->
getTree()->getTreeTable() .
' ' .
770 'WHERE ( child = %s OR child = %s ) ' .
771 'AND ' . $this->
getTree()->getTreePk() .
' = %s ';
772 $res = $this->db->queryF(
$query, array(
'integer',
'integer',
'integer'), array(
779 if (
$res->numRows() != 2) {
783 $source_lft = $target_lft = $source_rgt = $target_rgt = $source_depth = $target_depth = $source_parent = 0;
784 while ($row = $this->db->fetchObject(
$res)) {
785 if ($row->child == $a_source_id) {
786 $source_lft = $row->lft;
787 $source_rgt = $row->rgt;
788 $source_depth = $row->depth;
789 $source_parent = $row->parent;
791 $target_lft = $row->lft;
792 $target_rgt = $row->rgt;
793 $target_depth = $row->depth;
798 if ($target_lft >= $source_lft && $target_rgt <= $source_rgt) {
805 $spread_diff = $source_rgt - $source_lft + 1;
806 #var_dump("<pre>","SPREAD_DIFF: ",$spread_diff,"<pre>"); 808 $query =
'UPDATE ' . $this->
getTree()->getTreeTable() .
' SET ' .
809 'lft = CASE WHEN lft > %s THEN lft + %s ELSE lft END, ' .
810 'rgt = CASE WHEN rgt >= %s THEN rgt + %s ELSE rgt END ';
812 if ($this->
getTree()->__isMainTree()) {
813 $res = $this->db->manipulateF(
$query, array(
'integer',
'integer',
'integer',
'integer'), [
820 $query .= (
'WHERE ' . $this->
getTree()->getTreePk() .
' = %s ');
821 $res = $this->db->manipulateF(
823 array(
'integer',
'integer',
'integer',
'integer',
'integer'),
836 if ($source_lft > $target_rgt) {
837 $where_offset = $spread_diff;
838 $move_diff = $target_rgt - $source_lft - $spread_diff;
841 $move_diff = $target_rgt - $source_lft;
843 $depth_diff = $target_depth - $source_depth + 1;
845 $query =
'UPDATE ' . $this->
getTree()->getTreeTable() .
' SET ' .
846 'parent = CASE WHEN parent = %s THEN %s ELSE parent END, ' .
849 'depth = depth + %s ' .
853 if ($this->
getTree()->__isMainTree()) {
854 $res = $this->db->manipulateF(
856 array(
'integer',
'integer',
'integer',
'integer',
'integer',
'integer',
'integer'),
863 $source_lft + $where_offset,
864 $source_rgt + $where_offset
869 $res = $this->db->manipulateF(
871 array(
'integer',
'integer',
'integer',
'integer',
'integer',
'integer',
'integer',
'integer'),
878 $source_lft + $where_offset,
879 $source_rgt + $where_offset,
886 $query =
'UPDATE ' . $this->
getTree()->getTreeTable() .
' SET ' .
887 'lft = CASE WHEN lft >= %s THEN lft - %s ELSE lft END, ' .
888 'rgt = CASE WHEN rgt >= %s THEN rgt - %s ELSE rgt END ';
890 if ($this->
getTree()->__isMainTree()) {
891 $res = $this->db->manipulateF(
$query, array(
'integer',
'integer',
'integer',
'integer'), [
892 $source_lft + $where_offset,
894 $source_rgt + $where_offset,
898 $query .= (
'WHERE ' . $this->
getTree()->getTreePk() .
' = %s ');
900 $res = $this->db->manipulateF(
902 array(
'integer',
'integer',
'integer',
'integer',
'integer'),
904 $source_lft + $where_offset,
906 $source_rgt + $where_offset,
914 if ($this->
getTree()->__isMainTree()) {
915 $ilAtomQuery = $this->db->buildAtomQuery();
916 $ilAtomQuery->addTableLock(
'tree');
917 $ilAtomQuery->addQueryCallable($move_tree_callable);
920 $move_tree_callable($this->db);
930 $query =
"SELECT t2.lft lft, t2.rgt rgt, t2.child child, t2.parent parent, type " .
931 "FROM " . $this->
getTree()->getTreeTable() .
" t1 " .
932 "JOIN " . $this->
getTree()->getTreeTable() .
" t2 ON (t2.lft BETWEEN t1.lft AND t1.rgt) " .
933 "JOIN " . $this->
getTree()->getTableReference() .
" obr ON t2.child = obr.ref_id " .
934 "JOIN " . $this->
getTree()->getObjectDataTable() .
" obd ON obr.obj_id = obd.obj_id " .
935 "WHERE t1.child = " . $this->db->quote($a_endnode_id,
'integer') .
" " .
936 "AND t1." . $this->
getTree()->getTreePk() .
" = " . $this->db->quote(
940 "AND t2." . $this->
getTree()->getTreePk() .
" = " . $this->db->quote(
949 $nodes[(
int) $row->child][
'lft'] = (
int) $row->lft;
950 $nodes[(
int) $row->child][
'rgt'] = (
int) $row->rgt;
951 $nodes[(
int) $row->child][
'child'] = (
int) $row->child;
952 $nodes[(
int) $row->child][
'parent'] = (
int) $row->parent;
953 $nodes[(
int) $row->child][
'type'] = (
string) $row->type;
965 $query =
'select ' . $this->
getTree()->getTreePk() .
', child from ' . $this->
getTree()->getTreeTable() .
' child where not exists ' .
967 'select child from ' . $this->
getTree()->getTreeTable() .
' parent where child.parent = parent.child and (parent.lft < child.lft) and (parent.rgt > child.rgt) ' .
969 'and ' . $this->
getTree()->getTreePk() .
' = ' . $this->
getTree()->getTreeId() .
' and child <> 1';
974 $failures[] = $row[$this->
getTree()->getTreePk()];
Thrown if invalid tree strucutes are found.
insertNode(int $a_node_id, int $a_parent_id, int $a_pos)
getSubTreeQuery(array $a_node, array $a_types=[], bool $a_force_join_reference=true, array $a_fields=[])
Get subtree.
static getLogger(string $a_component_id)
Get component logger.
Base class for nested set path based trees.
getSubTreeIds(int $a_node_id)
Get subtree ids int[].
getPathIds(int $a_endnode, int $a_startnode=0)
Get path ids from a startnode to a given endnode.
getRelation(array $a_node_a, array $a_node_b)
Get relation of two nodes.
__construct(ilTree $a_tree)
Constructor.
deleteTree(int $a_node_id)
Delete tree.
moveTree(int $a_source_id, int $a_target_id, int $a_position)
Move a source subtree to target.
getSubtreeInfo(int $a_endnode_id)
getTrashSubTreeQuery(array $a_node, array $a_types, bool $a_force_join_reference=true, array $a_fields=[])
Get subtree query for trashed tree items.
validateParentRelations()
Validate the parent relations of the tree implementation For nested set, validate the lft...
getPathIdsUsingNestedSets(int $a_endnode_id, int $a_startnode_id=0)
get path from a given startnode to a given endnode if startnode is not given the rootnode is startnod...
Interface for tree implementations Currrently nested set or materialized path.
moveToTrash(int $a_node_id)
Move subtree to trash.
getPathIdsUsingAdjacencyMap(int $a_endnode_id, int $a_startnode_id=0)
get path from a given startnode to a given endnode if startnode is not given the rootnode is startnod...