JTableNested/move
From Joomla! Documentation
< API16:JTableNested
The "API16" namespace is an archived namespace. This page contains information for a Joomla! version which is no longer supported. It exists only as a historical reference, it will not be improved and its content may be incomplete and/or contain broken links.
Description[edit]
Method to move a node and its children to a new location in the tree.
Syntax[edit]
move($referenceId, $position= 'after', $pk=null)
Parameter Name | Default Value | Description |
---|---|---|
$referenceId | The primary key of the node to reference new location by. | |
$position | 'after' | Location type string. ['before', 'after', 'first-child', 'last-child'] |
$pk | null | The primary key of the node to move. |
Returns[edit]
boolean True on success.
Defined in[edit]
libraries/joomla/database/tablenested.php
Importing[edit]
jimport( 'joomla.database.tablenested' );
Source Body[edit]
public function move($referenceId, $position = 'after', $pk = null)
{
if ($this->_debug) {
echo "\nMoving ReferenceId:$referenceId, Position:$position, PK:$pk";
}
// Initialise variables.
$k = $this->_tbl_key;
$pk = (is_null($pk)) ? $this->$k : $pk;
// Get the node by id.
if (!$node = $this->_getNode($pk)) {
// Error message set in getNode method.
return false;
}
// Get the ids of child nodes.
$this->_db->setQuery(
'SELECT `'.$k.'`' .
' FROM `'.$this->_tbl.'`' .
' WHERE `lft` BETWEEN '.(int) $node->lft.' AND '.(int) $node->rgt
);
$children = $this->_db->loadResultArray();
// Check for a database error.
if ($this->_db->getErrorNum()) {
$this->setError($this->_db->getErrorMsg());
return false;
}
if ($this->_debug) {
$this->_logtable(false);
}
// Cannot move the node to be a child of itself.
if (in_array($referenceId, $children)) {
$this->setError(JText::_('Invalid_Node_Recursion'));
return false;
}
// Lock the table for writing.
if (!$this->_lock()) {
// Error message set in lock method.
return false;
}
// We are moving the tree relative to a reference node.
if ($referenceId) {
// Get the reference node by primary key.
if (!$reference = $this->_getNode($referenceId)) {
// Error message set in getNode method.
$this->_unlock();
return false;
}
// If moving "down" the tree, adjust $reference lft, rgt for $node width
if ($node->rgt < $reference->rgt) {
$reference->lft -= $node->width;
$reference->rgt -= $node->width;
}
// Get the reposition data for shifting the tree and re-inserting the node.
if (!$repositionData = $this->_getTreeRepositionData($reference, $node->width, $position)) {
// Error message set in getNode method.
$this->_unlock();
return false;
}
}
// We are moving the tree to be a new root node.
else {
// Get the last root node as the reference node.
$this->_db->setQuery(
'SELECT `'.$this->_tbl_key.'`, `parent_id`, `level`, `lft`, `rgt`' .
' FROM `'.$this->_tbl.'`' .
' WHERE `parent_id` = 0' .
' ORDER BY `lft` DESC',
0, 1
);
$reference = $this->_db->loadObject();
// Check for a database error.
if ($this->_db->getErrorNum()) {
$this->setError($this->_db->getErrorMsg());
$this->_unlock();
return false;
}
if ($this->_debug) {
$this->_logtable(false);
}
// Get the reposition data for re-inserting the node after the found root.
if (!$repositionData = $this->_getTreeRepositionData($reference, $node->width, 'after')) {
// Error message set in getNode method.
$this->_unlock();
return false;
}
}
/*
* Move the sub-tree out of the nested sets by negating its left and right values.
*/
$this->_db->setQuery(
'UPDATE `'.$this->_tbl.'`' .
' SET `lft` = `lft` * (-1), `rgt` = `rgt` * (-1)' .
' WHERE `lft` BETWEEN '.(int) $node->lft.' AND '.(int) $node->rgt
);
$this->_db->query();
// Check for a database error.
if ($this->_db->getErrorNum()) {
$this->setError($this->_db->getErrorMsg());
$this->_unlock();
return false;
}
if ($this->_debug) {
$this->_logtable();
}
/*
* Close the hole in the tree that was opened by removing the sub-tree from the nested sets.
*/
// Compress the left values.
$this->_db->setQuery(
'UPDATE `'.$this->_tbl.'`' .
' SET `lft` = `lft` - '.(int) $node->width .
' WHERE `lft` > '.(int) $node->rgt
);
$this->_db->query();
// Check for a database error.
if ($this->_db->getErrorNum()) {
$this->setError($this->_db->getErrorMsg());
$this->_unlock();
return false;
}
if ($this->_debug) {
$this->_logtable();
}
// Compress the right values.
$this->_db->setQuery(
'UPDATE `'.$this->_tbl.'`' .
' SET `rgt` = `rgt` - '.(int) $node->width .
' WHERE `rgt` > '.(int) $node->rgt
);
$this->_db->query();
// Check for a database error.
if ($this->_db->getErrorNum()) {
$this->setError($this->_db->getErrorMsg());
$this->_unlock();
return false;
}
if ($this->_debug) {
$this->_logtable();
}
/*
* Create space in the nested sets at the new location for the moved sub-tree.
*/
// Shift left values.
$this->_db->setQuery(
'UPDATE `'.$this->_tbl.'`' .
' SET `lft` = `lft` + '.(int) $node->width .
' WHERE '.$repositionData->left_where
);
$this->_db->query();
// Check for a database error.
if ($this->_db->getErrorNum()) {
$this->setError($this->_db->getErrorMsg());
$this->_unlock();
return false;
}
if ($this->_debug) {
$this->_logtable();
}
// Shift right values.
$this->_db->setQuery(
'UPDATE `'.$this->_tbl.'`' .
' SET `rgt` = `rgt` + '.(int) $node->width .
' WHERE '.$repositionData->right_where
);
$this->_db->query();
// Check for a database error.
if ($this->_db->getErrorNum()) {
$this->setError($this->_db->getErrorMsg());
$this->_unlock();
return false;
}
if ($this->_debug) {
$this->_logtable();
}
/*
* Calculate the offset between where the node used to be in the tree and
* where it needs to be in the tree for left ids (also works for right ids).
*/
$offset = $repositionData->new_lft - $node->lft;
$levelOffset = $repositionData->new_level - $node->level;
// Move the nodes back into position in the tree using the calculated offsets.
$this->_db->setQuery(
'UPDATE `'.$this->_tbl.'`' .
' SET `rgt` = '.(int) $offset.' - `rgt`,' .
' `lft` = '.(int) $offset.' - `lft`,' .
' `level` = `level` + '.(int) $levelOffset .
' WHERE `lft` < 0'
);
$this->_db->query();
// Check for a database error.
if ($this->_db->getErrorNum()) {
$this->setError($this->_db->getErrorMsg());
$this->_unlock();
return false;
}
if ($this->_debug) {
$this->_logtable();
}
// Set the correct parent id for the moved node if required.
if ($node->parent_id != $repositionData->new_parent_id) {
$this->_db->setQuery(
'UPDATE `'.$this->_tbl.'`' .
' SET `parent_id` = '.(int) $repositionData->new_parent_id .
' WHERE `'.$this->_tbl_key.'` = '.(int) $node->$k
);
$this->_db->query();
// Check for a database error.
if ($this->_db->getErrorNum()) {
$this->setError($this->_db->getErrorMsg());
$this->_unlock();
return false;
}
if ($this->_debug) {
$this->_logtable();
}
}
// Unlock the table for writing.
$this->_unlock();
// Set the object values.
$this->parent_id = $repositionData->new_parent_id;
$this->level = $repositionData->new_level;
$this->lft = $repositionData->new_lft;
$this->rgt = $repositionData->new_rgt;
return true;
}
Examples[edit]
Code Examples[edit]