Actions

API16

JTableNested/move

From Joomla! Documentation

< API16:JTableNested
Revision as of 17:43, 22 March 2010 by Doxiki (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Replacement filing cabinet.png
This Namespace has been archived - Please Do Not Edit or Create Pages in this namespace. Pages contain information for a Joomla! version which is no longer supported. It exists only as a historical reference, will not be improved and its content may be incomplete.

Contents

Description

Method to move a node and its children to a new location in the tree.

[Edit Descripton]

Description:JTableNested/move

Syntax

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

boolean True on success.

Defined in

libraries/joomla/database/tablenested.php

Importing

jimport( 'joomla.database.tablenested' );

Source Body

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;
}

[Edit See Also] SeeAlso:JTableNested/move

Examples

<CodeExamplesForm />