ILIAS  Release_4_2_x_branch Revision 61807
 All Data Structures Namespaces Files Functions Variables Groups Pages
ilTree Class Reference

Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco. More...

+ Inheritance diagram for ilTree:
+ Collaboration diagram for ilTree:

Public Member Functions

 ilTree ($a_tree_id, $a_root_id=0)
 Constructor public.
 useCache ($a_use=true)
 Use Cache (usually activated)
 isCacheUsed ()
 Check if cache is active.
 initLangCode ()
 Store user language.
 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 a reference table.
 setReferenceTablePK ($a_column_name)
 set column containing primary key in reference table public
 setObjectTablePK ($a_column_name)
 set column containing primary key in object table public
 setTreeTablePK ($a_column_name)
 set column containing primary key in tree table public
 buildJoin ()
 build join depending on table settings private
 getChilds ($a_node_id, $a_order="", $a_direction="ASC")
 get child nodes of given node public
 getFilteredChilds ($a_filter, $a_node, $a_order="", $a_direction="ASC")
 get child nodes of given node (exclude filtered obj_types) public
 getChildsByType ($a_node_id, $a_type)
 get child nodes of given node by object type public
 getChildsByTypeFilter ($a_node_id, $a_types)
 get child nodes of given node by object type 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
 getFilteredSubTree ($a_node_id, $a_filter=array())
 get filtered subtree
 getSubTreeIds ($a_ref_id)
 Get all ids of subnodes.
 getSubTree ($a_node, $a_with_data=true, $a_type="")
 get all nodes in the subtree under specified node
 getSubTreeTypes ($a_node, $a_filter=0)
 get types of nodes in the subtree under specified node
 deleteTree ($a_node)
 delete node and the whole subtree under this node public
 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 startnode.
 getPathIdsUsingNestedSets ($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 startnode public
 getPathIdsUsingAdjacencyMap ($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 startnode public
 preloadDepthParent ($a_node_ids)
 Preload depth/parent.
 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 startnode public
 getNodePathForTitlePath ($titlePath, $a_startnode_id=null)
 Converts a path consisting of object titles into a path consisting of tree nodes.
 getNodePath ($a_endnode_id, $a_startnode_id=0)
 Returns the node path for the specified object reference.
 checkTree ()
 check consistence of tree all left & right values are checked if they are exists only once public
 checkTreeChilds ($a_no_zero_child=true)
 check, if all childs of tree nodes exist in object table
 getMaximumDepth ()
 Return the maximum depth in tree public.
 getDepth ($a_node_id)
 return depth of a node in tree private
 getNodeData ($a_node_id, $a_tree_pk=null)
 get all information of a node.
 fetchNodeData ($a_row)
 get data of parent node from tree and object_data private
 isInTree ($a_node_id)
 get all information of a node.
 getParentNodeData ($a_node_id)
 get data of parent node from tree and object_data public
 isGrandChild ($a_startnode_id, $a_querynode_id)
 checks if a node is in the path of an other node public
 addTree ($a_tree_id, $a_node_id=-1)
 create a new tree to do: ???
 getNodeDataByType ($a_type)
 get nodes by type // TODO: method needs revision
 removeTree ($a_tree_id)
 remove an existing tree
 saveSubTree ($a_node_id, $a_set_deleted=false)
 save subtree: delete a subtree (defined by node_id) to a new tree with $this->tree_id -node_id.
 isDeleted ($a_node_id)
 This is a wrapper for isSaved() with a more useful name.
 isSaved ($a_node_id)
 check if node is saved
 preloadDeleted ($a_node_ids)
 Preload deleted information.
 getSavedNodeData ($a_parent_id)
 get data saved/deleted nodes
 getParentId ($a_node_id)
 get parent id of given node public
 getLeftValue ($a_node_id)
 get left value of given node public
 getChildSequenceNumber ($a_node, $type="")
 get sequence number of node in sibling sequence public
 readRootId ()
 read root id from database
 getRootId ()
 get the root id of tree public
 setRootId ($a_root_id)
 getTreeId ()
 get tree id public
 setTreeId ($a_tree_id)
 set tree id public
 fetchSuccessorNode ($a_node_id, $a_type="")
 get node data of successor node
 fetchPredecessorNode ($a_node_id, $a_type="")
 get node data of predecessor node
 renumber ($node_id=1, $i=1)
 Wrapper for renumber.
 __renumber ($node_id=1, $i=1)
 This method is private.
 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 => checkForParentType(3,'crs');.
 _removeEntry ($a_tree, $a_child, $a_db_table="tree")
 STATIC METHOD Removes a single entry from a tree.
 __isMainTree ()
 Check if operations are done on main tree.
 __checkDelete ($a_node)
 Check for deleteTree() compares a subtree of a given node by checking lft, rgt against parent relation.
 __getSubTreeByParentRelation ($a_node_id, &$parent_childs)
 __validateSubtrees (&$lft_childs, $parent_childs)
 moveTree ($a_source_id, $a_target_id, $a_location=IL_LAST_NODE)
 Move Tree Implementation.
 getRbacSubtreeInfo ($a_endnode_id)
 This method is used for change existing objects and returns all necessary information for this action.

Data Fields

 $ilias
 $log
 $root_id
 $tree_id
 $table_tree
 $table_obj_data
 $table_obj_reference
 $ref_pk
 $obj_pk
 $tree_pk
 $gap

Protected Member Functions

 fetchTranslationFromObjectDataCache ($a_obj_ids)
 Get translation data from object cache (trigger in object cache on preload)

Protected Attributes

 $depth_cache = array()
 $parent_cache = array()

Detailed Description

Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco.

Author
Sascha Hofmann sasch.nosp@m.ahof.nosp@m.mann@.nosp@m.gmx..nosp@m.de
Stefan Meyer meyer.nosp@m.@lei.nosp@m.fos.c.nosp@m.om
Version
Id:
class.ilTree.php 47422 2014-01-22 09:21:04Z jluetzen

Definition at line 21 of file class.ilTree.php.

Member Function Documentation

ilTree::__checkDelete (   $a_node)

Check for deleteTree() compares a subtree of a given node by checking lft, rgt against parent relation.

private

Parameters
arraynode data from ilTree::getNodeData()
Returns
boolean

Definition at line 2877 of file class.ilTree.php.

References $ilDB, $query, $res, $row, __getSubTreeByParentRelation(), and __validateSubtrees().

Referenced by deleteTree().

{
global $ilDB;
// get subtree by lft,rgt
$query = 'SELECT * FROM '.$this->table_tree.' '.
'WHERE lft >= %s '.
'AND rgt <= %s '.
'AND '.$this->tree_pk.' = %s ';
$res = $ilDB->queryF($query,array('integer','integer','integer'),array(
$a_node['lft'],
$a_node['rgt'],
$a_node[$this->tree_pk]));
$counter = (int) $lft_childs = array();
while($row = $ilDB->fetchObject($res))
{
$lft_childs[$row->child] = $row->parent;
++$counter;
}
// CHECK FOR DUPLICATE CHILD IDS
if($counter != count($lft_childs))
{
$message = sprintf('%s::__checkTree(): Duplicate entries for "child" in maintree! $a_node_id: %s',
get_class($this),
$a_node['child']);
$this->log->write($message,$this->log->FATAL);
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
// GET SUBTREE BY PARENT RELATION
$parent_childs = array();
$this->__getSubTreeByParentRelation($a_node['child'],$parent_childs);
$this->__validateSubtrees($lft_childs,$parent_childs);
return true;
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::__getSubTreeByParentRelation (   $a_node_id,
$parent_childs 
)

Definition at line 2916 of file class.ilTree.php.

References $ilDB, $query, $res, and $row.

Referenced by __checkDelete().

{
global $ilDB;
// GET PARENT ID
$query = 'SELECT * FROM '.$this->table_tree.' '.
'WHERE child = %s '.
'AND tree = %s ';
$res = $ilDB->queryF($query,array('integer','integer'),array(
$a_node_id,
$this->tree_id));
$counter = 0;
while($row = $ilDB->fetchObject($res))
{
$parent_childs[$a_node_id] = $row->parent;
++$counter;
}
// MULTIPLE ENTRIES
if($counter > 1)
{
$message = sprintf('%s::__getSubTreeByParentRelation(): Multiple entries in maintree! $a_node_id: %s',
get_class($this),
$a_node_id);
$this->log->write($message,$this->log->FATAL);
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
// GET ALL CHILDS
$query = 'SELECT * FROM '.$this->table_tree.' '.
'WHERE parent = %s ';
$res = $ilDB->queryF($query,array('integer'),array($a_node_id));
while($row = $ilDB->fetchObject($res))
{
// RECURSION
$this->__getSubTreeByParentRelation($row->child,$parent_childs);
}
return true;
}

+ Here is the caller graph for this function:

ilTree::__isMainTree ( )

Check if operations are done on main tree.

private

Returns
boolean

Definition at line 2864 of file class.ilTree.php.

Referenced by addTree(), checkForParentType(), deleteTree(), getChilds(), getNodeData(), getPathFull(), getPathId(), getPathIdsUsingAdjacencyMap(), getSubTree(), insertNode(), isCacheUsed(), isInTree(), isSaved(), moveTree(), preloadDeleted(), preloadDepthParent(), removeTree(), renumber(), and saveSubTree().

{
return $this->table_tree === 'tree';
}

+ Here is the caller graph for this function:

ilTree::__renumber (   $node_id = 1,
  $i = 1 
)

This method is private.

Always call ilTree->renumber() since it locks the tree table renumber left/right values and close the gaps in numbers (recursive) private

Parameters
integernode_id where to start (usually the root node)
integerfirst left value of start node (usually 1)
Returns
integer current left value of recursive call

Definition at line 2727 of file class.ilTree.php.

References $ilDB, $query, $res, and getChilds().

Referenced by renumber().

{
global $ilDB;
$query = 'UPDATE '.$this->table_tree.' SET lft = %s WHERE child = %s';
$res = $ilDB->manipulateF($query,array('integer','integer'),array(
$i,
$node_id));
$childs = $this->getChilds($node_id);
foreach ($childs as $child)
{
$i = $this->__renumber($child["child"],$i+1);
}
$i++;
// Insert a gap at the end of node, if the node has children
if (count($childs) > 0)
{
$i += $this->gap * 2;
}
$query = 'UPDATE '.$this->table_tree.' SET rgt = %s WHERE child = %s';
$res = $ilDB->manipulateF($query,array('integer','integer'),array(
$i,
$node_id));
return $i;
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::__validateSubtrees ( $lft_childs,
  $parent_childs 
)

Definition at line 2957 of file class.ilTree.php.

Referenced by __checkDelete().

{
// SORT BY KEY
ksort($lft_childs);
ksort($parent_childs);
if(count($lft_childs) != count($parent_childs))
{
$message = sprintf('%s::__validateSubtrees(): (COUNT) Tree is corrupted! Left/Right subtree does not comply .'.
'with parent relation',
get_class($this));
$this->log->write($message,$this->log->FATAL);
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
foreach($lft_childs as $key => $value)
{
if($parent_childs[$key] != $value)
{
$message = sprintf('%s::__validateSubtrees(): (COMPARE) Tree is corrupted! Left/Right subtree does not comply '.
'with parent relation',
get_class($this));
$this->log->write($message,$this->log->FATAL);
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
if($key == ROOT_FOLDER_ID)
{
$message = sprintf('%s::__validateSubtrees(): (ROOT_FOLDER) Tree is corrupted! Tried to delete root folder',
get_class($this));
$this->log->write($message,$this->log->FATAL);
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
}
return true;
}

+ Here is the caller graph for this function:

ilTree::_removeEntry (   $a_tree,
  $a_child,
  $a_db_table = "tree" 
)

STATIC METHOD Removes a single entry from a tree.

The tree structure is NOT updated!

public

Parameters
integertree id
integerchild id
stringdb_table name. default is 'tree' (optional)

Definition at line 2831 of file class.ilTree.php.

References $ilDB, $ilErr, $ilLog, $query, and $res.

Referenced by ilValidator\purgeObjects().

{
if($a_db_table === 'tree')
{
if($a_tree == 1 and $a_child == ROOT_FOLDER_ID)
{
$message = sprintf('%s::_removeEntry(): Tried to delete root node! $a_tree: %s $a_child: %s',
get_class($this),
$a_tree,
$a_child);
$ilLog->write($message,$ilLog->FATAL);
$ilErr->raiseError($message,$ilErr->WARNING);
}
}
$query = 'DELETE FROM '.$a_db_table.' '.
'WHERE tree = %s '.
'AND child = %s ';
$res = $ilDB->manipulateF($query,array('integer','integer'),array(
$a_tree,
$a_child));
}

+ Here is the caller graph for this function:

ilTree::addTree (   $a_tree_id,
  $a_node_id = -1 
)

create a new tree to do: ???

Parameters
integera_tree_id: obj_id of object where tree belongs to
integera_node_id: root node of tree (optional; default is tree_id itself)
Returns
boolean true on success public

Definition at line 2045 of file class.ilTree.php.

References $ilDB, $query, $res, and __isMainTree().

Referenced by ilWorkspaceExplorer\__construct(), and ilSCORMPackageParser\handlerBeginTag().

{
global $ilDB;
// FOR SECURITY addTree() IS NOT ALLOWED ON MAIN TREE
if($this->__isMainTree())
{
$message = sprintf('%s::addTree(): Operation not allowed on main tree! $a_tree_if: %s $a_node_id: %s',
get_class($this),
$a_tree_id,
$a_node_id);
$this->log->write($message,$this->log->FATAL);
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
if (!isset($a_tree_id))
{
$this->ilErr->raiseError(get_class($this)."::addTree(): No tree_id given! ",$this->ilErr->WARNING);
}
if ($a_node_id <= 0)
{
$a_node_id = $a_tree_id;
}
$query = 'INSERT INTO '.$this->table_tree.' ('.
$this->tree_pk.', child,parent,lft,rgt,depth) '.
'VALUES '.
'(%s,%s,%s,%s,%s,%s)';
$res = $ilDB->manipulateF($query,array('integer','integer','integer','integer','integer','integer'),array(
$a_tree_id,
$a_node_id,
0,
1,
2,
1));
return true;
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::buildJoin ( )

build join depending on table settings private

Returns
string

Definition at line 309 of file class.ilTree.php.

Referenced by fetchPredecessorNode(), fetchSuccessorNode(), getChildsByTypeFilter(), getChildSequenceNumber(), getNodeData(), getNodeDataByType(), getPathFull(), getSavedNodeData(), and getSubTree().

{
if ($this->table_obj_reference)
{
// Use inner join instead of left join to improve performance
return "JOIN ".$this->table_obj_reference." ON ".$this->table_tree.".child=".$this->table_obj_reference.".".$this->ref_pk." ".
"JOIN ".$this->table_obj_data." ON ".$this->table_obj_reference.".".$this->obj_pk."=".$this->table_obj_data.".".$this->obj_pk." ";
}
else
{
// Use inner join instead of left join to improve performance
return "JOIN ".$this->table_obj_data." ON ".$this->table_tree.".child=".$this->table_obj_data.".".$this->obj_pk." ";
}
}

+ Here is the caller graph for this function:

ilTree::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 => checkForParentType(3,'crs');.

public

Parameters
integerref_id
stringtype
Returns
mixed false if item is not in tree, int (object ref_id) > 0 if path container course, int 0 if pathc does not contain the object type

Definition at line 2769 of file class.ilTree.php.

References $path, __isMainTree(), getPathFull(), isCacheUsed(), and isInTree().

{
// #12577
$cache_key = $a_ref_id.'.'.$a_type.'.'.((int)$a_exclude_source_check);
// Try to return a cached result
if($this->isCacheUsed() &&
array_key_exists($cache_key, $this->parent_type_cache))
{
return $this->parent_type_cache[$cache_key];
}
// Store up to 1000 results in cache
$do_cache = ($this->__isMainTree() && count($this->parent_type_cache) < 1000);
// ref_id is not in tree
if(!$this->isInTree($a_ref_id))
{
if($do_cache)
{
$this->parent_type_cache[$cache_key] = false;
}
return false;
}
$path = array_reverse($this->getPathFull($a_ref_id));
// remove first path entry as it is requested node
if($a_exclude_source_check)
{
array_shift($path);
}
foreach($path as $node)
{
// found matching parent
if($node["type"] == $a_type)
{
if($do_cache)
{
$this->parent_type_cache[$cache_key] = $node["child"];
}
return $node["child"];
}
}
if($do_cache)
{
$this->parent_type_cache[$cache_key] = false;
}
return 0;
}

+ Here is the call graph for this function:

ilTree::checkTree ( )

check consistence of tree all left & right values are checked if they are exists only once public

Returns
boolean true if tree is ok; otherwise throws error object

Definition at line 1587 of file class.ilTree.php.

References $ilDB, $query, $res, and $row.

{
global $ilDB;
$types = array('integer');
$query = 'SELECT lft,rgt FROM '.$this->table_tree.' '.
'WHERE '.$this->tree_pk.' = %s ';
$res = $ilDB->queryF($query,$types,array($this->tree_id));
while ($row = $ilDB->fetchObject($res))
{
$lft[] = $row->lft;
$rgt[] = $row->rgt;
}
$all = array_merge($lft,$rgt);
$uni = array_unique($all);
if (count($all) != count($uni))
{
$message = sprintf('%s::checkTree(): Tree is corrupted!',
get_class($this));
$this->log->write($message,$this->log->FATAL);
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
return true;
}
ilTree::checkTreeChilds (   $a_no_zero_child = true)

check, if all childs of tree nodes exist in object table

Definition at line 1620 of file class.ilTree.php.

References $ilDB, $query, and $row.

{
global $ilDB;
$query = 'SELECT * FROM '.$this->table_tree.' '.
'WHERE '.$this->tree_pk.' = %s '.
'ORDER BY lft';
$r1 = $ilDB->queryF($query,array('integer'),array($this->tree_id));
while ($row = $ilDB->fetchAssoc($r1))
{
//echo "tree:".$row[$this->tree_pk].":lft:".$row["lft"].":rgt:".$row["rgt"].":child:".$row["child"].":<br>";
if (($row["child"] == 0) && $a_no_zero_child)
{
$this->ilErr->raiseError(get_class($this)."::checkTreeChilds(): Tree contains child with ID 0!",$this->ilErr->WARNING);
}
if ($this->table_obj_reference)
{
// get object reference data
$query = 'SELECT * FROM '.$this->table_obj_reference.' WHERE '.$this->ref_pk.' = %s ';
$r2 = $ilDB->queryF($query,array('integer'),array($row['child']));
//echo "num_childs:".$r2->numRows().":<br>";
if ($r2->numRows() == 0)
{
$this->ilErr->raiseError(get_class($this)."::checkTree(): No Object-to-Reference entry found for ID ".
$row["child"]."!",$this->ilErr->WARNING);
}
if ($r2->numRows() > 1)
{
$this->ilErr->raiseError(get_class($this)."::checkTree(): More Object-to-Reference entries found for ID ".
$row["child"]."!",$this->ilErr->WARNING);
}
// get object data
$obj_ref = $ilDB->fetchAssoc($r2);
$query = 'SELECT * FROM '.$this->table_obj_data.' WHERE '.$this->obj_pk.' = %s';
$r3 = $ilDB->queryF($query,array('integer'),array($obj_ref[$this->obj_pk]));
if ($r3->numRows() == 0)
{
$this->ilErr->raiseError(get_class($this)."::checkTree(): No child found for ID ".
$obj_ref[$this->obj_pk]."!",$this->ilErr->WARNING);
}
if ($r3->numRows() > 1)
{
$this->ilErr->raiseError(get_class($this)."::checkTree(): More childs found for ID ".
$obj_ref[$this->obj_pk]."!",$this->ilErr->WARNING);
}
}
else
{
// get only object data
$query = 'SELECT * FROM '.$this->table_obj_data.' WHERE '.$this->obj_pk.' = %s';
$r2 = $ilDB->queryF($query,array('integer'),array($row['child']));
//echo "num_childs:".$r2->numRows().":<br>";
if ($r2->numRows() == 0)
{
$this->ilErr->raiseError(get_class($this)."::checkTree(): No child found for ID ".
$row["child"]."!",$this->ilErr->WARNING);
}
if ($r2->numRows() > 1)
{
$this->ilErr->raiseError(get_class($this)."::checkTree(): More childs found for ID ".
$row["child"]."!",$this->ilErr->WARNING);
}
}
}
return true;
}
ilTree::deleteTree (   $a_node)

delete node and the whole subtree under this node public

Parameters
arraynode_data of a node

Definition at line 1012 of file class.ilTree.php.

References $ilDB, $query, $res, $row, __checkDelete(), __isMainTree(), and ilDB\LOCK_WRITE.

Referenced by ilWorkspaceTree\cascadingDelete().

{
global $ilDB;
if (!is_array($a_node))
{
$this->ilErr->raiseError(get_class($this)."::deleteTree(): Wrong datatype for node_data! ",$this->ilErr->WARNING);
}
if($this->__isMainTree() and $a_node[$this->tree_pk] === 1)
{
if($a_node['lft'] <= 1 or $a_node['rgt'] <= 2)
{
$message = sprintf('%s::deleteTree(): Invalid parameters given: $a_node["lft"]: %s, $a_node["rgt"] %s',
get_class($this),
$a_node['lft'],
$a_node['rgt']);
$this->log->write($message,$this->log->FATAL);
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
else if(!$this->__checkDelete($a_node))
{
$message = sprintf('%s::deleteTree(): Check delete failed: $a_node["lft"]: %s, $a_node["rgt"] %s',
get_class($this),
$a_node['lft'],
$a_node['rgt']);
$this->log->write($message,$this->log->FATAL);
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
}
$diff = $a_node["rgt"] - $a_node["lft"] + 1;
// LOCKED ###########################################################
// get lft and rgt values. Don't trust parameter lft/rgt values of $a_node
if($this->__isMainTree())
{
#ilDB::_lockTables(array('tree' => 'WRITE'));
$ilDB->lockTables(
array(
0 => array('name' => 'tree', 'type' => ilDB::LOCK_WRITE)));
}
$query = sprintf('SELECT * FROM '.$this->table_tree.' '.
'WHERE child = %s '.
'AND '.$this->tree_pk.' = %s ',
$ilDB->quote($a_node['child'],'integer'),
$ilDB->quote($a_node[$this->tree_pk],'integer'));
$res = $ilDB->query($query);
while($row = $ilDB->fetchObject($res))
{
$a_node['lft'] = $row->lft;
$a_node['rgt'] = $row->rgt;
$diff = $a_node["rgt"] - $a_node["lft"] + 1;
}
// delete subtree
$query = sprintf('DELETE FROM '.$this->table_tree.' '.
'WHERE lft BETWEEN %s AND %s '.
'AND rgt BETWEEN %s AND %s '.
'AND '.$this->tree_pk.' = %s',
$ilDB->quote($a_node['lft'],'integer'),
$ilDB->quote($a_node['rgt'],'integer'),
$ilDB->quote($a_node['lft'],'integer'),
$ilDB->quote($a_node['rgt'],'integer'),
$ilDB->quote($a_node[$this->tree_pk],'integer'));
$res = $ilDB->manipulate($query);
// Performance improvement: We only close the gap, if the node
// is not in a trash tree, and if the resulting gap will be
// larger than twice the gap value
if ($a_node[$this->tree_pk] >= 0 && $a_node['rgt'] - $a_node['lft'] >= $this->gap * 2)
{
//$this->log->write('ilTree.deleteTree('.$a_node['child'].') closing gap at '.$a_node['lft'].'...'.$a_node['rgt']);
// close gaps
$query = sprintf('UPDATE '.$this->table_tree.' SET '.
'lft = CASE WHEN lft > %s THEN lft - %s ELSE lft END, '.
'rgt = CASE WHEN rgt > %s THEN rgt - %s ELSE rgt END '.
'WHERE '.$this->tree_pk.' = %s ',
$ilDB->quote($a_node['lft'],'integer'),
$ilDB->quote($diff,'integer'),
$ilDB->quote($a_node['lft'],'integer'),
$ilDB->quote($diff,'integer'),
$ilDB->quote($a_node[$this->tree_pk],'integer'));
$res = $ilDB->manipulate($query);
}
else
{
//$this->log->write('ilTree.deleteTree('.$a_node['child'].') leaving gap open '.$a_node['lft'].'...'.$a_node['rgt']);
}
if($this->__isMainTree())
{
#$GLOBALS['ilLog']->write(__METHOD__.': Resetting in tree cache ');
$ilDB->unlockTables();
$this->in_tree_cache = array();
}
// LOCKED ###########################################################
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::fetchNodeData (   $a_row)

get data of parent node from tree and object_data private

Parameters
objectdb db result object containing node_data
Returns
array 2-dim (int/str) node_data TODO: select description twice for compability. Please use 'desc' in future only

Definition at line 1791 of file class.ilTree.php.

References $data, $ilBench, $ilDB, $lng, $query, $res, $row, ilContainerReference\_lookupTargetTitle(), isCacheUsed(), and ilUtil\shortenText().

Referenced by fetchPredecessorNode(), fetchSuccessorNode(), ilSCORMTree\getChilds(), getChilds(), getChildsByType(), getChildsByTypeFilter(), getNodeData(), getNodeDataByType(), getParentNodeData(), getPathFull(), getSavedNodeData(), and getSubTree().

{
global $objDefinition, $lng, $ilBench,$ilDB;
//$ilBench->start("Tree", "fetchNodeData_getRow");
$data = $a_row;
$data["desc"] = $a_row["description"]; // for compability
//$ilBench->stop("Tree", "fetchNodeData_getRow");
// multilingual support systemobjects (sys) & categories (db)
//$ilBench->start("Tree", "fetchNodeData_readDefinition");
if (is_object($objDefinition))
{
$translation_type = $objDefinition->getTranslationType($data["type"]);
}
//$ilBench->stop("Tree", "fetchNodeData_readDefinition");
if ($translation_type == "sys")
{
//$ilBench->start("Tree", "fetchNodeData_getLangData");
if ($data["type"] == "rolf" and $data["obj_id"] != ROLE_FOLDER_ID)
{
$data["description"] = $lng->txt("obj_".$data["type"]."_local_desc").$data["title"].$data["desc"];
$data["desc"] = $lng->txt("obj_".$data["type"]."_local_desc").$data["title"].$data["desc"];
$data["title"] = $lng->txt("obj_".$data["type"]."_local");
}
else
{
$data["title"] = $lng->txt("obj_".$data["type"]);
$data["description"] = $lng->txt("obj_".$data["type"]."_desc");
$data["desc"] = $lng->txt("obj_".$data["type"]."_desc");
}
//$ilBench->stop("Tree", "fetchNodeData_getLangData");
}
elseif ($translation_type == "db")
{
// Try to retrieve object translation from cache
if ($this->isCacheUsed() &&
array_key_exists($data["obj_id"].'.'.$lang_code, $this->translation_cache)) {
$key = $data["obj_id"].'.'.$lang_code;
$data["title"] = $this->translation_cache[$key]['title'];
$data["description"] = $this->translation_cache[$key]['description'];
$data["desc"] = $this->translation_cache[$key]['desc'];
}
else
{
// Object translation is not in cache, read it from database
//$ilBench->start("Tree", "fetchNodeData_getTranslation");
$query = 'SELECT title,description FROM object_translation '.
'WHERE obj_id = %s '.
'AND lang_code = %s '.
'AND NOT lang_default = %s';
$res = $ilDB->queryF($query,array('integer','text','integer'),array(
$data['obj_id'],
$this->lang_code,
1));
$row = $ilDB->fetchObject($res);
if ($row)
{
$data["title"] = $row->title;
$data["description"] = ilUtil::shortenText($row->description,MAXLENGTH_OBJ_DESC,true);
$data["desc"] = $row->description;
}
//$ilBench->stop("Tree", "fetchNodeData_getTranslation");
// Store up to 1000 object translations in cache
if ($this->isCacheUsed() && count($this->translation_cache) < 1000)
{
$key = $data["obj_id"].'.'.$lang_code;
$this->translation_cache[$key] = array();
$this->translation_cache[$key]['title'] = $data["title"] ;
$this->translation_cache[$key]['description'] = $data["description"];
$this->translation_cache[$key]['desc'] = $data["desc"];
}
}
}
// TODO: Handle this switch by module.xml definitions
if($data['type'] == 'crsr' or $data['type'] == 'catr')
{
include_once('./Services/ContainerReference/classes/class.ilContainerReference.php');
}
return $data ? $data : array();
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::fetchPredecessorNode (   $a_node_id,
  $a_type = "" 
)

get node data of predecessor node

public

Parameters
integernode id
Returns
array node data array

Definition at line 2618 of file class.ilTree.php.

References $ilDB, $query, $res, $row, buildJoin(), and fetchNodeData().

{
global $ilDB;
if (!isset($a_node_id))
{
$this->ilErr->raiseError(get_class($this)."::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
}
// get lft value for current node
$query = 'SELECT lft FROM '.$this->table_tree.' '.
'WHERE '.$this->table_tree.'.child = %s '.
'AND '.$this->table_tree.'.'.$this->tree_pk.' = %s ';
$res = $ilDB->queryF($query,array('integer','integer'),array(
$a_node_id,
$this->tree_id));
$curr_node = $ilDB->fetchAssoc($res);
if($a_type)
{
$query = 'SELECT * FROM '.$this->table_tree.' '.
$this->buildJoin().
'WHERE lft < %s '.
'AND '.$this->table_obj_data.'.type = %s '.
'AND '.$this->table_tree.'.'.$this->tree_pk.' = %s '.
'ORDER BY lft DESC';
$ilDB->setLimit(1);
$res = $ilDB->queryF($query,array('integer','text','integer'),array(
$curr_node['lft'],
$a_type,
$this->tree_id));
}
else
{
$query = 'SELECT * FROM '.$this->table_tree.' '.
$this->buildJoin().
'WHERE lft < %s '.
'AND '.$this->table_tree.'.'.$this->tree_pk.' = %s '.
'ORDER BY lft DESC';
$ilDB->setLimit(1);
$res = $ilDB->queryF($query,array('integer','integer'),array(
$curr_node['lft'],
$this->tree_id));
}
if ($res->numRows() < 1)
{
return false;
}
else
{
$row = $ilDB->fetchAssoc($res);
return $this->fetchNodeData($row);
}
}

+ Here is the call graph for this function:

ilTree::fetchSuccessorNode (   $a_node_id,
  $a_type = "" 
)

get node data of successor node

public

Parameters
integernode id
Returns
array node data array

Definition at line 2554 of file class.ilTree.php.

References $ilDB, $query, $res, $row, buildJoin(), and fetchNodeData().

Referenced by ilSCORMPresentationGUI\finishSahs().

{
global $ilDB;
if (!isset($a_node_id))
{
$this->ilErr->raiseError(get_class($this)."::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
}
// get lft value for current node
$query = 'SELECT lft FROM '.$this->table_tree.' '.
'WHERE '.$this->table_tree.'.child = %s '.
'AND '.$this->table_tree.'.'.$this->tree_pk.' = %s ';
$res = $ilDB->queryF($query,array('integer','integer'),array(
$a_node_id,
$this->tree_id));
$curr_node = $ilDB->fetchAssoc($res);
if($a_type)
{
$query = 'SELECT * FROM '.$this->table_tree.' '.
$this->buildJoin().
'WHERE lft > %s '.
'AND '.$this->table_obj_data.'.type = %s '.
'AND '.$this->table_tree.'.'.$this->tree_pk.' = %s '.
'ORDER BY lft ';
$ilDB->setLimit(1);
$res = $ilDB->queryF($query,array('integer','text','integer'),array(
$curr_node['lft'],
$a_type,
$this->tree_id));
}
else
{
$query = 'SELECT * FROM '.$this->table_tree.' '.
$this->buildJoin().
'WHERE lft > %s '.
'AND '.$this->table_tree.'.'.$this->tree_pk.' = %s '.
'ORDER BY lft ';
$ilDB->setLimit(1);
$res = $ilDB->queryF($query,array('integer','integer'),array(
$curr_node['lft'],
$this->tree_id));
}
if ($res->numRows() < 1)
{
return false;
}
else
{
$row = $ilDB->fetchAssoc($res);
return $this->fetchNodeData($row);
}
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::fetchTranslationFromObjectDataCache (   $a_obj_ids)
protected

Get translation data from object cache (trigger in object cache on preload)

Parameters
array$a_obj_idsobject ids

Definition at line 1887 of file class.ilTree.php.

References isCacheUsed().

Referenced by getChilds().

{
global $ilObjDataCache;
if ($this->isCacheUsed() && is_array($a_obj_ids) && is_object($ilObjDataCache))
{
foreach ($a_obj_ids as $id)
{
$this->translation_cache[$id.'.']['title'] = $ilObjDataCache->lookupTitle($id);
$this->translation_cache[$id.'.']['description'] = $ilObjDataCache->lookupDescription($id);;
$this->translation_cache[$id.'.']['desc'] =
$this->translation_cache[$id.'.']['description'];
}
}
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::getChilds (   $a_node_id,
  $a_order = "",
  $a_direction = "ASC" 
)

get child nodes of given node public

Parameters
integernode_id
stringsort order of returned childs, optional (possible values: 'title','desc','last_update' or 'type')
stringsort direction, optional (possible values: 'DESC' or 'ASC'; defalut is 'ASC')
Returns
array with node data of all childs or empty array

Reimplemented in ilSCORMTree.

Definition at line 332 of file class.ilTree.php.

References $ilBench, $ilDB, $query, $res, $row, __isMainTree(), fetchNodeData(), fetchTranslationFromObjectDataCache(), and isCacheUsed().

Referenced by __renumber(), getFilteredChilds(), and ilObjWorkspaceFolderTableGUI\getItems().

{
global $ilBench,$ilDB, $ilObjDataCache, $ilUser;
if (!isset($a_node_id))
{
$message = get_class($this)."::getChilds(): No node_id given!";
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
// init childs
$childs = array();
// number of childs
$count = 0;
// init order_clause
$order_clause = "";
// set order_clause if sort order parameter is given
if (!empty($a_order))
{
$order_clause = "ORDER BY ".$a_order." ".$a_direction;
}
else
{
$order_clause = "ORDER BY ".$this->table_tree.".lft";
}
$query = sprintf('SELECT * FROM '.$this->table_tree.' '.
$this->buildJoin().
"WHERE parent = %s " .
"AND ".$this->table_tree.".".$this->tree_pk." = %s ".
$order_clause,
$ilDB->quote($a_node_id,'integer'),
$ilDB->quote($this->tree_id,'integer'));
$res = $ilDB->query($query);
if(!$count = $res->numRows())
{
return array();
}
// get rows and object ids
$rows = array();
while($r = $ilDB->fetchAssoc($res))
{
$rows[] = $r;
$obj_ids[] = $r["obj_id"];
}
// preload object translation information
if ($this->__isMainTree() && $this->isCacheUsed() && is_object($ilObjDataCache) &&
is_object($ilUser) && $this->lang_code == $ilUser->getLanguage() && !$this->oc_preloaded[$a_node_id])
{
// $ilObjDataCache->preloadTranslations($obj_ids, $this->lang_code);
$ilObjDataCache->preloadObjectCache($obj_ids, $this->lang_code);
$this->oc_preloaded[$a_node_id] = true;
}
foreach ($rows as $row)
{
$childs[] = $this->fetchNodeData($row);
// Update cache of main tree
if ($this->__isMainTree())
{
#$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$row['child'].' = true');
$this->in_tree_cache[$row['child']] = $row['tree'] == 1;
}
}
$childs[$count - 1]["last"] = true;
return $childs;
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::getChildsByType (   $a_node_id,
  $a_type 
)

get child nodes of given node by object type public

Parameters
integernode_id
stringobject type
Returns
array with node data of all childs or empty array

Definition at line 441 of file class.ilTree.php.

References $ilDB, $query, $res, $row, and fetchNodeData().

{
global $ilDB;
if (!isset($a_node_id) or !isset($a_type))
{
$message = get_class($this)."::getChildsByType(): Missing parameter! node_id:".$a_node_id." type:".$a_type;
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
if ($a_type=='rolf' && $this->table_obj_reference) {
// Performance optimization: A node can only have exactly one
// role folder as its child. Therefore we don't need to sort the
// results, and we can let the database know about the expected limit.
$ilDB->setLimit(1,0);
$query = sprintf("SELECT * FROM ".$this->table_tree." ".
$this->buildJoin().
"WHERE parent = %s ".
"AND ".$this->table_tree.".".$this->tree_pk." = %s ".
"AND ".$this->table_obj_data.".type = %s ",
$ilDB->quote($a_node_id,'integer'),
$ilDB->quote($this->tree_id,'integer'),
$ilDB->quote($a_type,'text'));
} else {
$query = sprintf("SELECT * FROM ".$this->table_tree." ".
$this->buildJoin().
"WHERE parent = %s ".
"AND ".$this->table_tree.".".$this->tree_pk." = %s ".
"AND ".$this->table_obj_data.".type = %s ".
"ORDER BY ".$this->table_tree.".lft",
$ilDB->quote($a_node_id,'integer'),
$ilDB->quote($this->tree_id,'integer'),
$ilDB->quote($a_type,'text'));
}
$res = $ilDB->query($query);
// init childs
$childs = array();
while($row = $ilDB->fetchAssoc($res))
{
$childs[] = $this->fetchNodeData($row);
}
return $childs ? $childs : array();
}

+ Here is the call graph for this function:

ilTree::getChildsByTypeFilter (   $a_node_id,
  $a_types 
)

get child nodes of given node by object type public

Parameters
integernode_id
arrayarray of object type
Returns
array with node data of all childs or empty array

Definition at line 495 of file class.ilTree.php.

References $ilDB, $query, $res, $row, buildJoin(), fetchNodeData(), and ilUtil\quoteArray().

{
global $ilDB;
if (!isset($a_node_id) or !$a_types)
{
$message = get_class($this)."::getChildsByType(): Missing parameter! node_id:".$a_node_id." type:".$a_types;
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
$filter = ' ';
if($a_types)
{
$filter = 'AND '.$this->table_obj_data.'.type IN('.implode(',',ilUtil::quoteArray($a_types)).') ';
}
$query = 'SELECT * FROM '.$this->table_tree.' '.
$this->buildJoin().
'WHERE parent = '.$ilDB->quote($a_node_id,'integer').' '.
'AND '.$this->table_tree.'.'.$this->tree_pk.' = '.$ilDB->quote($this->tree_id,'integer').' '.
$filter.
'ORDER BY '.$this->table_tree.'.lft';
$res = $ilDB->query($query);
while($row = $ilDB->fetchAssoc($res))
{
$childs[] = $this->fetchNodeData($row);
}
return $childs ? $childs : array();
}

+ Here is the call graph for this function:

ilTree::getChildSequenceNumber (   $a_node,
  $type = "" 
)

get sequence number of node in sibling sequence public

Parameters
arraynode
Returns
integer sequence number

Definition at line 2450 of file class.ilTree.php.

References $ilDB, $query, $res, $row, and buildJoin().

{
global $ilDB;
if (!isset($a_node))
{
$this->ilErr->raiseError(get_class($this)."::getChildSequenceNumber(): No node_id given! ",$this->ilErr->WARNING);
}
if($type)
{
$query = 'SELECT count(*) cnt FROM '.$this->table_tree.' '.
$this->buildJoin().
'WHERE lft <= %s '.
'AND type = %s '.
'AND parent = %s '.
'AND '.$this->table_tree.'.'.$this->tree_pk.' = %s ';
$res = $ilDB->queryF($query,array('integer','text','integer','integer'),array(
$a_node['lft'],
$type,
$a_node['parent'],
$this->tree_id));
}
else
{
$query = 'SELECT count(*) cnt FROM '.$this->table_tree.' '.
$this->buildJoin().
'WHERE lft <= %s '.
'AND parent = %s '.
'AND '.$this->table_tree.'.'.$this->tree_pk.' = %s ';
$res = $ilDB->queryF($query,array('integer','integer','integer'),array(
$a_node['lft'],
$a_node['parent'],
$this->tree_id));
}
$row = $ilDB->fetchAssoc($res);
return $row["cnt"];
}

+ Here is the call graph for this function:

ilTree::getDepth (   $a_node_id)

return depth of a node in tree private

Parameters
integernode_id of parent's node_id
Returns
integer depth of node in tree

Definition at line 1716 of file class.ilTree.php.

References $ilDB, $query, $res, and $row.

Referenced by insertNode().

{
global $ilDB;
if ($a_node_id)
{
$query = 'SELECT depth FROM '.$this->table_tree.' '.
'WHERE child = %s '.
'AND '.$this->tree_pk.' = %s ';
$res = $ilDB->queryF($query,array('integer','integer'),array($a_node_id,$this->tree_id));
$row = $ilDB->fetchObject($res);
return $row->depth;
}
else
{
return 1;
}
}

+ Here is the caller graph for this function:

ilTree::getFilteredChilds (   $a_filter,
  $a_node,
  $a_order = "",
  $a_direction = "ASC" 
)

get child nodes of given node (exclude filtered obj_types) public

Parameters
arrayobjects to filter (e.g array('rolf'))
integernode_id
stringsort order of returned childs, optional (possible values: 'title','desc','last_update' or 'type')
stringsort direction, optional (possible values: 'DESC' or 'ASC'; defalut is 'ASC')
Returns
array with node data of all childs or empty array

Definition at line 419 of file class.ilTree.php.

References getChilds().

{
$childs = $this->getChilds($a_node,$a_order,$a_direction);
foreach($childs as $child)
{
if(!in_array($child["type"],$a_filter))
{
$filtered[] = $child;
}
}
return $filtered ? $filtered : array();
}

+ Here is the call graph for this function:

ilTree::getFilteredSubTree (   $a_node_id,
  $a_filter = array() 
)

get filtered subtree

get all subtree nodes beginning at a specific node excluding specific object types and their child nodes.

E.g getFilteredSubTreeNodes()

public

Parameters
@return

Definition at line 845 of file class.ilTree.php.

References getNodeData(), and getSubTree().

{
$node = $this->getNodeData($a_node_id);
$first = true;
$depth = 0;
foreach($this->getSubTree($node) as $subnode)
{
if($depth and $subnode['depth'] > $depth)
{
continue;
}
if(!$first and in_array($subnode['type'],$a_filter))
{
$depth = $subnode['depth'];
$first = false;
continue;
}
$depth = 0;
$first = false;
$filtered[] = $subnode;
}
return $filtered ? $filtered : array();
}

+ Here is the call graph for this function:

ilTree::getLeftValue (   $a_node_id)

get left value of given node public

Parameters
integernode id
Returns
integer left value

Definition at line 2425 of file class.ilTree.php.

References $ilDB, $query, $res, and $row.

{
global $ilDB;
if (!isset($a_node_id))
{
$this->ilErr->raiseError(get_class($this)."::getLeftValued(): No node_id given! ",$this->ilErr->WARNING);
}
$query = 'SELECT lft FROM '.$this->table_tree.' '.
'WHERE child = %s '.
'AND '.$this->tree_pk.' = %s ';
$res = $ilDB->queryF($query,array('integer','integer'),array(
$a_node_id,
$this->tree_id));
$row = $ilDB->fetchObject($res);
return $row->lft;
}
ilTree::getMaximumDepth ( )

Return the maximum depth in tree public.

Returns
integer max depth level of tree

Definition at line 1699 of file class.ilTree.php.

References $ilDB, $query, $res, and $row.

{
global $ilDB;
$query = 'SELECT MAX(depth) depth FROM '.$this->table_tree;
$res = $ilDB->query($query);
$row = $ilDB->fetchAssoc($res);
return $row['depth'];
}
ilTree::getNodeData (   $a_node_id,
  $a_tree_pk = null 
)

get all information of a node.

get data of a specific node from tree and object_data public

Parameters
integernode id
Returns
array 2-dim (int/str) node_data

Definition at line 1746 of file class.ilTree.php.

References $GLOBALS, $ilDB, $query, $res, $row, $tree_id, $tree_pk, __isMainTree(), buildJoin(), and fetchNodeData().

Referenced by ilWorkspaceTree\cascadingDelete(), getFilteredSubTree(), ilPortfolioPageTableGUI\getItems(), ilExAssignmentGUI\getOverviewBody(), ilOrgUnitTree\getRecursiveOrgUnitTree(), getSubTreeTypes(), ilObjPortfolioGUI\initBlogForm(), ilPCBlogGUI\initForm(), ilPCVerificationGUI\initForm(), ilObjPortfolioGUI\initForm(), ilPCFileListGUI\insertNewFileItem(), ilPCFileItemGUI\insertNewItemAfter(), ilPCFileItemGUI\insertNewItemBefore(), and ilPCFileListGUI\selectFile().

{
global $ilDB;
if (!isset($a_node_id))
{
$GLOBALS['ilLog']->logStack();
$this->ilErr->raiseError(get_class($this)."::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
}
if($this->__isMainTree())
{
if($a_node_id < 1)
{
$message = sprintf('%s::getNodeData(): No valid parameter given! $a_node_id: %s',
get_class($this),
$a_node_id);
$this->log->write($message,$this->log->FATAL);
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
}
// BEGIN WebDAV: Pass tree id to this method
$query = 'SELECT * FROM '.$this->table_tree.' '.
$this->buildJoin().
'WHERE '.$this->table_tree.'.child = %s '.
'AND '.$this->table_tree.'.'.$this->tree_pk.' = %s ';
$res = $ilDB->queryF($query,array('integer','integer'),array(
$a_node_id,
$a_tree_pk === null ? $this->tree_id : $a_tree_pk));
// END WebDAV: Pass tree id to this method
$row = $ilDB->fetchAssoc($res);
return $this->fetchNodeData($row);
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::getNodeDataByType (   $a_type)

get nodes by type // TODO: method needs revision

Parameters
integera_tree_id: obj_id of object where tree belongs to
integera_type_id: type of object public

Definition at line 2092 of file class.ilTree.php.

References $data, $ilDB, $query, $res, $row, buildJoin(), and fetchNodeData().

{
global $ilDB;
if (!isset($a_type) or (!is_string($a_type)))
{
$this->ilErr->raiseError(get_class($this)."::getNodeDataByType(): Type not given or wrong datatype!",$this->ilErr->WARNING);
}
$data = array(); // node_data
$row = ""; // fetched row
$left = ""; // tree_left
$right = ""; // tree_right
$query = 'SELECT * FROM '.$this->table_tree.' '.
'WHERE '.$this->tree_pk.' = %s '.
'AND parent = %s ';
$res = $ilDB->queryF($query,array('integer','integer'),array(
$this->tree_id,
0));
while ($row = $ilDB->fetchObject($res))
{
$left = $row->lft;
$right = $row->rgt;
}
$query = 'SELECT * FROM '.$this->table_tree.' '.
$this->buildJoin().
'WHERE '.$this->table_obj_data.'.type = %s '.
'AND '.$this->table_tree.'.lft BETWEEN %s AND %s '.
'AND '.$this->table_tree.'.rgt BETWEEN %s AND %s '.
'AND '.$this->table_tree.'.'.$this->tree_pk.' = %s ';
$res = $ilDB->queryF($query,array('text','integer','integer','integer','integer','integer'),array(
$a_type,
$left,
$right,
$left,
$right,
$this->tree_id));
while($row = $ilDB->fetchAssoc($res))
{
$data[] = $this->fetchNodeData($row);
}
return $data;
}

+ Here is the call graph for this function:

ilTree::getNodePath (   $a_endnode_id,
  $a_startnode_id = 0 
)

Returns the node path for the specified object reference.

Note: this function returns the same result as getNodePathForTitlePath, but takes ref-id's as parameters.

This function differs from getPathFull, in the following aspects:

  • The title of an object is not translated into the language of the user
  • This function is significantly faster than getPathFull.

public

Parameters
integernode_id of endnode
integernode_id of startnode (optional)
Returns
array ordered path info (depth,parent,child,obj_id,type,title) or null, if the node_id can not be converted into a node path.

Definition at line 1542 of file class.ilTree.php.

References $data, $ilDB, $query, $res, $row, and getPathId().

Referenced by getNodePathForTitlePath().

{
global $ilDB;
$pathIds = $this->getPathId($a_endnode_id, $a_startnode_id);
// Abort if no path ids were found
if (count($pathIds) == 0)
{
return null;
}
$types = array();
$data = array();
for ($i = 0; $i < count($pathIds); $i++)
{
$types[] = 'integer';
$data[] = $pathIds[$i];
}
$query = 'SELECT t.depth,t.parent,t.child,d.obj_id,d.type,d.title '.
'FROM '.$this->table_tree.' t '.
'JOIN '.$this->table_obj_reference.' r ON r.ref_id = t.child '.
'JOIN '.$this->table_obj_data.' d ON d.obj_id = r.obj_id '.
'WHERE '.$ilDB->in('t.child',$data,false,'integer').' '.
'ORDER BY t.depth ';
$res = $ilDB->queryF($query,$types,$data);
$titlePath = array();
while ($row = $ilDB->fetchAssoc($res))
{
$titlePath[] = $row;
}
return $titlePath;
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::getNodePathForTitlePath (   $titlePath,
  $a_startnode_id = null 
)

Converts a path consisting of object titles into a path consisting of tree nodes.

The comparison is non-case sensitive.

Note: this function returns the same result as getNodePath, but takes a title path as parameter.

public

Parameters
ArrayPath array with object titles. e.g. array('ILIAS','English','Course A')
ref_idStartnode of the relative path. Specify null, if the title path is an absolute path. Specify a ref id, if the title path is a relative path starting at this ref id.
Returns
array ordered path info (depth,parent,child,obj_id,type,title) or null, if the title path can not be converted into a node path.

Definition at line 1419 of file class.ilTree.php.

References $ilDB, $log, $obj_pk, $row, DB_FETCHMODE_ASSOC, getNodePath(), ilStr\strToLower(), and UtfNormal\toNFC().

{
global $ilDB, $log;
//$log->write('getNodePathForTitlePath('.implode('/',$titlePath));
// handle empty title path
if ($titlePath == null || count($titlePath) == 0)
{
if ($a_startnode_id == 0)
{
return null;
}
else
{
return $this->getNodePath($a_startnode_id);
}
}
// fetch the node path up to the startnode
if ($a_startnode_id != null && $a_startnode_id != 0)
{
// Start using the node path to the root of the relative path
$nodePath = $this->getNodePath($a_startnode_id);
$parent = $a_startnode_id;
}
else
{
// Start using the root of the tree
$nodePath = array();
$parent = 0;
}
// Convert title path into Unicode Normal Form C
// This is needed to ensure that we can compare title path strings with
// strings from the database.
require_once('include/Unicode/UtfNormal.php');
include_once './Services/Utilities/classes/class.ilStr.php';
$inClause = 'd.title IN (';
for ($i=0; $i < count($titlePath); $i++)
{
$titlePath[$i] = ilStr::strToLower(UtfNormal::toNFC($titlePath[$i]));
if ($i > 0) $inClause .= ',';
$inClause .= $ilDB->quote($titlePath[$i],'text');
}
$inClause .= ')';
// Fetch all rows that are potential path elements
if ($this->table_obj_reference)
{
$joinClause = 'JOIN '.$this->table_obj_reference.' r ON t.child = r.'.$this->ref_pk.' '.
'JOIN '.$this->table_obj_data.' d ON r.'.$this->obj_pk.' = d.'.$this->obj_pk;
}
else
{
$joinClause = 'JOIN '.$this->table_obj_data.' d ON t.child = d.'.$this->obj_pk;
}
// The ORDER BY clause in the following SQL statement ensures that,
// in case of a multiple objects with the same title, always the Object
// with the oldest ref_id is chosen.
// This ensure, that, if a new object with the same title is added,
// WebDAV clients can still work with the older object.
$q = 'SELECT t.depth, t.parent, t.child, d.'.$this->obj_pk.' obj_id, d.type, d.title '.
'FROM '.$this->table_tree.' t '.
$joinClause.' '.
'WHERE '.$inClause.' '.
'AND t.depth <= '.(count($titlePath)+count($nodePath)).' '.
'AND t.tree = 1 '.
'ORDER BY t.depth, t.child ASC';
$r = $ilDB->query($q);
$rows = array();
while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC))
{
$row['title'] = UtfNormal::toNFC($row['title']);
$row['ref_id'] = $row['child'];
$rows[] = $row;
}
// Extract the path elements from the fetched rows
for ($i = 0; $i < count($titlePath); $i++) {
$pathElementFound = false;
foreach ($rows as $row) {
if ($row['parent'] == $parent &&
ilStr::strToLower($row['title']) == $titlePath[$i])
{
// FIXME - We should test here, if the user has
// 'visible' permission for the object.
$nodePath[] = $row;
$parent = $row['child'];
$pathElementFound = true;
break;
}
}
// Abort if we haven't found a path element for the current depth
if (! $pathElementFound)
{
//$log->write('ilTree.getNodePathForTitlePath('.var_export($titlePath,true).','.$a_startnode_id.'):null');
return null;
}
}
// Return the node path
//$log->write('ilTree.getNodePathForTitlePath('.var_export($titlePath,true).','.$a_startnode_id.'):'.var_export($nodePath,true));
return $nodePath;
}

+ Here is the call graph for this function:

ilTree::getParentId (   $a_node_id)

get parent id of given node public

Parameters
integernode id
Returns
integer parent id

Definition at line 2399 of file class.ilTree.php.

References $ilDB, $query, $res, and $row.

{
global $ilDB;
if (!isset($a_node_id))
{
$this->ilErr->raiseError(get_class($this)."::getParentId(): No node_id given! ",$this->ilErr->WARNING);
}
$query = 'SELECT parent FROM '.$this->table_tree.' '.
'WHERE child = %s '.
'AND '.$this->tree_pk.' = %s ';
$res = $ilDB->queryF($query,array('integer','integer'),array(
$a_node_id,
$this->tree_id));
$row = $ilDB->fetchObject($res);
return $row->parent;
}
ilTree::getParentNodeData (   $a_node_id)

get data of parent node from tree and object_data public

Parameters
integernode id
Returns
array

Definition at line 1963 of file class.ilTree.php.

References $ilDB, $ilLog, $query, $res, $row, and fetchNodeData().

{
global $ilDB;
global $ilLog;
if (!isset($a_node_id))
{
$ilLog->logStack();
$this->ilErr->raiseError(get_class($this)."::getParentNodeData(): No node_id given! ",$this->ilErr->WARNING);
}
if ($this->table_obj_reference)
{
// Use inner join instead of left join to improve performance
$innerjoin = "JOIN ".$this->table_obj_reference." ON v.child=".$this->table_obj_reference.".".$this->ref_pk." ".
"JOIN ".$this->table_obj_data." ON ".$this->table_obj_reference.".".$this->obj_pk."=".$this->table_obj_data.".".$this->obj_pk." ";
}
else
{
// Use inner join instead of left join to improve performance
$innerjoin = "JOIN ".$this->table_obj_data." ON v.child=".$this->table_obj_data.".".$this->obj_pk." ";
}
$query = 'SELECT * FROM '.$this->table_tree.' s, '.$this->table_tree.' v '.
$innerjoin.
'WHERE s.child = %s '.
'AND s.parent = v.child '.
'AND s.lft > v.lft '.
'AND s.rgt < v.rgt '.
'AND s.'.$this->tree_pk.' = %s '.
'AND v.'.$this->tree_pk.' = %s';
$res = $ilDB->queryF($query,array('integer','integer','integer'),array(
$a_node_id,
$this->tree_id,
$this->tree_id));
$row = $ilDB->fetchAssoc($res);
return $this->fetchNodeData($row);
}

+ Here is the call graph for this function:

ilTree::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 startnode.

This function chooses the algorithm to be used.

public

Parameters
integernode_id of endnode
integernode_id of startnode (optional)
Returns
array ordered path info (id,title,parent) from start to end

Definition at line 1125 of file class.ilTree.php.

References $ilDB, $row, __isMainTree(), buildJoin(), DB_FETCHMODE_ASSOC, fetchNodeData(), getPathId(), and ilDB\quote().

Referenced by checkForParentType(), and ilSkillTree\getSkillTreePath().

{
$pathIds =& $this->getPathId($a_endnode_id, $a_startnode_id);
// We retrieve the full path in a single query to improve performance
global $ilDB;
// Abort if no path ids were found
if (count($pathIds) == 0)
{
return null;
}
$inClause = 'child IN (';
for ($i=0; $i < count($pathIds); $i++)
{
if ($i > 0) $inClause .= ',';
$inClause .= $ilDB->quote($pathIds[$i],'integer');
}
$inClause .= ')';
$q = 'SELECT * '.
'FROM '.$this->table_tree.' '.
$this->buildJoin().' '.
'WHERE '.$inClause.' '.
'AND '.$this->table_tree.'.'.$this->tree_pk.' = '.$this->ilDB->quote($this->tree_id,'integer').' '.
'ORDER BY depth';
$r = $ilDB->query($q);
$pathFull = array();
while ($row = $r->fetchRow(DB_FETCHMODE_ASSOC))
{
$pathFull[] = $this->fetchNodeData($row);
// Update cache
if ($this->__isMainTree())
{
#$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$row['child']);
$this->in_tree_cache[$row['child']] = $row['tree'] == 1;
}
}
return $pathFull;
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::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 startnode public

Parameters
integernode_id of endnode
integernode_id of startnode (optional)
Returns
array all path ids from startnode to endnode

Definition at line 1382 of file class.ilTree.php.

References __isMainTree(), getPathIdsUsingAdjacencyMap(), and isCacheUsed().

Referenced by getNodePath(), and getPathFull().

{
// path id cache
if ($this->isCacheUsed() && isset($this->path_id_cache[$a_endnode_id][$a_startnode_id]))
{
//echo "<br>getPathIdhit";
return $this->path_id_cache[$a_endnode_id][$a_startnode_id];
}
//echo "<br>miss";
$pathIds =& $this->getPathIdsUsingAdjacencyMap($a_endnode_id, $a_startnode_id);
if($this->__isMainTree())
{
$this->path_id_cache[$a_endnode_id][$a_startnode_id] = $pathIds;
}
return $pathIds;
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::getPathIdsUsingAdjacencyMap (   $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 startnode public

Parameters
integernode_id of endnode
integernode_id of startnode (optional)
Returns
array all path ids from startnode to endnode

Definition at line 1223 of file class.ilTree.php.

References $data, $ilDB, $log, $query, $res, $root_id, $row, $tree_id, __isMainTree(), and getPathIdsUsingNestedSets().

Referenced by getPathId().

{
// The adjacency map algorithm is harder to implement than the nested sets algorithm.
// This algorithms performs an index search for each of the path element.
// This algorithms performs well for large trees which are not deeply nested.
// The $takeId variable is used, to determine if a given id shall be included in the path
$takeId = $a_startnode_id == 0;
if (!isset($a_endnode_id))
{
$this->ilErr->raiseError(get_class($this)."::getPathId(): No endnode_id given! ",$this->ilErr->WARNING);
}
global $log, $ilDB;
if ($this->__isMainTree() && isset($this->depth_cache[$a_endnode_id])
&& isset($this->parent_cache[$a_endnode_id]))
{
$nodeDepth = $this->depth_cache[$a_endnode_id];
$parentId = $this->parent_cache[$a_endnode_id];
}
else
{
$types = array('integer','integer');
$data = array($a_endnode_id,$this->tree_id);
$query = 'SELECT t.depth, t.parent '.
'FROM '.$this->table_tree.' t '.
'WHERE child = %s '.
'AND '.$this->tree_pk.' = %s ';
$res = $ilDB->queryF($query,$types,$data);
if($res->numRows() == 0)
{
return array();
}
$row = $ilDB->fetchAssoc($res);
$nodeDepth = $row['depth'];
$parentId = $row['parent'];
}
//$this->writelog('getIdsUsingAdjacencyMap depth='.$nodeDepth);
// Fetch the node ids. For shallow depths we can fill in the id's directly.
$pathIds = array();
if ($nodeDepth == 1)
{
$takeId = $takeId || $a_endnode_id == $a_startnode_id;
if ($takeId) $pathIds[] = $a_endnode_id;
}
else if ($nodeDepth == 2)
{
$takeId = $takeId || $parentId == $a_startnode_id;
if ($takeId) $pathIds[] = $parentId;
$takeId = $takeId || $a_endnode_id == $a_startnode_id;
if ($takeId) $pathIds[] = $a_endnode_id;
}
else if ($nodeDepth == 3)
{
$takeId = $takeId || $this->root_id == $a_startnode_id;
if ($takeId) $pathIds[] = $this->root_id;
$takeId = $takeId || $parentId == $a_startnode_id;
if ($takeId) $pathIds[] = $parentId;
$takeId = $takeId || $a_endnode_id == $a_startnode_id;
if ($takeId) $pathIds[] = $a_endnode_id;
}
else if ($nodeDepth < 32)
{
// Adjacency Map Tree performs better than
// Nested Sets Tree even for very deep trees.
// The following code construct nested self-joins
// Since we already know the root-id of the tree and
// we also know the id and parent id of the current node,
// we only need to perform $nodeDepth - 3 self-joins.
// We can further reduce the number of self-joins by 1
// by taking into account, that each row in table tree
// contains the id of itself and of its parent.
$qSelect = 't1.child c0';
$qJoin = '';
for ($i = 1; $i < $nodeDepth - 2; $i++)
{
$qSelect .= ', t'.$i.'.parent c'.$i;
$qJoin .= ' JOIN '.$this->table_tree.' t'.$i.' ON '.
't'.$i.'.child=t'.($i - 1).'.parent AND '.
't'.$i.'.'.$this->tree_pk.' = '.(int) $this->tree_id;
}
$types = array('integer','integer');
$data = array($this->tree_id,$parentId);
$query = 'SELECT '.$qSelect.' '.
'FROM '.$this->table_tree.' t0 '.$qJoin.' '.
'WHERE t0.'.$this->tree_pk.' = %s '.
'AND t0.child = %s ';
$ilDB->setLimit(1);
$res = $ilDB->queryF($query,$types,$data);
if ($res->numRows() == 0)
{
return array();
}
$row = $ilDB->fetchAssoc($res);
$takeId = $takeId || $this->root_id == $a_startnode_id;
if ($takeId) $pathIds[] = $this->root_id;
for ($i = $nodeDepth - 4; $i >=0; $i--)
{
$takeId = $takeId || $row['c'.$i] == $a_startnode_id;
if ($takeId) $pathIds[] = $row['c'.$i];
}
$takeId = $takeId || $parentId == $a_startnode_id;
if ($takeId) $pathIds[] = $parentId;
$takeId = $takeId || $a_endnode_id == $a_startnode_id;
if ($takeId) $pathIds[] = $a_endnode_id;
}
else
{
// Fall back to nested sets tree for extremely deep tree structures
return $this->getPathIdsUsingNestedSets($a_endnode_id, $a_startnode_id);
}
return $pathIds;
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::getPathIdsUsingNestedSets (   $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 startnode public

Parameters
integernode_id of endnode
integernode_id of startnode (optional)
Returns
array all path ids from startnode to endnode

Definition at line 1176 of file class.ilTree.php.

References $data, $ilDB, $query, $res, and $row.

Referenced by getPathIdsUsingAdjacencyMap().

{
global $ilDB;
// The nested sets algorithm is very easy to implement.
// Unfortunately it always does a full table space scan to retrieve the path
// regardless whether indices on lft and rgt are set or not.
// (At least, this is what happens on MySQL 4.1).
// This algorithms performs well for small trees which are deeply nested.
if (!isset($a_endnode_id))
{
$this->ilErr->raiseError(get_class($this)."::getPathId(): No endnode_id given! ",$this->ilErr->WARNING);
}
$fields = array('integer','integer','integer');
$data = array($a_endnode_id,$this->tree_id,$this->tree_id);
$query = "SELECT T2.child ".
"FROM ".$this->table_tree." T1, ".$this->table_tree." T2 ".
"WHERE T1.child = %s ".
"AND T1.lft BETWEEN T2.lft AND T2.rgt ".
"AND T1.".$this->tree_pk." = %s ".
"AND T2.".$this->tree_pk." = %s ".
"ORDER BY T2.depth";
$res = $ilDB->queryF($query,$fields,$data);
$takeId = $a_startnode_id == 0;
while($row = $ilDB->fetchAssoc($res))
{
if ($takeId || $row['child'] == $a_startnode_id)
{
$takeId = true;
$pathIds[] = $row['child'];
}
}
return $pathIds ? $pathIds : array();
}

+ Here is the caller graph for this function:

ilTree::getRbacSubtreeInfo (   $a_endnode_id)

This method is used for change existing objects and returns all necessary information for this action.

The former use of ilTree::getSubtree needs to much memory.

Parameters
ref_idref_id of source node
Returns

Definition at line 3142 of file class.ilTree.php.

References $ilDB, $query, $res, $row, and DB_FETCHMODE_OBJECT.

{
global $ilDB;
$query = "SELECT t2.lft lft, t2.rgt rgt, t2.child child, type ".
"FROM ".$this->table_tree." t1 ".
"JOIN ".$this->table_tree." t2 ON (t2.lft BETWEEN t1.lft AND t1.rgt) ".
"JOIN ".$this->table_obj_reference." obr ON t2.child = obr.ref_id ".
"JOIN ".$this->table_obj_data." obd ON obr.obj_id = obd.obj_id ".
"WHERE t1.child = ".$ilDB->quote($a_endnode_id,'integer')." ".
"AND t1.".$this->tree_pk." = ".$ilDB->quote($this->tree_id,'integer')." ".
"AND t2.".$this->tree_pk." = ".$ilDB->quote($this->tree_id,'integer')." ".
"ORDER BY t2.lft";
$res = $ilDB->query($query);
while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
{
$nodes[$row->child]['lft'] = $row->lft;
$nodes[$row->child]['rgt'] = $row->rgt;
$nodes[$row->child]['child']= $row->child;
$nodes[$row->child]['type'] = $row->type;
}
return (array) $nodes;
}
ilTree::getRootId ( )

get the root id of tree public

Returns
integer root node id

Definition at line 2518 of file class.ilTree.php.

References $root_id.

Referenced by ilPCBlogGUI\initForm(), and ilPCVerificationGUI\initForm().

{
}

+ Here is the caller graph for this function:

ilTree::getSavedNodeData (   $a_parent_id)

get data saved/deleted nodes

Returns
array data
Parameters
integerid of parent object of saved object public

Definition at line 2368 of file class.ilTree.php.

References $ilDB, $query, $res, $row, buildJoin(), and fetchNodeData().

{
global $ilDB;
if (!isset($a_parent_id))
{
$this->ilErr->raiseError(get_class($this)."::getSavedNodeData(): No node_id given!",$this->ilErr->WARNING);
}
$query = 'SELECT * FROM '.$this->table_tree.' '.
$this->buildJoin().
'WHERE '.$this->table_tree.'.'.$this->tree_pk.' < %s '.
'AND '.$this->table_tree.'.parent = %s';
$res = $ilDB->queryF($query,array('integer','integer'),array(
0,
$a_parent_id));
while($row = $ilDB->fetchAssoc($res))
{
$saved[] = $this->fetchNodeData($row);
}
return $saved ? $saved : array();
}

+ Here is the call graph for this function:

ilTree::getSubTree (   $a_node,
  $a_with_data = true,
  $a_type = "" 
)

get all nodes in the subtree under specified node

public

Parameters
arraynode_data
booleanwith data: default is true otherwise this function return only a ref_id array
Returns
array 2-dim (int/array) key, node_data of each subtree node including the specified node

Definition at line 906 of file class.ilTree.php.

References $data, $ilDB, $query, $res, $row, __isMainTree(), buildJoin(), exit, and fetchNodeData().

Referenced by ilWorkspaceTree\cascadingDelete(), getFilteredSubTree(), and ilOrgUnitTree\getRecursiveOrgUnitTree().

{
global $ilDB;
if (!is_array($a_node))
{
$this->ilErr->raiseError(get_class($this)."::getSubTree(): Wrong datatype for node_data! ",$this->ilErr->WARNING);
}
if($a_node['lft'] < 1 or $a_node['rgt'] < 2)
{
$message = sprintf('%s::getSubTree(): Invalid node given! $a_node["lft"]: %s $a_node["rgt"]: %s',
get_class($this),
$a_node['lft'],
$a_node['rgt']);
$this->log->write($message,$this->log->FATAL);
if (DEVMODE == 1)
{
try
{
throw new Exception("e");
}
catch(Exception $e)
{
echo $e->getTraceAsString();
}
}
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
$fields = array('integer','integer','integer');
$data = array($a_node['lft'],$a_node['rgt'],$this->tree_id);
$type_str = '';
if (is_array($a_type))
{
$type_str = "AND ".$ilDB->in($this->table_obj_data.".type", $a_type, false, "text");
}
else if(strlen($a_type))
{
//$fields[] = 'text';
//$data[] = $a_type;
$type_str = "AND ".$this->table_obj_data.".type = ".
$ilDB->quote($a_type, "text");
}
$query = "SELECT * FROM ".$this->table_tree." ".
$this->buildJoin().
"WHERE ".$this->table_tree.".lft BETWEEN %s AND %s ".
"AND ".$this->table_tree.".".$this->tree_pk." = %s ".
$type_str.
"ORDER BY ".$this->table_tree.".lft";
$res = $ilDB->queryF($query,$fields,$data);
while($row = $ilDB->fetchAssoc($res))
{
if($a_with_data)
{
$subtree[] = $this->fetchNodeData($row);
}
else
{
$subtree[] = $row['child'];
}
if($this->__isMainTree())
{
#$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true');
$this->in_tree_cache[$row['child']] = true;
}
}
return $subtree ? $subtree : array();
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::getSubTreeIds (   $a_ref_id)

Get all ids of subnodes.

Returns
Parameters
object$a_ref_id

Definition at line 875 of file class.ilTree.php.

References $ilDB, $query, $res, $row, and DB_FETCHMODE_OBJECT.

{
global $ilDB;
$query = 'SELECT s.child FROM '.$this->table_tree.' s, '.$this->table_tree.' t '.
'WHERE t.child = %s '.
'AND s.lft > t.lft '.
'AND s.rgt < t.rgt '.
'AND s.'.$this->tree_pk.' = %s';
$res = $ilDB->queryF(
array('integer','integer'),
array($a_ref_id,$this->tree_id)
);
while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
{
$childs[] = $row->child;
}
return $childs ? $childs : array();
}
ilTree::getSubTreeTypes (   $a_node,
  $a_filter = 0 
)

get types of nodes in the subtree under specified node

public

Parameters
arraynode_id
arrayobject types to filter e.g array('rolf')
Returns
array 2-dim (int/array) key, node_data of each subtree node including the specified node

Definition at line 992 of file class.ilTree.php.

References getNodeData().

{
$a_filter = $a_filter ? $a_filter : array();
foreach($this->getSubtree($this->getNodeData($a_node)) as $node)
{
if(in_array($node["type"],$a_filter))
{
continue;
}
$types["$node[type]"] = $node["type"];
}
return $types ? $types : array();
}

+ Here is the call graph for this function:

ilTree::getTreeId ( )

get tree id public

Returns
integer tree id

Definition at line 2532 of file class.ilTree.php.

References $tree_id.

Referenced by ilWorkspaceExplorer\__construct().

{
}

+ Here is the caller graph for this function:

ilTree::ilTree (   $a_tree_id,
  $a_root_id = 0 
)

Constructor public.

Parameters
integer$a_tree_idtree_id
integer$a_root_idroot_id (optional)

Definition at line 130 of file class.ilTree.php.

References $ilDB, $ilErr, $ilias, $ilLog, and PEAR_ERROR_CALLBACK.

Referenced by ilAICCTree\ilAICCTree(), and ilSCORMTree\ilSCORMTree().

{
// set db & error handler
$this->ilDB = $ilDB;
if (!isset($ilErr))
{
$ilErr = new ilErrorHandling();
$ilErr->setErrorHandling(PEAR_ERROR_CALLBACK,array($ilErr,'errorHandler'));
}
else
{
$this->ilErr = $ilErr;
}
$this->lang_code = "en";
if (!isset($a_tree_id) or (func_num_args() == 0) )
{
$this->ilErr->raiseError(get_class($this)."::Constructor(): No tree_id given!",$this->ilErr->WARNING);
}
if (func_num_args() > 2)
{
$this->ilErr->raiseError(get_class($this)."::Constructor(): Wrong parameter count!",$this->ilErr->WARNING);
}
// CREATE LOGGER INSTANCE
$this->log = $ilLog;
//init variables
if (empty($a_root_id))
{
$a_root_id = ROOT_FOLDER_ID;
}
$this->tree_id = $a_tree_id;
$this->root_id = $a_root_id;
$this->table_tree = 'tree';
$this->table_obj_data = 'object_data';
$this->table_obj_reference = 'object_reference';
$this->ref_pk = 'ref_id';
$this->obj_pk = 'obj_id';
$this->tree_pk = 'tree';
$this->use_cache = true;
// If cache is activated, cache object translations to improve performance
$this->translation_cache = array();
$this->parent_type_cache = array();
// By default, we create gaps in the tree sequence numbering for 50 nodes
$this->gap = 50;
}

+ Here is the caller graph for this function:

ilTree::initLangCode ( )

Store user language.

This function is used by the "main" tree only (during initialisation).

Definition at line 208 of file class.ilTree.php.

{
global $ilUser;
// lang_code is only required in $this->fetchnodedata
if (!is_object($ilUser))
{
$this->lang_code = "en";
}
else
{
$this->lang_code = $ilUser->getCurrentLanguage();
}
}
ilTree::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

Parameters
integernode_id
integerparent_id
integerIL_LAST_NODE | IL_FIRST_NODE | node id of preceding child

Definition at line 534 of file class.ilTree.php.

References $ilDB, $query, $res, __isMainTree(), ilObject\_resetDeletedDate(), getDepth(), IL_FIRST_NODE, IL_LAST_NODE, isInTree(), and ilDB\LOCK_WRITE.

Referenced by ilWorkspaceTree\insertObject().

{
global $ilDB;
//echo "+$a_node_id+$a_parent_id+";
// CHECK node_id and parent_id > 0 if in main tree
if($this->__isMainTree())
{
if($a_node_id <= 1 or $a_parent_id <= 0)
{
$message = sprintf('%s::insertNode(): Invalid parameters! $a_node_id: %s $a_parent_id: %s',
get_class($this),
$a_node_id,
$a_parent_id);
$this->log->write($message,$this->log->FATAL);
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
}
if (!isset($a_node_id) or !isset($a_parent_id))
{
$this->ilErr->raiseError(get_class($this)."::insertNode(): Missing parameter! ".
"node_id: ".$a_node_id." parent_id: ".$a_parent_id,$this->ilErr->WARNING);
}
if ($this->isInTree($a_node_id))
{
$this->ilErr->raiseError(get_class($this)."::insertNode(): Node ".$a_node_id." already in tree ".
$this->table_tree."!",$this->ilErr->WARNING);
}
//
switch ($a_pos)
{
if($this->__isMainTree())
{
#ilDB::_lockTables(array('tree' => 'WRITE'));
$ilDB->lockTables(
array(
0 => array('name' => $this->table_tree, 'type' => ilDB::LOCK_WRITE)));
}
// get left value of parent
$query = sprintf('SELECT * FROM '.$this->table_tree.' '.
'WHERE child = %s '.
'AND '.$this->tree_pk.' = %s ',
$ilDB->quote($a_parent_id,'integer'),
$ilDB->quote($this->tree_id,'integer'));
$res = $ilDB->query($query);
$r = $ilDB->fetchObject($res);
if ($r->parent == NULL)
{
if($this->__isMainTree())
{
$ilDB->unlockTables();
}
$this->ilErr->raiseError(get_class($this)."::insertNode(): Parent with ID ".$a_parent_id." not found in ".
$this->table_tree."!",$this->ilErr->WARNING);
}
$left = $r->lft;
$lft = $left + 1;
$rgt = $left + 2;
// spread tree
$query = sprintf('UPDATE '.$this->table_tree.' SET '.
'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, '.
'rgt = CASE WHEN rgt > %s THEN rgt + 2 ELSE rgt END '.
'WHERE '.$this->tree_pk.' = %s ',
$ilDB->quote($left,'integer'),
$ilDB->quote($left,'integer'),
$ilDB->quote($this->tree_id,'integer'));
$res = $ilDB->manipulate($query);
break;
// Special treatment for trees with gaps
if ($this->gap > 0)
{
if($this->__isMainTree())
{
#ilDB::_lockTables(array('tree' => 'WRITE'));
$ilDB->lockTables(
array(
0 => array('name' => $this->table_tree, 'type' => ilDB::LOCK_WRITE)));
}
// get lft and rgt value of parent
$query = sprintf('SELECT rgt,lft,parent FROM '.$this->table_tree.' '.
'WHERE child = %s '.
'AND '.$this->tree_pk.' = %s',
$ilDB->quote($a_parent_id,'integer'),
$ilDB->quote($this->tree_id,'integer'));
$res = $ilDB->query($query);
$r = $ilDB->fetchAssoc($res);
if ($r['parent'] == null)
{
if($this->__isMainTree())
{
$ilDB->unlockTables();
}
$this->ilErr->raiseError(get_class($this)."::insertNode(): Parent with ID ".
$a_parent_id." not found in ".$this->table_tree."!",$this->ilErr->WARNING);
}
$parentRgt = $r['rgt'];
$parentLft = $r['lft'];
// Get the available space, without taking children into account yet
$availableSpace = $parentRgt - $parentLft;
if ($availableSpace < 2)
{
// If there is not enough space between parent lft and rgt, we don't need
// to look any further, because we must spread the tree.
$lft = $parentRgt;
}
else
{
// If there is space between parent lft and rgt, we need to check
// whether there is space left between the rightmost child of the
// parent and parent rgt.
$query = sprintf('SELECT MAX(rgt) max_rgt FROM '.$this->table_tree.' '.
'WHERE parent = %s '.
'AND '.$this->tree_pk.' = %s',
$ilDB->quote($a_parent_id,'integer'),
$ilDB->quote($this->tree_id,'integer'));
$res = $ilDB->query($query);
$r = $ilDB->fetchAssoc($res);
if (isset($r['max_rgt']))
{
// If the parent has children, we compute the available space
// between rgt of the rightmost child and parent rgt.
$availableSpace = $parentRgt - $r['max_rgt'];
$lft = $r['max_rgt'] + 1;
}
else
{
// If the parent has no children, we know now, that we can
// add the new node at parent lft + 1 without having to spread
// the tree.
$lft = $parentLft + 1;
}
}
$rgt = $lft + 1;
// spread tree if there is not enough space to insert the new node
if ($availableSpace < 2)
{
//$this->log->write('ilTree.insertNode('.$a_node_id.','.$a_parent_id.') creating gap at '.$a_parent_id.' '.$parentLft.'..'.$parentRgt.'+'.(2 + $this->gap * 2));
$query = sprintf('UPDATE '.$this->table_tree.' SET '.
'lft = CASE WHEN lft > %s THEN lft + %s ELSE lft END, '.
'rgt = CASE WHEN rgt >= %s THEN rgt + %s ELSE rgt END '.
'WHERE '.$this->tree_pk.' = %s ',
$ilDB->quote($parentRgt,'integer'),
$ilDB->quote((2 + $this->gap * 2),'integer'),
$ilDB->quote($parentRgt,'integer'),
$ilDB->quote((2 + $this->gap * 2),'integer'),
$ilDB->quote($this->tree_id,'integer'));
$res = $ilDB->manipulate($query);
}
else
{
//$this->log->write('ilTree.insertNode('.$a_node_id.','.$a_parent_id.') reusing gap at '.$a_parent_id.' '.$parentLft.'..'.$parentRgt.' for node '.$a_node_id.' '.$lft.'..'.$rgt);
}
}
// Treatment for trees without gaps
else
{
if($this->__isMainTree())
{
#ilDB::_lockTables(array('tree' => 'WRITE'));
$ilDB->lockTables(
array(
0 => array('name' => $this->table_tree, 'type' => ilDB::LOCK_WRITE)));
}
// get right value of parent
$query = sprintf('SELECT * FROM '.$this->table_tree.' '.
'WHERE child = %s '.
'AND '.$this->tree_pk.' = %s ',
$ilDB->quote($a_parent_id,'integer'),
$ilDB->quote($this->tree_id,'integer'));
$res = $ilDB->query($query);
$r = $ilDB->fetchObject($res);
if ($r->parent == null)
{
if($this->__isMainTree())
{
$ilDB->unlockTables();
}
$this->ilErr->raiseError(get_class($this)."::insertNode(): Parent with ID ".
$a_parent_id." not found in ".$this->table_tree."!",$this->ilErr->WARNING);
}
$right = $r->rgt;
$lft = $right;
$rgt = $right + 1;
// spread tree
$query = sprintf('UPDATE '.$this->table_tree.' SET '.
'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, '.
'rgt = CASE WHEN rgt >= %s THEN rgt + 2 ELSE rgt END '.
'WHERE '.$this->tree_pk.' = %s',
$ilDB->quote($right,'integer'),
$ilDB->quote($right,'integer'),
$ilDB->quote($this->tree_id,'integer'));
$res = $ilDB->manipulate($query);
}
break;
default:
// this code shouldn't be executed
if($this->__isMainTree())
{
#ilDB::_lockTables(array('tree' => 'WRITE'));
$ilDB->lockTables(
array(
0 => array('name' => $this->table_tree, 'type' => ilDB::LOCK_WRITE)));
}
// get right value of preceeding child
$query = sprintf('SELECT * FROM '.$this->table_tree.' '.
'WHERE child = %s '.
'AND '.$this->tree_pk.' = %s ',
$ilDB->quote($a_pos,'integer'),
$ilDB->quote($this->tree_id,'integer'));
$res = $ilDB->query($query);
$r = $ilDB->fetchObject($res);
// crosscheck parents of sibling and new node (must be identical)
if ($r->parent != $a_parent_id)
{
if($this->__isMainTree())
{
$ilDB->unlockTables();
}
$this->ilErr->raiseError(get_class($this)."::insertNode(): Parents mismatch! ".
"new node parent: ".$a_parent_id." sibling parent: ".$r->parent,$this->ilErr->WARNING);
}
$right = $r->rgt;
$lft = $right + 1;
$rgt = $right + 2;
// update lft/rgt values
$query = sprintf('UPDATE '.$this->table_tree.' SET '.
'lft = CASE WHEN lft > %s THEN lft + 2 ELSE lft END, '.
'rgt = CASE WHEN rgt > %s THEN rgt + 2 ELSE rgt END '.
'WHERE '.$this->tree_pk.' = %s',
$ilDB->quote($right,'integer'),
$ilDB->quote($right,'integer'),
$ilDB->quote($this->tree_id,'integer'));
$res = $ilDB->manipulate($query);
break;
}
// get depth
$depth = $this->getDepth($a_parent_id) + 1;
// insert node
//$this->log->write('ilTree.insertNode('.$a_node_id.','.$a_parent_id.') inserting node:'.$a_node_id.' parent:'.$a_parent_id." ".$lft."..".$rgt." depth:".$depth);
$query = sprintf('INSERT INTO '.$this->table_tree.' ('.$this->tree_pk.',child,parent,lft,rgt,depth) '.
'VALUES (%s,%s,%s,%s,%s,%s)',
$ilDB->quote($this->tree_id,'integer'),
$ilDB->quote($a_node_id,'integer'),
$ilDB->quote($a_parent_id,'integer'),
$ilDB->quote($lft,'integer'),
$ilDB->quote($rgt,'integer'),
$ilDB->quote($depth,'integer'));
$res = $ilDB->manipulate($query);
// Finally unlock tables and update cache
if($this->__isMainTree())
{
#$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true');
$this->in_tree_cache[$a_node_id] = true;
$ilDB->unlockTables();
}
// reset deletion date
if ($a_reset_deletion_date)
{
}
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::isCacheUsed ( )

Check if cache is active.

Returns
bool

Definition at line 199 of file class.ilTree.php.

References __isMainTree().

Referenced by checkForParentType(), fetchNodeData(), fetchTranslationFromObjectDataCache(), getChilds(), getPathId(), isInTree(), isSaved(), preloadDeleted(), and preloadDepthParent().

{
return $this->__isMainTree() and $this->use_cache;
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::isDeleted (   $a_node_id)

This is a wrapper for isSaved() with a more useful name.

Definition at line 2281 of file class.ilTree.php.

References isSaved().

{
return $this->isSaved($a_node_id);
}

+ Here is the call graph for this function:

ilTree::isGrandChild (   $a_startnode_id,
  $a_querynode_id 
)

checks if a node is in the path of an other node public

Parameters
integerobject id of start node
integerobject id of query node
Returns
integer number of entries

Definition at line 2009 of file class.ilTree.php.

References $ilDB, $query, and $res.

{
global $ilDB;
if (!isset($a_startnode_id) or !isset($a_querynode_id))
{
return false;
}
$query = 'SELECT * FROM '.$this->table_tree.' s, '.$this->table_tree.' v '.
'WHERE s.child = %s '.
'AND v.child = %s '.
'AND s.'.$this->tree_pk.' = %s '.
'AND v.'.$this->tree_pk.' = %s '.
'AND v.lft BETWEEN s.lft AND s.rgt '.
'AND v.rgt BETWEEN s.lft AND s.rgt';
$res = $ilDB->queryF(
array('integer','integer','integer','integer'),
array(
$a_startnode_id,
$a_querynode_id,
$this->tree_id,
$this->tree_id));
return $res->numRows();
}
ilTree::isInTree (   $a_node_id)

get all information of a node.

get data of a specific node from tree and object_data public

Parameters
integernode id
Returns
boolean true, if node id is in tree

Definition at line 1911 of file class.ilTree.php.

References $ilDB, $query, $res, __isMainTree(), and isCacheUsed().

Referenced by checkForParentType(), and insertNode().

{
global $ilDB;
if (!isset($a_node_id))
{
return false;
#$this->ilErr->raiseError(get_class($this)."::getNodeData(): No node_id given! ",$this->ilErr->WARNING);
}
// is in tree cache
if ($this->isCacheUsed() && isset($this->in_tree_cache[$a_node_id]))
{
#$GLOBALS['ilLog']->write(__METHOD__.': Using in tree cache '.$a_node_id);
//echo "<br>in_tree_hit";
return $this->in_tree_cache[$a_node_id];
}
$query = 'SELECT * FROM '.$this->table_tree.' '.
'WHERE '.$this->table_tree.'.child = %s '.
'AND '.$this->table_tree.'.'.$this->tree_pk.' = %s';
$res = $ilDB->queryF($query,array('integer','integer'),array(
$a_node_id,
$this->tree_id));
if ($res->numRows() > 0)
{
if($this->__isMainTree())
{
#$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = true');
$this->in_tree_cache[$a_node_id] = true;
}
return true;
}
else
{
if($this->__isMainTree())
{
#$GLOBALS['ilLog']->write(__METHOD__.': Storing in tree cache '.$a_node_id.' = false');
$this->in_tree_cache[$a_node_id] = false;
}
return false;
}
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::isSaved (   $a_node_id)

check if node is saved

Definition at line 2289 of file class.ilTree.php.

References $ilDB, $query, $res, $row, __isMainTree(), and isCacheUsed().

Referenced by isDeleted().

{
global $ilDB;
// is saved cache
if ($this->isCacheUsed() && isset($this->is_saved_cache[$a_node_id]))
{
//echo "<br>issavedhit";
return $this->is_saved_cache[$a_node_id];
}
$query = 'SELECT '.$this->tree_pk.' FROM '.$this->table_tree.' '.
'WHERE child = %s ';
$res = $ilDB->queryF($query,array('integer'),array($a_node_id));
$row = $ilDB->fetchAssoc($res);
if ($row[$this->tree_pk] < 0)
{
if($this->__isMainTree())
{
$this->is_saved_cache[$a_node_id] = true;
}
return true;
}
else
{
if($this->__isMainTree())
{
$this->is_saved_cache[$a_node_id] = false;
}
return false;
}
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

ilTree::moveTree (   $a_source_id,
  $a_target_id,
  $a_location = IL_LAST_NODE 
)

Move Tree Implementation.

public

Parameters
intsource ref_id
inttarget ref_id
intlocation IL_LAST_NODE or IL_FIRST_NODE (IL_FIRST_NODE not implemented yet)

Definition at line 3002 of file class.ilTree.php.

References $ilDB, $query, $res, $row, __isMainTree(), and ilDB\LOCK_WRITE.

{
global $ilDB;
if($this->__isMainTree())
{
#ilDB::_lockTables(array('tree' => 'WRITE'));
$ilDB->lockTables(
array(
0 => array('name' => 'tree', 'type' => ilDB::LOCK_WRITE)));
}
// Receive node infos for source and target
$query = 'SELECT * FROM '.$this->table_tree.' '.
'WHERE ( child = %s OR child = %s ) '.
'AND tree = %s ';
$res = $ilDB->queryF($query,array('integer','integer','integer'),array(
$a_source_id,
$a_target_id,
$this->tree_id));
// Check in tree
if($res->numRows() != 2)
{
if($this->__isMainTree())
{
$ilDB->unlockTables();
}
$this->log->write(__METHOD__.' Objects not found in tree!',$this->log->FATAL);
$this->ilErr->raiseError('Error moving node',$this->ilErr->WARNING);
}
while($row = $ilDB->fetchObject($res))
{
if($row->child == $a_source_id)
{
$source_lft = $row->lft;
$source_rgt = $row->rgt;
$source_depth = $row->depth;
$source_parent = $row->parent;
}
else
{
$target_lft = $row->lft;
$target_rgt = $row->rgt;
$target_depth = $row->depth;
}
}
#var_dump("<pre>",$source_lft,$source_rgt,$source_depth,$target_lft,$target_rgt,$target_depth,"<pre>");
// Check target not child of source
if($target_lft >= $source_lft and $target_rgt <= $source_rgt)
{
if($this->__isMainTree())
{
$ilDB->unlockTables();
}
$this->log->write(__METHOD__.' Target is child of source',$this->log->FATAL);
$this->ilErr->raiseError('Error moving node',$this->ilErr->WARNING);
}
// Now spread the tree at the target location. After this update the table should be still in a consistent state.
// implementation for IL_LAST_NODE
$spread_diff = $source_rgt - $source_lft + 1;
#var_dump("<pre>","SPREAD_DIFF: ",$spread_diff,"<pre>");
$query = 'UPDATE '.$this->table_tree.' SET '.
'lft = CASE WHEN lft > %s THEN lft + %s ELSE lft END, '.
'rgt = CASE WHEN rgt >= %s THEN rgt + %s ELSE rgt END '.
'WHERE tree = %s ';
$res = $ilDB->manipulateF($query,array('integer','integer','integer','integer','integer'),array(
$target_rgt,
$spread_diff,
$target_rgt,
$spread_diff,
$this->tree_id));
// Maybe the source node has been updated, too.
// Check this:
if($source_lft > $target_rgt)
{
$where_offset = $spread_diff;
$move_diff = $target_rgt - $source_lft - $spread_diff;
}
else
{
$where_offset = 0;
$move_diff = $target_rgt - $source_lft;
}
$depth_diff = $target_depth - $source_depth + 1;
$query = 'UPDATE '.$this->table_tree.' SET '.
'parent = CASE WHEN parent = %s THEN %s ELSE parent END, '.
'rgt = rgt + %s, '.
'lft = lft + %s, '.
'depth = depth + %s '.
'WHERE lft >= %s '.
'AND rgt <= %s '.
'AND tree = %s ';
$res = $ilDB->manipulateF($query,
array('integer','integer','integer','integer','integer','integer','integer','integer'),
array(
$source_parent,
$a_target_id,
$move_diff,
$move_diff,
$depth_diff,
$source_lft + $where_offset,
$source_rgt + $where_offset,
$this->tree_id));
// done: close old gap
$query = 'UPDATE '.$this->table_tree.' SET '.
'lft = CASE WHEN lft >= %s THEN lft - %s ELSE lft END, '.
'rgt = CASE WHEN rgt >= %s THEN rgt - %s ELSE rgt END '.
'WHERE tree = %s ';
$res = $ilDB->manipulateF($query,
array('integer','integer','integer','integer','integer'),
array(
$source_lft + $where_offset,
$spread_diff,
$source_rgt +$where_offset,
$spread_diff,
$this->tree_id));
if($this->__isMainTree())
{
$ilDB->unlockTables();
}
return true;
}

+ Here is the call graph for this function:

ilTree::preloadDeleted (   $a_node_ids)

Preload deleted information.

Parameters
@return

Definition at line 2329 of file class.ilTree.php.

References $ilDB, $query, $res, $row, __isMainTree(), and isCacheUsed().

{
global $ilDB;
if (!is_array($a_node_ids) || !$this->isCacheUsed())
{
return;
}
$query = 'SELECT '.$this->tree_pk.', child FROM '.$this->table_tree.' '.
'WHERE '.$ilDB->in("child", $a_node_ids, false, "integer");
$res = $ilDB->query($query);
while ($row = $ilDB->fetchAssoc($res))
{
if ($row[$this->tree_pk] < 0)
{
if($this->__isMainTree())
{
$this->is_saved_cache[$row["child"]] = true;
}
}
else
{
if($this->__isMainTree())
{
$this->is_saved_cache[$row["child"]] = false;
}
}
}
}

+ Here is the call graph for this function:

ilTree::preloadDepthParent (   $a_node_ids)

Preload depth/parent.

Parameters
@return

Definition at line 1354 of file class.ilTree.php.

References $ilDB, $res, $row, __isMainTree(), and isCacheUsed().

{
global $ilDB;
if (!$this->__isMainTree() || !is_array($a_node_ids) || !$this->isCacheUsed())
{
return;
}
$res = $ilDB->query('SELECT t.depth, t.parent, t.child '.
'FROM '.$this->table_tree.' t '.
'WHERE '.$ilDB->in("child", $a_node_ids, false, "integer").
'AND '.$this->tree_pk.' = '.$ilDB->quote($this->tree_id, "integer"));
while ($row = $ilDB->fetchAssoc($res))
{
$this->depth_cache[$row["child"]] = $row["depth"];
$this->parent_cache[$row["child"]] = $row["parent"];
}
}

+ Here is the call graph for this function:

ilTree::readRootId ( )

read root id from database

Parameters
root_idpublic
Returns
int new root id

Definition at line 2498 of file class.ilTree.php.

References $ilDB, $query, $res, $root_id, and $row.

Referenced by ilWorkspaceTree\__construct(), ilWorkspaceExplorer\__construct(), ilWorkspaceTree\cascadingDelete(), ilWorkspaceAccessHandler\checkAccessOfUser(), ilHACPPresentationGUI\explorer(), ilAICCPresentationGUI\explorer(), ilSAHSPresentationGUI\explorer(), ilSCORMPresentationGUI\explorer(), ilPortfolioPageTableGUI\getItems(), ilAICCExplorer\ilAICCExplorer(), ilHACPExplorer\ilHACPExplorer(), ilSCORMExplorer\ilSCORMExplorer(), ilObjPortfolioGUI\initBlogForm(), and ilObjPortfolioGUI\initForm().

{
global $ilDB;
$query = 'SELECT child FROM '.$this->table_tree.' '.
'WHERE parent = %s '.
'AND '.$this->tree_pk.' = %s ';
$res = $ilDB->queryF($query,array('integer','integer'),array(
0,
$this->tree_id));
$row = $ilDB->fetchObject($res);
$this->root_id = $row->child;
}

+ Here is the caller graph for this function:

ilTree::removeTree (   $a_tree_id)

remove an existing tree

Parameters
integera_tree_id: tree to be removed
Returns
boolean true on success public

Definition at line 2148 of file class.ilTree.php.

References $ilDB, $query, $res, and __isMainTree().

{
global $ilDB;
// OPERATION NOT ALLOWED ON MAIN TREE
if($this->__isMainTree())
{
$message = sprintf('%s::removeTree(): Operation not allowed on main tree! $a_tree_if: %s',
get_class($this),
$a_tree_id);
$this->log->write($message,$this->log->FATAL);
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
if (!$a_tree_id)
{
$this->ilErr->raiseError(get_class($this)."::removeTree(): No tree_id given! Action aborted",$this->ilErr->MESSAGE);
}
$query = 'DELETE FROM '.$this->table_tree.
' WHERE '.$this->tree_pk.' = %s ';
$res = $ilDB->manipulateF($query,array('integer'),array($a_tree_id));
return true;
}

+ Here is the call graph for this function:

ilTree::renumber (   $node_id = 1,
  $i = 1 
)

Wrapper for renumber.

This method locks the table tree (recursive) public

Parameters
integernode_id where to start (usually the root node)
integerfirst left value of start node (usually 1)
Returns
integer current left value of recursive call

Definition at line 2683 of file class.ilTree.php.

References $ilDB, __isMainTree(), __renumber(), and ilDB\LOCK_WRITE.

{
global $ilDB;
// LOCKED ###################################
if($this->__isMainTree())
{
/*
ilDB::_lockTables(array($this->table_tree => 'WRITE',
$this->table_obj_data => 'WRITE',
$this->table_obj_reference => 'WRITE',
'object_translation' => 'WRITE',
'object_data od' => 'WRITE',
'container_reference cr' => 'WRITE'));
*/
$ilDB->lockTables(
array(
0 => array('name' => $this->table_tree, 'type' => ilDB::LOCK_WRITE),
1 => array('name' => $this->table_obj_data, 'type' => ilDB::LOCK_WRITE),
2 => array('name' => $this->table_obj_reference, 'type' => ilDB::LOCK_WRITE),
3 => array('name' => 'object_translation', 'type' => ilDB::LOCK_WRITE),
4 => array('name' => 'object_data', 'type' => ilDB::LOCK_WRITE, 'alias' => 'od'),
5 => array('name' => 'container_reference', 'type' => ilDB::LOCK_WRITE, 'alias' => 'cr')
));
}
$return = $this->__renumber($node_id,$i);
if($this->__isMainTree())
{
$ilDB->unlockTables();
}
// LOCKED ###################################
return $return;
}

+ Here is the call graph for this function:

ilTree::saveSubTree (   $a_node_id,
  $a_set_deleted = false 
)

save subtree: delete a subtree (defined by node_id) to a new tree with $this->tree_id -node_id.

This is neccessary for undelete functionality

Parameters
integernode_id
Returns
integer public

Definition at line 2179 of file class.ilTree.php.

References $ilDB, $query, $res, $row, __isMainTree(), ilObject\_setDeletedDate(), and ilDB\LOCK_WRITE.

{
global $ilDB;
if (!$a_node_id)
{
$message = sprintf('%s::saveSubTree(): No valid parameter given! $a_node_id: %s',
get_class($this),
$a_node_id);
$this->log->write($message,$this->log->FATAL);
$this->ilErr->raiseError($message,$this->ilErr->WARNING);
}
// LOCKED ###############################################
if($this->__isMainTree())
{
$ilDB->lockTables(
array(
0 => array('name' => 'tree', 'type' => ilDB::LOCK_WRITE),
1 => array('name' => 'object_reference', 'type' => ilDB::LOCK_WRITE)));
#ilDB::_lockTables(array('tree' => 'WRITE',
# 'object_reference' => 'WRITE'));
}
// GET LEFT AND RIGHT VALUE
$query = 'SELECT * FROM '.$this->table_tree.' '.
'WHERE '.$this->tree_pk.' = %s '.
'AND child = %s ';
$res = $ilDB->queryF($query,array('integer','integer'),array(
$this->tree_id,
$a_node_id));
while($row = $ilDB->fetchObject($res))
{
$lft = $row->lft;
$rgt = $row->rgt;
}
// GET ALL SUBNODES
$query = 'SELECT child FROM '.$this->table_tree.' '.
'WHERE '.$this->tree_pk.' = %s '.
'AND lft BETWEEN %s AND %s ';
$res = $ilDB->queryF($query,array('integer','integer','integer'),array(
$this->tree_id,
$lft,
$rgt));
$subnodes = array();
while($row = $ilDB->fetchAssoc($res))
{
$subnodes[] = $row['child'];
}
if(!count($subnodes))
{
// possibly already deleted
// Unlock locked tables before returning
if($this->__isMainTree())
{
$ilDB->unlockTables();
}
return false;
}
// SAVE SUBTREE
foreach($subnodes as $child)
{
// set node as deleted
if ($a_set_deleted)
{
// TODO: new method that expects an array of ids
}
}
// Set the nodes deleted (negative tree id)
$query = 'UPDATE '.$this->table_tree.' '.
'SET tree = %s '.
'WHERE '.$this->tree_pk.' = %s '.
'AND lft BETWEEN %s AND %s ';
$res = $ilDB->manipulateF($query,array('integer','integer','integer','integer'),array(
-$a_node_id,
$this->tree_id,
$lft,
$rgt));
if($this->__isMainTree())
{
$ilDB->unlockTables();
}
// LOCKED ###############################################
return true;
}

+ Here is the call graph for this function:

ilTree::setObjectTablePK (   $a_column_name)

set column containing primary key in object table public

Parameters
stringcolumn name
Returns
boolean true, when successfully set

Definition at line 276 of file class.ilTree.php.

{
if (!isset($a_column_name))
{
$this->ilErr->raiseError(get_class($this)."::setObjectTablePK(): No column name given!",$this->ilErr->WARNING);
}
$this->obj_pk = $a_column_name;
return true;
}
ilTree::setReferenceTablePK (   $a_column_name)

set column containing primary key in reference table public

Parameters
stringcolumn name
Returns
boolean true, when successfully set

Definition at line 259 of file class.ilTree.php.

{
if (!isset($a_column_name))
{
$this->ilErr->raiseError(get_class($this)."::setReferenceTablePK(): No column name given!",$this->ilErr->WARNING);
}
$this->ref_pk = $a_column_name;
return true;
}
ilTree::setRootId (   $a_root_id)

Definition at line 2522 of file class.ilTree.php.

Referenced by ilWorkspaceExplorer\__construct().

{
$this->root_id = $a_root_id;
}

+ Here is the caller graph for this function:

ilTree::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 a reference table.

If no reference table is specified the given tree table is directly joined with the given object_data table. The primary key in object_data table and its foreign key in reference table must have the same name!

Parameters
stringtable name of tree table
stringtable name of object_data table
stringtable name of object_reference table (optional) public
Returns
boolean

Definition at line 238 of file class.ilTree.php.

Referenced by ilSkillTree\__construct(), ilSCORM2004Tree\__construct(), ilLMPageObject\_splitPage(), ilLMPageObject\_splitPageNext(), ilObjContentObjectGUI\explorer(), ilSCORM2004ScoGUI\getExportResources(), ilAICCTree\ilAICCTree(), ilLMEditorGUI\ilLMEditorGUI(), ilLMExplorer\ilLMExplorer(), ilLMPresentationGUI\ilLMPresentationGUI(), ilScorm2004EditorExplorer\ilScorm2004EditorExplorer(), ilSCORMTree\ilSCORMTree(), ilLMPresentationGUI\mapCurrentPageId(), ilMailFolderTableGUI\prepareHTML(), ilSCORM2004NodeGUI\putInTree(), ilLMObjectGUI\putInTree(), ilLMObject\putInTree(), ilSCORM2004ScoGUI\sahs_questions(), ilSCORM2004ScoGUI\sco_preview(), ilSCORM2004NodeGUI\setLocator(), ilMailFolderGUI\showFolder(), ilMailGUI\showMenu(), and ilObjSCORM2004LearningModuleGUI\showTree().

{
if (!isset($a_table_tree) or !isset($a_table_obj_data))
{
$this->ilErr->raiseError(get_class($this)."::setTableNames(): Missing parameter! ".
"tree table: ".$a_table_tree." object data table: ".$a_table_obj_data,$this->ilErr->WARNING);
}
$this->table_tree = $a_table_tree;
$this->table_obj_data = $a_table_obj_data;
$this->table_obj_reference = $a_table_obj_reference;
return true;
}

+ Here is the caller graph for this function:

ilTree::setTreeId (   $a_tree_id)

set tree id public

Returns
integer tree id

Definition at line 2542 of file class.ilTree.php.

{
$this->tree_id = $a_tree_id;
}
ilTree::setTreeTablePK (   $a_column_name)

set column containing primary key in tree table public

Parameters
stringcolumn name
Returns
boolean true, when successfully set

Definition at line 293 of file class.ilTree.php.

Referenced by ilSkillTree\__construct(), ilSCORM2004Tree\__construct(), ilSCORM13Package\dbImportLM(), ilSCORM2004ScoGUI\getEditTree(), ilObjSCORM2004LearningModuleGUI\getEditTree(), ilAICCTree\ilAICCTree(), ilContObjParser\ilContObjParser(), ilSCORMTree\ilSCORMTree(), ilObjSCORM2004LearningModuleGUI\insertAsset(), ilObjSCORM2004LearningModuleGUI\insertChapter(), ilObjSCORM2004LearningModuleGUI\insertPage(), ilObjSCORM2004LearningModuleGUI\insertScenario(), ilObjSCORM2004LearningModuleGUI\insertSco(), ilObjSCORM2004LearningModuleGUI\insertTemplate(), and ilSCORM2004Node\putInTree().

{
if (!isset($a_column_name))
{
$this->ilErr->raiseError(get_class($this)."::setTreeTablePK(): No column name given!",$this->ilErr->WARNING);
}
$this->tree_pk = $a_column_name;
return true;
}

+ Here is the caller graph for this function:

ilTree::useCache (   $a_use = true)

Use Cache (usually activated)

Definition at line 190 of file class.ilTree.php.

{
$this->use_cache = $a_use;
}

Field Documentation

ilTree::$depth_cache = array()
protected

Definition at line 120 of file class.ilTree.php.

ilTree::$gap

Definition at line 118 of file class.ilTree.php.

ilTree::$ilias

Definition at line 28 of file class.ilTree.php.

Referenced by ilTree().

ilTree::$log

Definition at line 36 of file class.ilTree.php.

Referenced by getNodePathForTitlePath(), and getPathIdsUsingAdjacencyMap().

ilTree::$obj_pk

Definition at line 85 of file class.ilTree.php.

Referenced by getNodePathForTitlePath(), and ilWorkspaceTree\lookupObjectId().

ilTree::$parent_cache = array()
protected

Definition at line 121 of file class.ilTree.php.

ilTree::$ref_pk

Definition at line 78 of file class.ilTree.php.

Referenced by ilWorkspaceTree\lookupNodeId().

ilTree::$root_id
ilTree::$table_obj_data

Definition at line 64 of file class.ilTree.php.

ilTree::$table_obj_reference

Definition at line 71 of file class.ilTree.php.

ilTree::$table_tree

Definition at line 57 of file class.ilTree.php.

ilTree::$tree_id

Definition at line 50 of file class.ilTree.php.

Referenced by getNodeData(), getPathIdsUsingAdjacencyMap(), and getTreeId().

ilTree::$tree_pk

Definition at line 92 of file class.ilTree.php.

Referenced by getNodeData().


The documentation for this class was generated from the following file: