4. Управление деревом
И вот, наконец, можно заняться управлением дерева. По структуре и принципу класс такой же как и модуль Perl, единственные отличия в операторах и специфицеских особенностях языка. Итак, функции, которые мы включим в класс:
- InsertUnit - создание узла;
- DeleteUnit - удаление узла и подчиненных;
- SetUnitUnder - перемещение узла в подчинение другому;
- SetUnitNear - перемещение узла рядом с другим;
- SetUnitLevel - изменение уровня узла (одни уровень вверх(вниз));
- SetUnitOrder - изменение порядка узла в пределах подчинения;
- _move_unit - внутренняя процедура перемещения узла и подчиненных;
Схемы и принципы описаны в предыдущих статьях, поэтому можно смело начинать писать код...
4.1. Создание (вставка) узла
function InsertUnit ($under = 'root', $tree = 1, $order) { if (!is_numeric($under)) {$under = 'root';} if (!is_numeric($tree)) {$tree = 1;} if ($under == 'root') { $level = 1; if ((isset($order) && $order == 'top') || $this->order == 'T') { $key = 1; } else { $sql = 'SELECT MAX('.$this->right.') + 1 AS nums FROM '.$this->table. ($this->type == 'M' ? ' WHERE '.$this->multi.' = '.$tree : ''); if (($query = mysql_query($sql)) && (mysql_num_rows($query) == 1) && ($Data = mysql_fetch_array($query))) {$key = $Data['nums'];} else {$key = 1;} } } else { $sql = 'SELECT '.$this->left.' AS lk, '. $this->right.' AS rk, '. $this->level.'AS lv'. ($this->type == 'M' ? ', '.$this->multi.' AS cl ' : ''). ' FROM '.$this->table.' WHERE '.$this->id.' = '.$under; if (($mysql_query = mysql_query($sql)) && (mysql_num_rows($mysql_query) == 1) && ($Data = mysql_fetch_array($mysql_query))) { $level = $Data['lv'] + 1; if ($this->type == 'M') {$tree = $Data['cl'];} if ((isset($order) && $order == 'top') || $this->order == 'T') { $key = $Data['cl']; } } else {trigger_error('ERR! Неправильный ID родительского узла!');} } $update = 'UPDATE '.$this->table.' SET '. $this->right.' = '.$this->right.' + 2, '. $this->left.' = CASE WHEN '.$this->left.' >= '.$key. ' THEN '.$this->left.' + 2 ELSE '.$this->left.' END WHERE '.$this->right.' >= '.$key. ($this->type == 'M' ? ' AND '.$this->multi.' = '.$tree : ''); mysql_query($update); // Список полей $update = 'INSERT INTO '.$this->table. ' ('.$this->left.', '. $this->right.', '. $this->level. ($this->type == 'M' ? ', '.$this->multi : ''). ') VAUES ('.$key.', '.($key + 1).', '.$level. ($this->type == 'M' ? ', '.$tree.')' : ')'); // Выполняем запрос mysql_query($update); // Получаем идентификатор вставленного узла $sql = 'SELECT MAX('.$this->id.') FROM '.$this->table; $mysql_query = mysql_query($sql); $id = mysql_fetch_array($mysql_query); return $id[0]; }
4.2. Удаление узла
// Удаление узла function DeleteUnit ($unit) { if (isset($unit)) {$this->SelectUnit($unit);} $skew_tree = $this->unit['right'] - $this->unit['left'] + 1; $update = 'DELETE FROM '.$this->table.' WHERE '.$this->left.'>='.$this->unit['left'].' AND '. $this->right.'<='.$this->unit['right']. ($this->type == 'M' ? ' AND '.$this->multi.'='.$this->unit['multi'] : ''); mysql_query($update); $update = 'UPDATE '.$this->table.' SET '.$this->left.'= CASE WHEN '.$this->left.'>'.$this->unit['left'].' THEN '.$this->left.'-'.$skew_tree.' ELSE '.$this->left.' END, '. $this->right.'='.$this->right.'-'.$skew_tree. ' WHERE '.$this->right.'>'.$this->unit['right']. ($this->type == 'M' ? ' AND '.$this->multi.'='.$this->unit['multi'] : ''); mysql_query($update); return 1; }
4.3. Перемещение узла
Процедуры перемещения узла начнем со стандартной, точнее, универсальной, которая, собственно, узлы и перемещает остальные процедуры просто определяют координаты перемещения. По сути, в процедуре всего два запроса, но довольно сложных.
// Внутренняя процедура перемещения узла function _move_unit ($data = array()) { if ($data['near'] >= $this->unit['left'] && $data['near'] <= $this->unit['right']) {return 'ERR';} $skew_tree = $this->unit['right'] - $this->unit['left'] + 1; $skew_level = $data['level_new'] - $this->unit['level']; // Перемещение вверх по дереву if ($this->unit['right'] < $data['near']) { $skew_edit = $data['near'] - $this->unit['left'] + 1 - $skew_tree; $sql = 'UPDATE '.$this->table.' SET '. $this->left.' = CASE WHEN '.$this->right.'<='.$this->unit['right'].' THEN '. $this->left.'+'.$skew_edit.' ELSE CASE WHEN '.$this->left.'>'.$this->unit['right'].' THEN '. $this->left.'-'.$skew_tree.' ELSE '.$this->left.' END END, '. $this->level.' = CASE WHEN '.$this->right.'<='.$this->unit['right'].' THEN '. $this->level.'+'.$skew_level.' ELSE '.$this->level.' END, '. $this->right.' = CASE WHEN '.$this->right.'<='.$this->unit['right'].' THEN '. $this->right.'+'.$skew_edit.' ELSE CASE WHEN '.$this->right.'<='.$data['near'].' THEN '. $this->right.'-'.$skew_tree.' ELSE '.$this->right.' END END WHERE '. $this->right.'>'.$this->unit['left'].' AND '. $this->left.'<='.$data['near']. ($this->type == 'M' ? ' AND '.$this->multi.'='.$this->unit['multi'] : ''); $mysql_query = mysql_query($sql); } else { // Перемещение вниз по дереву $skew_edit = $data['near'] - $this->unit['left'] + 1; $sql = 'UPDATE '.$this->table.' SET '. $this->right.' = CASE WHEN '.$this->left.'>='.$this->unit['left'].' THEN '. $this->right.'+'.$skew_edit.' ELSE CASE WHEN '.$this->right.'<'.$this->unit['left'].' THEN '. $this->right.'+'.$skew_tree.' ELSE '.$this->right.' END END, '. $this->level.' = CASE WHEN '.$this->left.'>='.$this->unit['left'].' THEN '. $this->level.'+'.$skew_level.' ELSE '.$this->level.' END, '. $this->left.' = CASE WHEN '.$this->left.'>='.$this->unit['left'].' THEN '. $this->left.'+'.$skew_edit.' ELSE CASE WHEN '.$this->left.'>'.$data['near'].' THEN '. $this->left.'+'.$skew_tree.' ELSE '.$this->left.' END END WHERE '. $this->right.'>'.$data['near'].' AND '. $this->left.'<'.$this->unit['right']. ($this->type == 'M' ? ' AND '.$this->multi.'='.$this->unit['multi'] : ''); $mysql_query = mysql_query($sql); } return 'OK'; }
Другие статьи по теме
|