riquito / Baobab

A library applying the nested set model
http://baobab.sideralis.org
Apache License 2.0
90 stars 27 forks source link

Duplicate branch? #9

Closed irrelevantdotcom closed 8 years ago

irrelevantdotcom commented 8 years ago

I have a use-case where I will frequently need to duplicate a record and all of it's descendants to another part of the same tree, and occasionally delete them again. Is there a simple way of doing this, or should I just call getChildren() / getNodeData recursively ?

irrelevantdotcom commented 8 years ago

Answering my own question. deleteNode() kills off all it's own children, so that part is easy.

Duplication... Wrote this and it seems to work for me: `
public function duplicateBranch($id_node, $new_parent){

    // fetch node and all decendants into an array.
    $branch = $this->_db_retrieve($id_node, 0);

    $idmap = array();
    $idmap[0] = $new_parent;

    foreach ($branch as $twig) {
        // get all record data
        $details = $this->getNodeData($twig[0]);
        // remove system fields
        unset ($details['tree_id'], $details['id'], $details['lft'], $details['rgt']);
        // add new child.
        $newtwig = $this->appendChild($idmap[$twig[1]], $details);
        $idmap[$twig[0]] = $newtwig;
    }

    return $idmap[$id_node];
}

/*  This function fetches a node and all it's decendents into a flat array.
   Unlike getDecendents, this includes the parent id for each node.
   By the nature of the search, each node's parents will be before it in the list
   This will be slower than getDecendents as it does a query for each level.
*/

function _db_retrieve($id_node, $parent){

    $r = array();
    $r[] = array($id_node, $parent);

    foreach ($this->getChildren($id_node) as $id_child) {
        $r = array_merge($r, $this->_db_retrieve($id_child, $id_node));
    }
    return $r;
}

`