4 include_once
'./Services/Tree/interfaces/interface.ilTreeImplementation.php';
27 $this->tree = $a_tree;
58 $node = $this->
getTree()->getNodeTreeData($a_node_id);
59 $query =
'SELECT child FROM ' . $this->
getTree()->getTreeTable() .
' ' .
60 'WHERE path BETWEEN ' .
61 $ilDB->quote($node[
'path'],
'text') .
' AND ' .
62 $ilDB->quote($node[
'path'] .
'.Z',
'text') .
' ' .
64 'AND ' . $this->
getTree()->getTreePk() .
' = %s';
68 array(
'integer',
'integer'),
71 while (
$row = $ilDB->fetchAssoc(
$res)) {
72 $childs[] =
$row[
'child'];
74 return $childs ? $childs :
array();
85 if ($a_node_a[
'child'] == $a_node_b[
'child']) {
89 if (stripos($a_node_a[
'path'], $a_node_b[
'path'] .
'.') === 0) {
93 if (stripos($a_node_b[
'path'], $a_node_a[
'path'] .
'.') === 0) {
97 $path_a = substr($a_node_a[
'path'], 0, strrpos($a_node_a[
'path'],
'.'));
98 $path_b = substr($a_node_b[
'path'], 0, strrpos($a_node_b[
'path'],
'.'));
102 if ($a_node_a[
'path'] and (strcmp($path_a, $path_b) === 0)) {
125 if (is_array($a_types)) {
127 $type_str =
"AND " . $ilDB->in($this->
getTree()->getObjectDataTable() .
".type", $a_types,
false,
"text");
129 } elseif (strlen($a_types)) {
130 $type_str =
"AND " . $this->
getTree()->getObjectDataTable() .
".type = " . $ilDB->quote($a_types,
"text");
134 if ($type_str or $a_force_join_reference) {
135 $join = $this->
getTree()->buildJoin();
139 if (count($a_fields)) {
140 $fields = implode(
',', $a_fields);
146 'FROM ' . $this->
getTree()->getTreeTable() .
' ' .
148 'WHERE ' . $this->
getTree()->getTreeTable() .
'.path ' .
150 $ilDB->quote($a_node[
'path'],
'text') .
' AND ' .
151 $ilDB->quote($a_node[
'path'] .
'.Z',
'text') .
' ' .
152 'AND ' . $this->
getTree()->getTreeTable() .
'.' . $this->
getTree()->getTreePk() .
' = ' . $ilDB->quote($this->
getTree()->getTreeId(),
'integer') .
' ' .
154 'ORDER BY ' . $this->
getTree()->getTreeTable() .
'.path';
170 $query =
'SELECT path FROM ' . $this->
getTree()->getTreeTable() .
' ' .
171 'WHERE child = ' . $ilDB->quote($a_endnode,
'integer') .
' ';
175 while (
$row = $ilDB->fetchAssoc(
$res)) {
179 $pathIds = explode(
'.',
$path);
181 if ($a_startnode != 0) {
182 while (count($pathIds) > 0 && $pathIds[0] != $a_startnode) {
183 array_shift($pathIds);
201 $insert_node_callable =
function (
ilDBInterface $ilDB) use ($a_node_id, $a_parent_id, $a_pos) {
205 $res = $ilDB->queryF(
206 'SELECT parent, depth, path FROM ' . $this->
getTree()->getTreeTable() .
' ' .
207 'WHERE child = %s ' .
' ' .
208 'AND ' . $this->
getTree()->getTreePk() .
' = %s',
209 array(
'integer',
'integer'),
214 $r = $ilDB->fetchObject(
$res);
216 if (
$r->parent === null) {
221 if (
$r->depth >= $this->getMaximumPossibleDepth()) {
226 $parentPath =
$r->path;
227 $depth =
$r->depth + 1;
233 'child' =>
array(
'integer', $a_node_id),
234 'parent' =>
array(
'integer', $a_parent_id),
235 'lft' =>
array(
'integer', $lft),
236 'rgt' =>
array(
'integer', $rgt),
237 'depth' =>
array(
'integer', $depth),
238 'path' =>
array(
'text', $parentPath .
"." . $a_node_id)));
243 if ($this->
getTree()->__isMainTree()) {
244 $ilAtomQuery = $ilDB->buildAtomQuery();
245 $ilAtomQuery->addTableLock(
"tree");
247 $ilAtomQuery->addQueryCallable($insert_node_callable);
251 $insert_node_callable($ilDB);
266 $query =
'SELECT * FROM ' . $this->
getTree()->getTreeTable() .
' ' .
267 'WHERE ' . $this->
getTree()->getTreeTable() .
'.child = %s ' .
268 'AND ' . $this->
getTree()->getTreeTable() .
'.' . $this->
getTree()->getTreePk() .
' = %s ';
271 $this->
getTree()->getTreeId()));
274 $query =
'DELETE FROM ' . $this->
getTree()->getTreeTable() .
' ' .
275 'WHERE path BETWEEN ' . $ilDB->quote(
$row[
'path'],
'text') .
' ' .
276 'AND ' . $ilDB->quote(
$row[
'path'] .
'.Z',
'text') .
' ' .
277 'AND ' . $this->
getTree()->getTreePk() .
' = ' . $ilDB->quote($this->
getTree()->getTreeId(),
'integer');
278 $ilDB->manipulate(
$query);
282 if ($this->
getTree()->__isMainTree()) {
283 $ilAtomQuery = $ilDB->buildAtomQuery();
284 $ilAtomQuery->addTableLock(
'tree');
285 $ilAtomQuery->addQueryCallable($delete_tree_callable);
288 $delete_tree_callable($ilDB);
305 $node = $this->
getTree()->getNodeTreeData($a_node_id);
310 UPDATE ' . $this->
getTree()->getTreeTable() .
' ' .
311 'SET tree = %s' .
' ' .
312 'WHERE ' . $this->
getTree()->getTreePk() .
' = %s ' .
313 'AND path BETWEEN %s AND %s',
314 array(
'integer',
'integer',
'text',
'text'),
315 array(-$a_node_id, $this->
getTree()->getTreeId(), $node[
'path'], $node[
'path'] .
'.Z')
321 if ($this->
getTree()->__isMainTree()) {
322 $ilAtomQuery = $ilDB->buildAtomQuery();
323 $ilAtomQuery->addTableLock(
"tree");
325 $ilAtomQuery->addQueryCallable($move_to_trash_callable);
329 $move_to_trash_callable($ilDB);
344 public function moveTree($a_source_id, $a_target_id, $a_position)
348 $move_tree_callable =
function (
ilDBInterface $ilDB) use ($a_source_id, $a_target_id, $a_position) {
353 'SELECT depth, child, parent, path FROM ' . $this->
getTree()->getTreeTable() .
' ' .
354 'WHERE ' . $ilDB->in(
'child',
array($a_source_id, $a_target_id),
false,
'integer') .
' ' .
355 'AND tree = ' . $ilDB->quote($this->
getTree()->getTreeId(),
'integer')
359 if ($ilDB->numRows(
$res) != 2) {
364 while (
$row = $ilDB->fetchObject(
$res)) {
365 if (
$row->child == $a_source_id) {
366 $source_path =
$row->path;
367 $source_depth =
$row->depth;
368 $source_parent =
$row->parent;
370 $target_path =
$row->path;
371 $target_depth =
$row->depth;
375 if ($target_depth >= $source_depth) {
381 $res = $ilDB->queryF(
382 'SELECT MAX(depth) max_depth ' .
383 'FROM ' . $this->
getTree()->getTreeTable() .
' ' .
384 'WHERE path BETWEEN %s AND %s' .
' ' .
386 array(
'text',
'text',
'integer'),
387 array($source_path, $source_path .
'.Z', $this->
getTree()->getTreeId())
392 if (
$row->max_depth - $source_depth + $target_depth + 1 > $this->getMaximumPossibleDepth()) {
398 if (substr($target_path .
'.', 0, strlen($source_path) .
'.') == $source_path .
'.') {
402 $depth_diff = $target_depth - $source_depth + 1;
406 UPDATE ' . $this->
getTree()->getTreeTable() .
' 407 SET parent = CASE WHEN parent = ' . $ilDB->quote($source_parent,
'integer') .
' 408 THEN ' . $ilDB->quote($a_target_id,
'integer') .
' 411 path = ' . $ilDB->concat(
array(
412 array($ilDB->quote($target_path,
'text'),
'text'),
413 array($ilDB->substr(
'path', strrpos(
'.' . $source_path,
'.')),
'text'))) .
' , 415 depth = depth + ' . $ilDB->quote($depth_diff,
'integer') .
' 417 WHERE path BETWEEN ' . $ilDB->quote($source_path,
'text') .
' 418 AND ' . $ilDB->quote($source_path .
'.Z',
'text') .
' 420 AND tree = ' . $ilDB->quote($this->
getTree()->getTreeId(),
'integer');
424 $ilDB->manipulate(
$query);
428 if ($this->
getTree()->__isMainTree()) {
429 $ilAtomQuery = $ilDB->buildAtomQuery();
430 $ilAtomQuery->addTableLock(
"tree");
431 $ilAtomQuery->addQueryCallable($move_tree_callable);
434 $move_tree_callable($ilDB);
445 $r = $ilDB->queryF(
'SELECT DISTINCT * FROM tree WHERE parent = %s',
array(
'integer'),
array(0));
447 while (
$row = $ilDB->fetchAssoc(
$r)) {
448 $success = self::createMaterializedPath(0,
'');
464 SET path = CONCAT(COALESCE(' . $ilDB->quote($parentPath,
'text') .
', \'\'), COALESCE( ' . $ilDB->cast(
"child",
"text") .
' , \'\')) 466 $r = $ilDB->manipulateF($q,
array(
'integer'),
array($parent));
468 $r = $ilDB->queryF(
'SELECT child FROM tree WHERE parent = %s',
array(
'integer'),
array($parent));
470 while (
$row = $ilDB->fetchAssoc(
$r)) {
471 self::createMaterializedPath(
$row[
'child'], $parentPath .
$row[
'child'] .
'.');
489 $query =
"SELECT t2.child child, type, t2.path path " .
490 "FROM " . $this->
getTree()->getTreeTable() .
" t1 " .
491 "JOIN " . $this->
getTree()->getTreeTable() .
" t2 ON (t2.path BETWEEN t1.path AND CONCAT(t1.path, '.Z')) " .
492 "JOIN " . $this->
getTree()->getTableReference() .
" obr ON t2.child = obr.ref_id " .
493 "JOIN " . $this->
getTree()->getObjectDataTable() .
" obd ON obr.obj_id = obd.obj_id " .
494 "WHERE t1.child = " . $ilDB->quote($a_endnode_id,
'integer') .
" " .
495 "AND t1." . $this->
getTree()->getTreePk() .
" = " . $ilDB->quote($this->
getTree()->getTreeId(),
'integer') .
" " .
496 "AND t2." . $this->
getTree()->getTreePk() .
" = " . $ilDB->quote($this->
getTree()->getTreeId(),
'integer') .
" " .
503 #$nodes[$row->child]['lft'] = $row->lft; 504 #$nodes[$row->child]['rgt'] = $row->rgt; 505 $nodes[
$row->child][
'child'] =
$row->child;
506 $nodes[
$row->child][
'type'] =
$row->type;
507 $nodes[
$row->child][
'path'] =
$row->path;
510 $depth_first_compare =
function ($a, $b) {
511 $a_exploded = explode(
'.', $a[
'path']);
512 #ilLoggerFactory::getLogger('tree')->debug(print_r($a_exploded,TRUE)); 513 $b_exploded = explode(
'.', $b[
'path']);
516 foreach ($a_exploded as $num) {
517 $a_padded .= (str_pad((
string) $num, 14,
'0', STR_PAD_LEFT));
520 foreach ($b_exploded as $num) {
521 $b_padded .= (str_pad((
string) $num, 14,
'0', STR_PAD_LEFT));
524 #ilLoggerFactory::getLogger('tree')->debug($a_padded); 525 return strcasecmp($a_padded, $b_padded);
528 #ilLoggerFactory::getLogger('tree')->debug(print_r($nodes,TRUE)); 530 uasort($nodes, $depth_first_compare);
532 #ilLoggerFactory::getLogger('tree')->debug(print_r($nodes,TRUE)); 534 return (
array) $nodes;
545 $query =
'select child from ' . $this->
getTree()->getTreeTable() .
' child where not exists ' .
547 'select child from ' . $this->
getTree()->getTreeTable() .
' parent where child.parent = parent.child and ' .
548 '(child.path BETWEEN parent.path AND CONCAT(parent.path,' . $ilDB->quote(
'Z',
'text') .
') )' .
')' .
549 'and ' . $this->
getTree()->getTreePk() .
' = ' . $this->
getTree()->getTreeId() .
' and child <> 1';
Thrown if invalid tree strucutes are found.
getMaximumPossibleDepth()
Get maximum possible depth.
deleteTree($a_node_id)
Delete a subtree.
static createMaterializedPath($parent, $parentPath)
static createFromParentReleation()
validateParentRelations()
Validaate parent relations.
foreach($_POST as $key=> $value) $res
getRelation($a_node_a, $a_node_b)
Get relation of two nodes.
getSubTreeQuery($a_node, $a_types='', $a_force_join_reference=true, $a_fields=array())
Get subtree query.
moveToTrash($a_node_id)
Move subtree to trash.
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
Create styles array
The data for the language used.
getTree()
Get tree object.
moveTree($a_source_id, $a_target_id, $a_position)
move source subtree to target node
insertNode($a_node_id, $a_parent_id, $a_pos)
Insert new node under parent node.
getSubtreeInfo($a_endnode_id)
Base class for materialize path based trees Based on implementation of Werner Randelshofer.
static getLogger($a_component_id)
Get component logger.
getPathIds($a_endnode, $a_startnode=0)
Get path ids.
Interface for tree implementations Currrently nested set or materialize path.
getSubTreeIds($a_node_id)
Get subtree ids.
__construct(ilTree $a_tree)
Constructor.