public function update(array $menu, $root = null) { // No root passed, so get the tree root node if (is_null($root)) { $root = $this->data; } // Previous menu item id $previous = null; // Processed menu items // Declared static so recursion can set it's value static $processed = array(); foreach ($menu as $item) { // Get id from input and find the model $id = \Arr::get($item, 'id'); $model = Model_Menu::find($id); // If model is not found then forge it is_null($model) and $model = Model_Menu::forge(); $properties = $this->prep_props($item); $model->set($properties); // If this is the first child then set it to parent // Otherwise set it next to the previous node if (is_null($previous)) { $model->first_child($root)->save(); } else { $model->next_sibling($previous)->save(); } // Is this a new menu item? Get it's id is_null($id) and $id = $model->id; // Set the previous node $previous = $model; // This menu item is processed $processed[] = $id; // If there are children then call the function again empty($item['children']) or $this->update($item['children'], $model); } // We are back from recusion: the current root is the tree root node if ($root->is_root()) { // Remove processed nodes from all nodes, so we can delete unused ones $nodes = $root->descendants()->get(); \Arr::delete($nodes, $processed); foreach ($nodes as $id => $model) { $model->delete(); } } return true; }