Шаги для перемещения поддерева в дереве категорий с использованием модели вложенного набора (с левым и правым столбцами):
1. преобразуйте столбцы lft и rgt в их отрицательные аналоги для категории, которую вы хотите переместить, и ее подкатегорий (это пока «удалит» поддерево из дерева)
2. если вы перемещаете поддерево вверх (или «влево» в представлении вложенного набора), переместите все категории между новым родителем поддерева и его старым левым (или правым, во втором случае) пределом вправо, в противном случае (при перемещении поддерева вниз) вправо. Это включает установку для левого и правого столбцов этих категорий их значений плюс (или минус во втором случае) расстояние между левым и правым столбцом поддерева (или перемещаемой категории).
3. после этого все, что вам нужно сделать, это вернуть левый и правый столбцы к положительным значениям и в то же время вычесть (или добавить во втором случае) разницу между его левым пределом и новым родительским левым столбцом ( или между родительским левым и правым пределом во втором случае)
Все это кажется очень сложным, выраженным в одном случае, поэтому я разбил его на два случая:
$step = 1+ $this->_categoriesTable->rgt
- $this->_categoriesTable->lft;
$lft = $this->_categoriesTable->lft;
$rgt = $this->_categoriesTable->rgt;
$id = $this->_categoriesTable->id;
$distance = $lft - $parentLeft - 1;
$query = '
UPDATE %s SET lft=-lft, rgt=-rgt
WHERE lft>=%d AND lft<=%d;
UPDATE %s SET lft=lft+%d WHERE lft>%d AND lft<%d;
UPDATE %s SET rgt=rgt+%d WHERE rgt>%d AND rgt<%d;
UPDATE %s SET lft=-lft-%d, rgt=-rgt-%d WHERE lft<=-%d
AND lft>=-%d;
UPDATE %s SET parent_id=%d, title=%s, description=%s,
metadescription=%s WHERE id=%s';
$query = sprintf($query,
$this->_db->nameQuote('#__categories'),
$lft, $rgt,
$this->_db->nameQuote('#__categories'), $step,
$parentLeft, $lft,
$this->_db->nameQuote('#__categories'), $step,
$parentLeft, $lft,
$this->_db->nameQuote('#__categories'), $distance,
$distance, $lft, $rgt,
$this->_db->nameQuote('#__categories'),
$data['parent_id'],
$this->_db->Quote($this->_categoriesTable->title),
$this->_db->Quote($this->_categoriesTable->description),
$this->_db->Quote(
$this->_categoriesTable->metadescription),
$this->_db->Quote($id));
// and for the moving to the "right" case
$step = 1+ $this->_categoriesTable->rgt
- $this->_categoriesTable->lft;
$distance = $parentLeft - $this->_categoriesTable->rgt;
// Memorize this because we bind and we need the old values
$lft = $this->_categoriesTable->lft;
$rgt = $this->_categoriesTable->rgt;
$id = $this->_categoriesTable->id;
$query = sprintf($query,
$this->_db->nameQuote('#__categories'),
$lft, $rgt,
$this->_db->nameQuote('#__categories'), $step,
$rgt, $parentLeft,
$this->_db->nameQuote('#__categories'), $step,
$rgt, $parentLeft,
$this->_db->nameQuote('#__categories'), $distance,
$distance, $lft, $rgt,
$this->_db->nameQuote('#__categories'),
$data['parent_id'],
$this->_db->Quote($this->_categoriesTable->title),
$this->_db->Quote($this->_categoriesTable->description),
$this->_db->Quote(
$this->_categoriesTable->metadescription),
$this->_db->Quote($id));