4 include_once
'./Services/Tree/interfaces/interface.ilTreeImplementation.php';
27 $this->tree = $a_tree;
60 $node = $this->
getTree()->getNodeTreeData($a_node_id);
61 $query =
'SELECT child FROM ' . $this->
getTree()->getTreeTable() .
' ' .
62 'WHERE path BETWEEN ' .
63 $ilDB->quote($node[
'path'],
'text') .
' AND ' .
64 $ilDB->quote($node[
'path'] .
'.Z',
'text') .
' ' .
66 'AND ' . $this->
getTree()->getTreePk() .
' = %s';
70 array(
'integer',
'integer'),
71 array($a_node_id, $this->
getTree()->getTreeId())
74 $childs[] =
$row[
'child'];
76 return $childs ? $childs : array();
87 if ($a_node_a[
'child'] == $a_node_b[
'child']) {
91 if (stripos($a_node_a[
'path'], $a_node_b[
'path'] .
'.') === 0) {
95 if (stripos($a_node_b[
'path'], $a_node_a[
'path'] .
'.') === 0) {
99 $path_a = substr($a_node_a[
'path'], 0, strrpos($a_node_a[
'path'],
'.'));
100 $path_b = substr($a_node_b[
'path'], 0, strrpos($a_node_b[
'path'],
'.'));
104 if ($a_node_a[
'path']
and (strcmp($path_a, $path_b) === 0)) {
122 public function getSubTreeQuery($a_node, $a_types =
'', $a_force_join_reference =
true, $a_fields = array())
126 $ilDB = $DIC[
'ilDB'];
129 if (is_array($a_types)) {
131 $type_str =
"AND " .
$ilDB->in($this->
getTree()->getObjectDataTable() .
".type", $a_types,
false,
"text");
133 } elseif (strlen($a_types)) {
134 $type_str =
"AND " . $this->
getTree()->getObjectDataTable() .
".type = " .
$ilDB->quote($a_types,
"text");
138 if ($type_str
or $a_force_join_reference) {
139 $join = $this->
getTree()->buildJoin();
143 if (count($a_fields)) {
144 $fields = implode(
',', $a_fields);
150 'FROM ' . $this->
getTree()->getTreeTable() .
' ' .
152 'WHERE ' . $this->
getTree()->getTreeTable() .
'.path ' .
154 $ilDB->quote($a_node[
'path'],
'text') .
' AND ' .
155 $ilDB->quote($a_node[
'path'] .
'.Z',
'text') .
' ' .
156 'AND ' . $this->
getTree()->getTreeTable() .
'.' . $this->
getTree()->getTreePk() .
' = ' .
$ilDB->quote($this->
getTree()->getTreeId(),
'integer') .
' ' .
158 'ORDER BY ' . $this->
getTree()->getTreeTable() .
'.path';
173 $ilDB = $DIC[
'ilDB'];
176 $query =
'SELECT path FROM ' . $this->
getTree()->getTreeTable() .
' ' .
177 'WHERE child = ' .
$ilDB->quote($a_endnode,
'integer') .
' ';
185 $pathIds = explode(
'.',
$path);
187 if ($a_startnode != 0) {
188 while (count($pathIds) > 0 && $pathIds[0] != $a_startnode) {
189 array_shift($pathIds);
207 $ilDB = $DIC[
'ilDB'];
209 $insert_node_callable =
function (
ilDBInterface $ilDB) use ($a_node_id, $a_parent_id, $a_pos) {
214 'SELECT parent, depth, path FROM ' . $this->
getTree()->getTreeTable() .
' ' .
215 'WHERE child = %s ' .
' ' .
216 'AND ' . $this->
getTree()->getTreePk() .
' = %s',
217 array(
'integer',
'integer'),
218 array($a_parent_id, $this->
getTree()->getTreeId())
224 if (
$r->parent === null) {
229 if (
$r->depth >= $this->getMaximumPossibleDepth()) {
234 $parentPath =
$r->path;
235 $depth =
$r->depth + 1;
240 $ilDB->insert($this->
getTree()->getTreeTable(), array($this->
getTree()->getTreePk() => array(
'integer', $this->
getTree()->getTreeId()),
241 'child' => array(
'integer', $a_node_id),
242 'parent' => array(
'integer', $a_parent_id),
243 'lft' => array(
'integer', $lft),
244 'rgt' => array(
'integer', $rgt),
245 'depth' => array(
'integer', $depth),
246 'path' => array(
'text', $parentPath .
"." . $a_node_id)));
251 if ($this->
getTree()->__isMainTree()) {
252 $ilAtomQuery =
$ilDB->buildAtomQuery();
253 $ilAtomQuery->addTableLock(
"tree");
255 $ilAtomQuery->addQueryCallable($insert_node_callable);
259 $insert_node_callable(
$ilDB);
274 $ilDB = $DIC[
'ilDB'];
276 $query =
'SELECT * FROM ' . $this->
getTree()->getTreeTable() .
' ' .
277 'WHERE ' . $this->
getTree()->getTreeTable() .
'.child = %s ' .
278 'AND ' . $this->
getTree()->getTreeTable() .
'.' . $this->
getTree()->getTreePk() .
' = %s ';
281 $this->
getTree()->getTreeId()));
284 $query =
'DELETE FROM ' . $this->
getTree()->getTreeTable() .
' ' .
285 'WHERE path BETWEEN ' .
$ilDB->quote(
$row[
'path'],
'text') .
' ' .
286 'AND ' .
$ilDB->quote(
$row[
'path'] .
'.Z',
'text') .
' ' .
287 'AND ' . $this->
getTree()->getTreePk() .
' = ' .
$ilDB->quote($this->
getTree()->getTreeId(),
'integer');
292 if ($this->
getTree()->__isMainTree()) {
293 $ilAtomQuery =
$ilDB->buildAtomQuery();
294 $ilAtomQuery->addTableLock(
'tree');
295 $ilAtomQuery->addQueryCallable($delete_tree_callable);
298 $delete_tree_callable(
$ilDB);
314 $ilDB = $DIC[
'ilDB'];
317 $node = $this->
getTree()->getNodeTreeData($a_node_id);
322 UPDATE ' . $this->
getTree()->getTreeTable() .
' ' .
323 'SET tree = %s' .
' ' .
324 'WHERE ' . $this->
getTree()->getTreePk() .
' = %s ' .
325 'AND path BETWEEN %s AND %s',
326 array(
'integer',
'integer',
'text',
'text'),
327 array(-$a_node_id, $this->
getTree()->getTreeId(), $node[
'path'], $node[
'path'] .
'.Z')
333 if ($this->
getTree()->__isMainTree()) {
334 $ilAtomQuery =
$ilDB->buildAtomQuery();
335 $ilAtomQuery->addTableLock(
"tree");
337 $ilAtomQuery->addQueryCallable($move_to_trash_callable);
341 $move_to_trash_callable(
$ilDB);
356 public function moveTree($a_source_id, $a_target_id, $a_position)
360 $ilDB = $DIC[
'ilDB'];
362 $move_tree_callable =
function (
ilDBInterface $ilDB) use ($a_source_id, $a_target_id, $a_position) {
367 'SELECT depth, child, parent, path FROM ' . $this->
getTree()->getTreeTable() .
' ' .
368 'WHERE ' .
$ilDB->in(
'child', array($a_source_id, $a_target_id),
false,
'integer') .
' ' .
369 'AND tree = ' .
$ilDB->quote($this->
getTree()->getTreeId(),
'integer')
379 if (
$row->child == $a_source_id) {
380 $source_path =
$row->path;
381 $source_depth =
$row->depth;
382 $source_parent =
$row->parent;
384 $target_path =
$row->path;
385 $target_depth =
$row->depth;
389 if ($target_depth >= $source_depth) {
396 'SELECT MAX(depth) max_depth ' .
397 'FROM ' . $this->
getTree()->getTreeTable() .
' ' .
398 'WHERE path BETWEEN %s AND %s' .
' ' .
400 array(
'text',
'text',
'integer'),
401 array($source_path, $source_path .
'.Z', $this->
getTree()->getTreeId())
406 if (
$row->max_depth - $source_depth + $target_depth + 1 > $this->getMaximumPossibleDepth()) {
412 if (substr($target_path .
'.', 0, strlen($source_path) .
'.') == $source_path .
'.') {
416 $depth_diff = $target_depth - $source_depth + 1;
420 UPDATE ' . $this->
getTree()->getTreeTable() .
' 421 SET parent = CASE WHEN parent = ' .
$ilDB->quote($source_parent,
'integer') .
' 422 THEN ' .
$ilDB->quote($a_target_id,
'integer') .
' 425 path = ' .
$ilDB->concat(array(
426 array(
$ilDB->quote($target_path,
'text'),
'text'),
427 array(
$ilDB->substr(
'path', strrpos(
'.' . $source_path,
'.')),
'text'))) .
' , 429 depth = depth + ' .
$ilDB->quote($depth_diff,
'integer') .
' 431 WHERE path BETWEEN ' .
$ilDB->quote($source_path,
'text') .
' 432 AND ' .
$ilDB->quote($source_path .
'.Z',
'text') .
' 434 AND tree = ' .
$ilDB->quote($this->
getTree()->getTreeId(),
'integer');
442 if ($this->
getTree()->__isMainTree()) {
443 $ilAtomQuery =
$ilDB->buildAtomQuery();
444 $ilAtomQuery->addTableLock(
"tree");
445 $ilAtomQuery->addQueryCallable($move_tree_callable);
448 $move_tree_callable(
$ilDB);
459 $ilDB = $DIC[
'ilDB'];
461 $r =
$ilDB->queryF(
'SELECT DISTINCT * FROM tree WHERE parent = %s', array(
'integer'), array(0));
464 $success = self::createMaterializedPath(0,
'');
480 $ilDB = $DIC[
'ilDB'];
482 SET path = CONCAT(COALESCE(' .
$ilDB->quote($parentPath,
'text') .
', \'\'), COALESCE( ' .
$ilDB->cast(
"child",
"text") .
' , \'\')) 484 $r =
$ilDB->manipulateF($q, array(
'integer'), array($parent));
486 $r =
$ilDB->queryF(
'SELECT child FROM tree WHERE parent = %s', array(
'integer'), array($parent));
489 self::createMaterializedPath(
$row[
'child'], $parentPath .
$row[
'child'] .
'.');
503 $ilDB = $DIC[
'ilDB'];
509 $query =
"SELECT t2.child child, type, t2.path path " .
510 "FROM " . $this->
getTree()->getTreeTable() .
" t1 " .
511 "JOIN " . $this->
getTree()->getTreeTable() .
" t2 ON (t2.path BETWEEN t1.path AND CONCAT(t1.path, '.Z')) " .
512 "JOIN " . $this->
getTree()->getTableReference() .
" obr ON t2.child = obr.ref_id " .
513 "JOIN " . $this->
getTree()->getObjectDataTable() .
" obd ON obr.obj_id = obd.obj_id " .
514 "WHERE t1.child = " .
$ilDB->quote($a_endnode_id,
'integer') .
" " .
515 "AND t1." . $this->
getTree()->getTreePk() .
" = " .
$ilDB->quote($this->
getTree()->getTreeId(),
'integer') .
" " .
516 "AND t2." . $this->
getTree()->getTreePk() .
" = " .
$ilDB->quote($this->
getTree()->getTreeId(),
'integer') .
" " .
523 #$nodes[$row->child]['lft'] = $row->lft; 524 #$nodes[$row->child]['rgt'] = $row->rgt; 530 $depth_first_compare =
function ($a, $b) {
531 $a_exploded = explode(
'.', $a[
'path']);
532 #ilLoggerFactory::getLogger('tree')->debug(print_r($a_exploded,TRUE)); 533 $b_exploded = explode(
'.', $b[
'path']);
536 foreach ($a_exploded as $num) {
537 $a_padded .= (str_pad((
string) $num, 14,
'0', STR_PAD_LEFT));
540 foreach ($b_exploded as $num) {
541 $b_padded .= (str_pad((
string) $num, 14,
'0', STR_PAD_LEFT));
544 #ilLoggerFactory::getLogger('tree')->debug($a_padded); 545 return strcasecmp($a_padded, $b_padded);
548 #ilLoggerFactory::getLogger('tree')->debug(print_r($nodes,TRUE)); 550 uasort(
$nodes, $depth_first_compare);
552 #ilLoggerFactory::getLogger('tree')->debug(print_r($nodes,TRUE)); 565 $ilDB = $DIC[
'ilDB'];
567 $query =
'select child from ' . $this->
getTree()->getTreeTable() .
' child where not exists ' .
569 'select child from ' . $this->
getTree()->getTreeTable() .
' parent where child.parent = parent.child and ' .
570 '(child.path BETWEEN parent.path AND CONCAT(parent.path,' .
$ilDB->quote(
'Z',
'text') .
') )' .
')' .
571 '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...
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.