/**
* Method to move a node one position to the left in the same level.
*
* @param integer $pk Primary key of the node to move.
*
* @return boolean True on success.
*
* @since 1.7.0
* @throws \RuntimeException on database error.
*/
public function orderUp($pk)
{
$k = $this->_tbl_key;
$pk = \is_null($pk) ? $this->{$k} : $pk;
// Lock the table for writing.
if (!$this->_lock()) {
// Error message set in lock method.
return false;
}
// Get the node by primary key.
$node = $this->_getNode($pk);
if (empty($node)) {
// Error message set in getNode method.
$this->_unlock();
return false;
}
// Get the left sibling node.
$sibling = $this->_getNode($node->lft - 1, 'right');
if (empty($sibling)) {
// Error message set in getNode method.
$this->_unlock();
return false;
}
try {
// Get the primary keys of child nodes.
$query = $this->_db->getQuery(true)->select($this->_tbl_key)->from($this->_tbl)->where('lft BETWEEN ' . (int) $node->lft . ' AND ' . (int) $node->rgt);
$children = $this->_db->setQuery($query)->loadColumn();
// Shift left and right values for the node and its children.
$query->clear()->update($this->_tbl)->set('lft = lft - ' . (int) $sibling->width)->set('rgt = rgt - ' . (int) $sibling->width)->where('lft BETWEEN ' . (int) $node->lft . ' AND ' . (int) $node->rgt);
$this->_db->setQuery($query)->execute();
// Shift left and right values for the sibling and its children.
$query->clear()->update($this->_tbl)->set('lft = lft + ' . (int) $node->width)->set('rgt = rgt + ' . (int) $node->width)->where('lft BETWEEN ' . (int) $sibling->lft . ' AND ' . (int) $sibling->rgt)->where($this->_tbl_key . ' NOT IN (' . implode(',', $children) . ')');
$this->_db->setQuery($query)->execute();
} catch (\RuntimeException $e) {
$this->_unlock();
throw $e;
}
// Unlock the table for writing.
$this->_unlock();
return true;
}