diff options
author | Tim Almdal <tnalmdal@shaw.ca> | 2008-12-04 20:05:58 +0000 |
---|---|---|
committer | Tim Almdal <tnalmdal@shaw.ca> | 2008-12-04 20:05:58 +0000 |
commit | 0f103b1c069063a2e6109a0ba7e566104f4ba8fa (patch) | |
tree | 8b7e26b0ef3650a6b90c0b9602da6b37bf3437f3 | |
parent | 80a7db61c9fba53477c1ec0850bdffaf7b11657a (diff) |
Moving albums around with a drag and drop interface seems to work and preserve the left right pointers.
* changed _lock and _unlock to protected methods lock and lock respectively
* added a moveTo method on the Item_Model
* Corrected the hole closure on delete.
* added moveTo on the ORM_MTPP class
* Changed the rearrange javascript to do moves with ajax
-rw-r--r-- | core/controllers/welcome.php | 2 | ||||
-rw-r--r-- | core/libraries/ORM_MPTT.php | 97 | ||||
-rw-r--r-- | core/models/item.php | 26 | ||||
-rw-r--r-- | modules/rearrange/controllers/rearrange.php | 26 | ||||
-rw-r--r-- | modules/rearrange/js/jquery.gallery.rearrange.tree.js | 18 |
5 files changed, 146 insertions, 23 deletions
diff --git a/core/controllers/welcome.php b/core/controllers/welcome.php index 8f8421d3..1d2082d4 100644 --- a/core/controllers/welcome.php +++ b/core/controllers/welcome.php @@ -125,7 +125,7 @@ class Welcome_Controller extends Template_Controller { $data = "digraph G {\n"; foreach ($items as $item) { $data .= " $item->parent_id -> $item->id\n"; - $data .= " $item->id [label=\"$item->id <$item->left, $item->right>\"]\n"; + $data .= " $item->id [label=\"$item->id $item->title <$item->left, $item->right>\"]\n"; } $data .= "}\n"; diff --git a/core/libraries/ORM_MPTT.php b/core/libraries/ORM_MPTT.php index bac4da92..2290c83a 100644 --- a/core/libraries/ORM_MPTT.php +++ b/core/libraries/ORM_MPTT.php @@ -53,7 +53,7 @@ class ORM_MPTT_Core extends ORM { * @return ORM */ function add_to_parent($parent_id) { - $this->_lock(); + $this->lock(); try { // Make a hole in the parent for this new item @@ -71,11 +71,11 @@ class ORM_MPTT_Core extends ORM { $this->level = $parent->level + 1; $this->save(); } catch (Exception $e) { - $this->_unlock(); + $this->unlock(); throw $e; } - $this->_unlock(); + $this->unlock(); return $this; } @@ -93,18 +93,18 @@ class ORM_MPTT_Core extends ORM { $this->reload(); } - $this->_lock(); + $this->lock(); try { $this->db->query( - "UPDATE `{$this->table_name}` SET `left` = `left` - 2 WHERE `left` >= {$this->right}"); + "UPDATE `{$this->table_name}` SET `left` = `left` - 2 WHERE `left` > {$this->right}"); $this->db->query( - "UPDATE `{$this->table_name}` SET `right` = `right` - 2 WHERE `right` >= {$this->right}"); + "UPDATE `{$this->table_name}` SET `right` = `right` - 2 WHERE `right` > {$this->right}"); } catch (Exception $e) { - $this->_unlock(); + $this->unlock(); throw $e; } - $this->_unlock(); + $this->unlock(); parent::delete(); } @@ -225,11 +225,88 @@ class ORM_MPTT_Core extends ORM { return parent::reload(); } + /** + * Move this item to the specified target. + * + * @chainable + * @param Item_Model $target Target item (must be an album + * @param boolean $locked The called is already holding the lock + * @return ORM_MTPP + */ + function moveTo($target, $locked=false) { + if ($target->type != "album") { + throw new Exception("@todo '{$target->type}' IS NOT A VALID MOVE TARGET"); + } + + if ($this->id == 1) { + throw new Exception("@todo '{$this->title}' IS NOT A VALID SOURCE"); + } + + $numberToMove = (int)(($this->right - $this->left) / 2 + 1); + $size_of_hole = $numberToMove * 2; + $original_parent = $this->parent; + + if (empty($locked)) { + $this->lock(); + } + try { + // Make a hole in the target for the move + $target->db->query( + "UPDATE `{$target->table_name}` SET `left` = `left` + $size_of_hole" . + " WHERE `left` >= {$target->right}"); + $target->db->query( + "UPDATE `{$target->table_name}` SET `right` = `right` + $size_of_hole" . + " WHERE `right` >= {$target->right}"); + + // Change the parent. + $this->db->query( + "UPDATE `{$this->table_name}` SET `parent_id` = {$target->id}" . + " WHERE `id` = {$this->id}"); + + // If the source is to the right of the target then we just adjusted its left and right above. + $left = $this->left; + $right = $this->right; + if ($this->left > $target->right) { + $left += $size_of_hole; + $right += $size_of_hole; + } + + $newOffset = $target->left - $left + 1; + $this->db->query( + "UPDATE `{$this->table_name}`" . + " SET `left` = `left` + $newOffset," . + " `right` = `right` + $newOffset" . + " WHERE `left` >= $left" . + " AND `right` <= $right"); + + // Close the hole in the source's parent after the move + $this->db->query( + "UPDATE `{$this->table_name}` SET `left` = `left` - $size_of_hole" . + " WHERE `left` > $right"); + $this->db->query( + "UPDATE `{$this->table_name}` SET `right` = `right` - $size_of_hole" . + " WHERE `right` > $right"); + + } catch (Exception $e) { + if (empty($locked)) { + $this->unlock(); + } + throw $e; + } + + if (empty($locked)) { + $this->_unlock(); + } + + // Lets reload to get the changes. + $this->reload(); + return $this; + } /** * Lock the tree to prevent concurrent modification. */ - private function _lock() { + protected function lock() { $result = $this->db->query("SELECT GET_LOCK('{$this->table_name}', 1) AS L")->current(); if (empty($result->L)) { throw new Exception("@todo UNABLE_TO_LOCK_EXCEPTION"); @@ -239,7 +316,7 @@ class ORM_MPTT_Core extends ORM { /** * Unlock the tree. */ - private function _unlock() { + protected function unlock() { $this->db->query("SELECT RELEASE_LOCK('{$this->table_name}')"); } } diff --git a/core/models/item.php b/core/models/item.php index fbaca0e7..495508ec 100644 --- a/core/models/item.php +++ b/core/models/item.php @@ -53,6 +53,32 @@ class Item_Model extends ORM_MPTT { } /** + * Move this item to the specified target. + * + * @chainable + * @param Item_Model $target Target item (must be an album + * @return ORM_MTPP + */ + function moveTo($target) { + $this->lock(); + try { + $original_path = $this->file_path(); + + parent::moveTo($target, true); + + $new_path = $this->file_path(); + rename($original_path, $new_path); + + } catch (Exception $e) { + $this->unlock(); + throw $e; + } + + $this->unlock(); + return $this; + } + + /** * album: /var/albums/album1/album2 * photo: /var/albums/album1/album2/photo.jpg */ diff --git a/modules/rearrange/controllers/rearrange.php b/modules/rearrange/controllers/rearrange.php index 59c1b069..6118e07e 100644 --- a/modules/rearrange/controllers/rearrange.php +++ b/modules/rearrange/controllers/rearrange.php @@ -22,14 +22,26 @@ class Rearrange_Controller extends Controller { public function show($id=null) { $view = new View("rearrange_item_list.html"); - if (empty($id)) { - $item = ORM::factory("item", 1); - $view->children = array($item); - } else { - $item = ORM::factory("item", $id); - $view->children = $item->children(); - } + $isRoot = empty($id); + $item = ORM::factory("item", $isRoot ? 1 : $id); + + $view->children = $isRoot ? array($item) : $item->children(); print $view; } + + public function move($source_id, $target_id) { + $source = ORM_MPTT::factory("item", $source_id); + $target = ORM_MPTT::factory("item", $target_id); + + try { + $source->moveTo($target); + print "success"; + } catch (Exception $e) { + Kohana::log("error", $e->getMessage() . "\n" + $e->getTraceAsString()); + header("HTTP/1.1 500"); + print $e->getMessage(); + } + } + }
\ No newline at end of file diff --git a/modules/rearrange/js/jquery.gallery.rearrange.tree.js b/modules/rearrange/js/jquery.gallery.rearrange.tree.js index 09284a25..c423becd 100644 --- a/modules/rearrange/js/jquery.gallery.rearrange.tree.js +++ b/modules/rearrange/js/jquery.gallery.rearrange.tree.js @@ -70,9 +70,19 @@ if(jQuery) (function($){ hoverClass: "droppable-hover", drop: function(ev, ui) { source_element = ui.draggable; - source_parent = source_element.parent(); + source_parent = getParent(source_element); target = ui.element; - alert(source_element.attr("id") + "\n" + target.attr("id")); + + $.ajax({ + url: "rearrange/move/" + source_element.attr("id") + "/" + target.attr("id"), + success: function(data, textStatus) { + collapse(source_parent); + showTree(source_parent, source_parent.attr("id")); + }, + error: function(xhr, textStatus, errorThrown) { + alert("Http Error Code: " + xhr.status + "Text Status: " + textStatus); + } + }); } }); bindTree(c); @@ -168,9 +178,7 @@ if(jQuery) (function($){ showTree(parent, parent.attr("id")); }, error: function(xhr, textStatus, errorThrown) { - alert(xhr.status); - alert(textStatus); - alert(errorThrown); + alert("Http Error Code: " + xhr.status + "Text Status: " + textStatus); }, type: "DELETE" }); |