Index: modules/taxonomy/taxonomy.module =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v retrieving revision 1.603 diff -u -p -r1.603 taxonomy.module --- modules/taxonomy/taxonomy.module 22 Aug 2010 15:45:03 -0000 1.603 +++ modules/taxonomy/taxonomy.module 30 Aug 2010 11:22:43 -0000 @@ -801,21 +801,17 @@ function taxonomy_get_children($tid, $vi * for the entire vocabulary. * @param $max_depth * The number of levels of the tree to return. Leave NULL to return all levels. - * @param $depth - * Internal use only. * * @return * An array of all term objects in the tree. Each term object is extended * to have "depth" and "parents" attributes in addition to its normal ones. * Results are statically cached. */ -function taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL, $depth = -1) { +function taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL) { $children = &drupal_static(__FUNCTION__, array()); $parents = &drupal_static(__FUNCTION__ . ':parents', array()); $terms = &drupal_static(__FUNCTION__ . ':terms', array()); - $depth++; - // We cache trees, so it's not CPU-intensive to call get_tree() on a term // and its children, too. if (!isset($children[$vid])) { @@ -839,19 +835,46 @@ function taxonomy_get_tree($vid, $parent $parents[$vid][$tid][] = $parent_tid; } } - - $max_depth = (is_null($max_depth)) ? count($children[$vid]) : $max_depth; + $tree = array(); - if ($max_depth > $depth && !empty($children[$vid][$parent])) { - foreach ($children[$vid][$parent] as $child) { - $term = clone $terms[$vid][$child]; - $term->depth = $depth; - $term->parents = $parents[$vid][$child]; - $tree[] = $term; - if (!empty($children[$vid][$child])) { - $tree = array_merge($tree, taxonomy_get_tree($vid, $child, $max_depth, $depth)); + $max_depth = (is_null($max_depth)) ? count($children[$vid]) : $max_depth; + $prev_parents = array(); //stores the parents we have to process + while (true) { + $depth = count($prev_parents); + if ($max_depth > $depth && !empty($children[$vid][$parent])) { + $has_children = FALSE; + $child = current($children[$vid][$parent]); + do { + if (empty($child)) { + break; + } + $term = clone $terms[$vid][$child]; + $term->depth = $depth; + $term->parents = $parents[$vid][$child]; + $tree[] = $term; + if (!empty($children[$vid][$child])) { + $prev_parents[] = $parent; //we have to continue with the current parent later + $prev_parents[] = $child; //use $child for the next iteration + reset($children[$vid][$child]); // reset pointers for child lists as we step in there more often with multi parents + next($children[$vid][$parent]); //move pointer so that we get the correct term the next time + $has_children = TRUE; + break; + } + } while ($child = next($children[$vid][$parent])); + + if (!$has_children) { + //we processed all terms in this hierarchy-level + //reset pointer so that this function works the next time it gets called + reset($children[$vid][$parent]); } } + + if (count($prev_parents)) { + $parent = array_pop($prev_parents); + } + else { + break; + } } return $tree;