=== modified file 'includes/common.inc' --- includes/common.inc 2009-11-08 12:43:40 +0000 +++ includes/common.inc 2009-11-08 21:28:26 +0000 @@ -4936,14 +4936,21 @@ function drupal_render_page($page) { */ function drupal_render(&$elements) { static $defaults; + // This variable contains the elements to be rendered. Each piece on the stack + // is an assocative array with two keys: elements is the parent elements and + // key is the actual key. Each POP from the stack is the equivalent of a + // drupal_render($elements[$key]) call. + $stack = array(); + $output = ''; + do { // Early-return nothing if user does not have access. if (!isset($elements) || (isset($elements['#access']) && !$elements['#access'])) { - return; + continue; } // Do not print elements twice. if (isset($elements['#printed']) && $elements['#printed']) { - return; + continue; } // Try to fetch the element's markup from cache and return. @@ -4980,7 +4987,8 @@ function drupal_render(&$elements) { } } - // Get the children of the element, sorted by weight. + // Get the children of the element sorted by weight. The elements + // themselves are sorted, too. $children = element_children($elements, TRUE); // Initialize this element's #children, unless a #pre_render callback already @@ -4997,8 +5005,18 @@ function drupal_render(&$elements) { // This is the same process as drupal_render_children() but is inlined // for speed. if ($elements['#children'] == '') { - foreach ($children as $key) { - $elements['#children'] .= drupal_render($elements[$key]); + $current_size = count($stack); + $new_size = $current_size + count($children); + // We need to reverse the array but there is no point to array_reverse + // and then add the keys to the stack, both can be done in one loop. + for ($i = $current_size; $i < $new_size; $i++) { + $stack[$i] = array('elements' => &$elements, 'key' => $children[$new_size - $i -1]); + } + if ($children) { + // Break references. It's not possible to put this in the for header + // because unset is not a function but a language construct. + unset($elements); + continue; } } @@ -5037,7 +5055,12 @@ function drupal_render(&$elements) { } $elements['#printed'] = TRUE; - return $prefix . $elements['#children'] . $suffix; + $output .= $prefix . $elements['#children'] . $suffix; + // Break references. It's not possible to put this in the for header. + unset($elements); + // POP a piece from the stack and if succeeded, also load $elements. + } while (($data = array_pop($stack)) && ($elements = &$data['elements'][$data['key']])); + return $output; } /**