Originariamente inviato da Fabio Heller
A me interessa
Posto il pezzo di codice.
Unico requisito è che i campi tree_left e tree_right devono essere interi con segno, non UNSIGNED come nel modello originale.
In $catId ho l'id del sottoalbero da spostare, in $destId quello di destinazione.
La variabile $pos identifica il tipo di spostamento.
- 'parent' indica che il sottoalbero deve essere spostato come figlio del nodo destinazione (che deve essere una foglia).
'after' indica l'inserimento nella posizione successiva al nodo destinazione.
'before' indica l'inserimento prima del nodo destinazione.
Ci sono 8 casi, a seconda della posizione del nodo da spostare rispetto alla destinazione. Molto probabilmente si possono accorpare e generalizzare, questa è una prima stesura, non ho badato a ottimizzare nient'altro che il numero e il peso delle query.
[supersaibal]
codice:
$dest = array();
$cat = array();
$st = $this->DB->query("SELECT tree_id, tree_left, tree_right, (tree_right - tree_left + 1) AS tree_width FROM ".$this->treeTable." WHERE tree_id = ".$this->DB->quote($catId)." OR tree_id = ".$this->DB->quote($destId));
while($row = $st->fetch(PDO::FETCH_ASSOC))
{
if($row['tree_id'] == $catId)
$cat = $row;
elseif($row['tree_id'] == $destId)
$dest = $row;
}
if(!$cat)
{
$this->error = array('category:E_NODE_NOT_FOUND', $catId);
$this->DB->rollBack();
return FALSE;
}
if(!$dest)
{
$this->error = array('category:E_NODE_NOT_FOUND', $destId);
$this->DB->rollBack();
return FALSE;
}
if($dest['tree_left'] > $cat['tree_left'] && $dest['tree_left'] < $cat['tree_right'])
{
$this->error = array('category:E_MOVE_IN_LOOP');
$this->DB->rollBack();
return FALSE;
}
switch($pos)
{
case 'parent':
if($dest['tree_right'] != ($dest['tree_left'] + 1))
{
$this->error = array('category:E_NODE_NOT_GOOD_PARENT', $destId);
$this->DB->rollBack();
return FALSE;
}
if($dest['tree_left'] < $cat['tree_left'])
{
// caso A
$offset = $cat['tree_left'] - $dest['tree_left'] - 1;
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left - ".$offset."), tree_right = -(tree_right - ".$offset.") WHERE tree_left BETWEEN ".$cat['tree_left']." AND ".$cat['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = tree_left + ".$cat['tree_width']." WHERE tree_left > 0 AND tree_left > ".$dest['tree_left']." AND tree_left < ".$cat['tree_left']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_right = tree_right + ".$cat['tree_width']." WHERE tree_left > 0 AND tree_right >= ".$dest['tree_right']." AND tree_right < ".$cat['tree_left']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left), tree_right = -(tree_right) WHERE tree_left < 0");
}
else
{
// caso B
$offset = $dest['tree_left'] - $cat['tree_left'] + 1 - $cat['tree_width'];
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left + ".$offset."), tree_right = -(tree_right + ".$offset.") WHERE tree_left BETWEEN ".$cat['tree_left']." AND ".$cat['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = tree_left - ".$cat['tree_width']." WHERE tree_left > 0 AND tree_left > ".$cat['tree_left']." AND tree_left <= ".$dest['tree_left']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_right = tree_right - ".$cat['tree_width']." WHERE tree_left > 0 AND tree_right > ".$cat['tree_right']." AND tree_right < ".$dest['tree_left']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left), tree_right = -(tree_right) WHERE tree_left < 0");
}
break;
case 'after':
if($dest['tree_right'] < $cat['tree_left'])
{
// caso C
$offset = $cat['tree_left'] - $dest['tree_right'] - 1;
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left - ".$offset."), tree_right = -(tree_right - ".$offset.") WHERE tree_left BETWEEN ".$cat['tree_left']." AND ".$cat['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = tree_left + ".$cat['tree_width']." WHERE tree_left > 0 AND tree_left > ".$dest['tree_right']." AND tree_left < ".$cat['tree_left']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_right = tree_right + ".$cat['tree_width']." WHERE tree_left > 0 AND tree_right > ".$dest['tree_right']." AND tree_right < ".$cat['tree_left']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left), tree_right = -(tree_right) WHERE tree_left < 0");
}
elseif($dest['tree_right'] > $cat['tree_left'] && $dest['tree_left'] < $cat['tree_left'])
{
// caso D
$offset = $dest['tree_right'] - $cat['tree_left'] + 1 - $cat['tree_width'];
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left + ".$offset."), tree_right = -(tree_right + ".$offset.") WHERE tree_left BETWEEN ".$cat['tree_left']." AND ".$cat['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = tree_left - ".$cat['tree_width']." WHERE tree_left > 0 AND tree_left > ".$cat['tree_right']." AND tree_right < ".$dest['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_right = tree_right - ".$cat['tree_width']." WHERE tree_left > 0 AND tree_right > ".$cat['tree_right']." AND tree_right <= ".$dest['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left), tree_right = -(tree_right) WHERE tree_left < 0");
}
else
{
// caso E
$offset = $dest['tree_right'] - $cat['tree_left'] + 1 - $cat['tree_width'];
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left + ".$offset."), tree_right = -(tree_right + ".$offset.") WHERE tree_left BETWEEN ".$cat['tree_left']." AND ".$cat['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = tree_left - ".$cat['tree_width']." WHERE tree_left > 0 AND tree_left > ".$cat['tree_right']." AND tree_left <= ".$dest['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_right = tree_right - ".$cat['tree_width']." WHERE tree_left > 0 AND tree_right > ".$cat['tree_right']." AND tree_right <= ".$dest['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left), tree_right = -(tree_right) WHERE tree_left < 0");
}
break;
case 'before':
if($dest['tree_left'] < $cat['tree_left'] && $dest['tree_right'] < $cat['tree_left'])
{
// caso F
$offset = $cat['tree_left'] - $dest['tree_left'];
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left - ".$offset."), tree_right = -(tree_right - ".$offset.") WHERE tree_left BETWEEN ".$cat['tree_left']." AND ".$cat['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = tree_left + ".$cat['tree_width']." WHERE tree_left > 0 AND tree_left >= ".$dest['tree_left']." AND tree_left < ".$cat['tree_left']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_right = tree_right + ".$cat['tree_width']." WHERE tree_left > 0 AND tree_right >= ".$dest['tree_left']." AND tree_right < ".$cat['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left), tree_right = -(tree_right) WHERE tree_left < 0");
}
elseif($dest['tree_left'] < $cat['tree_left'] && $dest['tree_right'] > $cat['tree_left'])
{
// caso G
$offset = $cat['tree_left'] - $dest['tree_left'];
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left - ".$offset."), tree_right = -(tree_right - ".$offset.") WHERE tree_left BETWEEN ".$cat['tree_left']." AND ".$cat['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = tree_left + ".$cat['tree_width']." WHERE tree_left > 0 AND tree_left >= ".$dest['tree_left']." AND tree_left < ".$cat['tree_left']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_right = tree_right + ".$cat['tree_width']." WHERE tree_left > 0 AND tree_right < ".$dest['tree_right']." AND tree_right < ".$cat['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left), tree_right = -(tree_right) WHERE tree_left < 0");
}
else
{
// caso H
$offset = $dest['tree_left'] - $cat['tree_left'] - $cat['tree_width'];
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left + ".$offset."), tree_right = -(tree_right + ".$offset.") WHERE tree_left BETWEEN ".$cat['tree_left']." AND ".$cat['tree_right']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = tree_left - ".$cat['tree_width']." WHERE tree_left > 0 AND tree_left > ".$cat['tree_left']." AND tree_left < ".$dest['tree_left']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_right = tree_right - ".$cat['tree_width']." WHERE tree_left > 0 AND tree_right > ".$cat['tree_right']." AND tree_right < ".$dest['tree_left']);
$this->DB->exec("UPDATE ".$this->treeTable." SET tree_left = -(tree_left), tree_right = -(tree_right) WHERE tree_left < 0");
}
break;
}
[/supersaibal]