Index: includes/tree.inc =================================================================== RCS file: includes/tree.inc diff -N includes/tree.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/tree.inc 9 Dec 2008 19:38:10 -0000 @@ -0,0 +1,491 @@ +addField($table, 'snv'); + $query->addField($table, 'sdv'); + $query->addField($table, 'flv'); + $query->condition('vid', $vid); + $query->condition(db_and() + ->condition('dv', '1') + ); + $query->orderBy('flv', 'ASC'); + $result = $query->execute(); + while ($term = $result->fetchObject()) { + $query = db_select($table); + $query->fields($table); + $query->condition('vid', $vid); + $query->condition(db_and() + ->condition('flv', $term->flv, '>') + ->condition('flv', bcdiv($term->snv, $term->sdv), '<') + ); + if ($depth > 0) { + $query->condition(db_and() + ->condition('depth', $depth, '<=') + ); + } + $tree = $query->execute()->fetchAll(); + } + } + else { + // all the tree for a nv, dv + $query = db_select($table); + $query->fields($table); + $query->condition('vid', $vid); + $query->condition(db_and() + ->condition('nv', $nv) + ->condition('dv', $dv) + ); + $term = $query->execute()->fetchObject(); + // calculate all the parent of the term + $ancnv = 0; + $ancdv = 1; + $ancsnv = 1; + $ancsdv = 0; + $numerator = $nv; + $denominator = $dv; + while ($numerator > 0 && $denominator > 0) { + $div = (int) ($numerator / $denominator); + $mod = $numerator % $denominator; + $ancnv = $ancnv + $div * $ancsnv; + $ancdv = $ancdv + $div * $ancsdv; + $ancsnv = $ancnv + $ancsnv; + $ancsdv = $ancdv + $ancsdv; + // grab the parent + $query = db_select($table); + $query->fields($table); + $query->condition('vid', $vid); + $query->condition(db_and() + ->condition('nv', $ancnv) + ->condition('dv', $ancdv) + ); + $tree[] = $query->execute()->fetchObject(); + $numerator = $mod; + if ($numerator > 0) { + $denominator = $denominator - $mod; + if ($denominator == 0) { + $denominator == 1; + } + } + } + // grab the children + $query = db_select($table); + $query->fields($table); + $query->condition('vid', $vid); + $query->condition(db_and() + ->condition('flv', $term->flv, '>') + ->condition('flv', bcdiv($term->snv, $term->sdv), '<') + ); + if ($depth > 0) { + $query->condition(db_and() + ->condition('depth', $term->depth + $depth, '<=') + ); + } + $result = $query->execute(); + while ($child = $result->fetchObject()) { + $tree[] = $child; + } + } + return $tree; + +} + + +/** + * save a term in a tree with his parents as input + * + * @param $parents + * contains the parents to store, each element the nv,dv values + * also contains the tid and vid of the term + * @param $table + * database table to use + */ +function tree_term_save(&$parents, $table = 'term_hierarchy') { + if (count($parents->parent)>0) { + bcscale(21); + foreach ($parents->parent as $parent) { + //multiple parent case ordering needs to be done elsewhere, + //we insert at the rightest position in a level + // get values of parent + $query = db_select($table); + $query->fields($table); + $query->condition('vid', $parents->vid); + $query->condition(db_and() + ->condition('nv', $parent["nv"]) + ->condition('dv', $parent["dv"]) + ); + $p = $query->execute()->fetchObject(); + // get last right son + $query = db_select($table); + $query->addField($table, 'snv'); + $query->addField($table, 'sdv'); + $query->condition('vid', $p->vid); + $query->condition(db_and() + ->condition('pflv', $p->nv. '-'.$p->dv) + ); + $query->orderBy('flv', 'DESC'); + $query->range(0, 1); + $s = $query->execute()->fetchObject(); + if (isset($s->snv)) { + $nv = $s->snv; + $dv = $s->sdv; + } + else { + $nv = $p->nv + $p->snv; + $dv = $p->dv + $p->sdv; + } + $query = db_select($table); + $query->condition('vid', $p->vid); + $query->condition(db_and() + ->condition('pflv', $p->nv. '-'.$p->dv) + ); + $child_num = $query->countQuery()->execute()->fetchField(); + if ($child_num == 0) { + $child_num = 1; + } + else { + $child_num = $child_num + 1; + } + // insert term + db_insert($table) + ->fields(array( + 'tid' => $parents->tid, + 'nv' => $nv, + 'dv' => $dv, + 'snv' => bcadd($p->nv , ($child_num + 1) * $p->snv, 0), + 'sdv' => bcadd($p->dv , ($child_num + 1) * $p->sdv, 0), + 'flv' => bcdiv($nv, $dv), + 'pflv' => $p->nv . '-' . $p->dv, + 'vid' => $p->vid, + 'depth' => ($p->depth + 1), + )) + ->execute(); + } + } + else { + #top level insert + #we need in this case the vid in parents + $query = db_select($table); + $query->addExpression('MAX(nv)', 'max'); + $query->condition('vid', $parents->vid); + $query->condition(db_and() + ->condition('depth', 0) + ); + $max = $query->execute()->fetchField(); + if ($max == 0) { + $nv = 2; + } + else { + $nv = $max +1; + } + db_insert($table) + ->fields(array( + 'tid' => $parents->tid, + 'nv' => $nv, + 'dv' => 1, + 'snv' => $nv + 1, + 'sdv' => 1, + 'flv' => $nv, + 'pflv' => 0, + 'vid' => $parents->vid, + 'depth' => 0, + )) + ->execute(); + } +} + +/** + * remove an element of a tree + * @param $nv + * numerator value of the term + * @param $dv + * denominator value of the term + * @param $tid + * taxonomy term id, for complete removal purpose + * @param $table + * database table to use + */ +function tree_term_del($nv, $dv, $tid = NULL, $vid, $table = 'term_hierarchy') { + #TODO : remove the term +} + +/** + * move a subtree from under a term, to under the mth child of a term + * @param $nv + * numerator value of the term + * @param $dv + * denominator value of the term + * @param $pnv + * numerator value of parent of the term underneath the subtree will be moved + * @param $pdv + * denominator value of parent of the term underneath the subtree will be moved + * @param $m + * child number of the new root. The subtree, will be under this child + * @param $vid + * vid value of the term + * @param $table + * database table to use + */ +function tree_subtree_move($nv, $dv, $pnv, $pdv, $m, $vid, $table = 'term_hierarchy') { + $query = db_select($table); + $query->fields($table); + $query->condition('vid', $vid); + $query->condition(db_and() + ->condition('nv', $nv) + ->condition('dv', $dv) + ); + $sub = $query->execute()->fetchObject(); + $s = explode('-', $sub->pflv); + $rnv = $s[0]; + $rdv = $s[1]; + $query = db_select($table); + $query->fields($table); + $query->condition('vid', $vid); + $query->condition(db_and() + ->condition('nv', $rnv) + ->condition('dv', $rdv) + ); + $root = $query->execute()->fetchObject(); + $children = tree_children_get_all($nv, $dv, $vid , $table); + $query = db_select($table); + $query->fields($table); + $query->condition('vid', $vid); + $query->condition(db_and() + ->condition('nv', $pnv) + ->condition('dv', $pdv) + ); + $new_root = $query->execute()->fetchObject(); + #calculate root child number (n) + $query = db_select($table); + $query->condition('vid', $vid); + $query->condition(db_and() + ->condition('flv', $sub->flv, '<') + ->condition('pflv', $sub->pflv) + ); + $c_child = $query->countQuery()->execute()->fetchField(); + if ($c_child == 0) { + $n = 1; + } + else { + $n = $c_child + 1; + } + bcscale(21); + #calculate nv and dv of the mth child of new_root for updating the parent + #calculate children relocation + foreach ($children as $child) { + $child->new_nv1 = bcadd(($new_root->nv + ($m -$n) * $new_root->snv) * (- $root->sdv), $new_root->snv * $root->dv, 0); + $child->new_dv1 = bcadd(($new_root->dv + ($m -$n) * $new_root->sdv) * (- $root->sdv), $new_root->sdv * $root->dv, 0); + $child->new_snv1 = bcadd(($new_root->nv + ($m -$n) * $new_root->snv) * $root->snv, $new_root->snv * (- $root->nv), 0); + $child->new_sdv1 = bcadd(($new_root->dv + ($m -$n) * $new_root->sdv) * $root->snv, $new_root->sdv * (- $root->nv), 0); + + $child->new_nv = bcadd($child->new_nv1 * $child->nv, $child->new_snv1 * $child->dv, 0); + $child->new_dv = bcadd($child->new_dv1 * $child->nv, $child->new_sdv1 * $child->dv, 0); + $child->new_snv = bcadd($child->new_nv1 * $child->snv, $child->new_snv1 * $child->sdv, 0); + $child->new_sdv = bcadd($child->new_dv1 * $child->snv, $child->new_sdv1 * $child->sdv, 0); + #we need to get the parent numerator and denominator values + $ancnv = 0; + $ancdv = 1; + $ancsnv = 1; + $ancsdv = 0; + $numerator = $child->new_nv; + $denominator = $child->new_dv; + while ($numerator > 0 && $denominator > 0) { + $div = (int)($numerator / $denominator); + $mod = $numerator % $denominator; + $parent_ancnv = $ancnv; + $parent_ancdv = $ancdv; + $ancnv = bcadd($ancnv, $div * $ancsnv, 0); + $ancdv = bcadd($ancdv, $div * $ancsdv, 0); + $ancsnv = bcadd($ancnv, $ancsnv, 0); + $ancsdv = bcadd($ancdv, $ancsdv, 0); + $numerator = $mod; + if ($numerator>0) { + $denominator = bcsub($denominator , $mod); + if ($denominator == 0) { + $denominator == 1; + } + } + } + db_update($table) + ->fields(array( + 'nv' => $child->new_nv, + 'dv' => $child->new_dv, + 'snv' => $child->new_snv, + 'sdv' => $child->new_sdv, + 'depth' => $new_root->depth + ($child->depth - $root->depth), + 'flv' => bcdiv($child->new_nv, $child->new_dv), + 'pflv' => $parent_ancnv . '-' . $parent_ancdv, + )) + ->condition('nv', $child->nv) + ->condition(db_and() + ->condition('dv', $child->dv) + ->condition('vid', $vid) + )->execute(); + } + +} + +/** + * get the parents of a term + * @param $nv + * numerator value of the term + * @param $dv + * denominator value of the term + * @param $vid + * vid value of the term + * @param $table + * database table to use + */ + +function tree_parents_get($nv, $dv, $vid, $table = 'term_hierarchy') { + // first take nv / dv of the flv + // calculate all the parent of the term + $ancnv = 0; + $ancdv = 1; + $ancsnv = 1; + $ancsdv = 0; + $numerator = $nv; + $denominator = $dv; + $parents = array(); + while ($numerator > 0 && $denominator > 0) { + $div = (int)($numerator / $denominator); + $mod = $numerator % $denominator; + $ancnv = $ancnv + $div * $ancsnv; + $ancdv = $ancdv + $div * $ancsdv; + $ancsnv = $ancnv + $ancsnv; + $ancsdv = $ancdv + $ancsdv; + // grab the parent + $query = db_select($table); + $query->fields($table); + $query->condition('vid', $vid); + $query->condition(db_and() + ->condition('nv', $ancnv) + ->condition('dv', $ancdv) + ); + $parents[] = $query->execute()->fetchObject(); + $numerator = $mod; + if ($numerator>0) { + $denominator = $denominator - $mod; + if ($denominator == 0) { + $denominator == 1; + } + } + } + return $parents; +} + +/** + * get the first level childrens of a term + * @param $nv + * numerator value of the term + * @param $dv + * denominator value of the term + * @param $vid + * vid value of the term + * @param $table + * database table to use + */ + +function tree_children_get($nv, $dv, $vid , $table = 'term_hierarchy') { + #first find nv and dv for the first child + if ($dv == 1) { + $flv = 0; + } + else { + $flv = $nv . '-' . $dv; + } + $query = db_select($table); + $query->fields($table); + $query->condition('vid', $vid); + $query->condition(db_and() + ->condition('pflv', $flv) + ); + $query->orderBy('nv', 'ASC'); + $children = $query->execute()->fetchAll(); + return $children; + +} + +/** + * get the all level childrens of a term + * @param $nv + * numerator value of the term + * @param $dv + * denominator value of the term + * @param $vid + * vid value of the term + * @param $table + * database table to use + */ + +function tree_children_get_all($nv, $dv, $vid , $table = 'term_hierarchy') { + bcscale(21); + $query = db_select($table); + $query->fields($table); + $query->condition('vid', $vid); + $query->condition(db_and() + ->condition('nv', $nv) + ->condition('dv', $dv) + ); + $term = $query->execute()->fetchObject(); + $query = db_select($table); + $query->fields($table); + $query->condition('vid', $vid); + $query->condition(db_and() + ->condition('flv', $term->flv, '>') + ->condition('flv', bcdiv($term->snv, $term->sdv), '<') + ); + $children = $query->execute()->fetchAll(); + return $children; + +} +?>