summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngie Byron <webchick@24967.no-reply.drupal.org>2009-02-09 03:29:54 +0000
committerAngie Byron <webchick@24967.no-reply.drupal.org>2009-02-09 03:29:54 +0000
commitc591f4562df55d7c656e201b17c6ce6f84d22926 (patch)
tree5bdbbe4aa13e1599be6045ee9d05d63153821379
parent341a95b80353ce93c62050c3051c6402063da5dc (diff)
downloadbrdo-c591f4562df55d7c656e201b17c6ce6f84d22926.tar.gz
brdo-c591f4562df55d7c656e201b17c6ce6f84d22926.tar.bz2
#370846 by catch: Further improve performance of drupal_render() sorting (with tests).
-rw-r--r--includes/common.inc45
-rw-r--r--modules/simpletest/tests/common.test23
2 files changed, 52 insertions, 16 deletions
diff --git a/includes/common.inc b/includes/common.inc
index fe8401dc9..9c4bb5492 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -3323,13 +3323,8 @@ function drupal_render(&$elements) {
}
}
- // Sort the elements by weight if they have not been sorted elsewhere already,
- // for example by a database query. Pre-sorted elements should have
- // $elements['#sorted'] set to TRUE to avoid unnecessary calls to uasort().
- if (empty($elements['#sorted'])) {
- uasort($elements, 'element_sort');
- $elements['#sorted'] = TRUE;
- }
+ // Get the children of the element, sorted by weight.
+ $children = element_children($elements, TRUE);
$elements['#children'] = '';
// Call the element's #theme function if it is set. Then any children of the
@@ -3340,7 +3335,7 @@ function drupal_render(&$elements) {
// If #theme was not set and the element has children, render them now
// using drupal_render_children().
if ($elements['#children'] == '') {
- $elements['#children'] = drupal_render_children($elements);
+ $elements['#children'] = drupal_render_children($elements, $children);
}
// Let the theme function in #theme_wrapper add markup around the rendered
@@ -3474,16 +3469,36 @@ function element_child($key) {
}
/**
- * Get keys of a structured array tree element that are not properties (i.e., do not begin with '#').
+ * Return the children of an element, optionally sorted by weight.
+ *
+ * @param $elements
+ * The element to be sorted.
+ * @param $sort
+ * Boolean to indicate whether the children should be sorted by weight.
+ * @return
+ * The array keys of the element's children.
*/
-function element_children($element) {
- $keys = array();
- foreach(array_keys($element) as $key) {
- if ($key[0] !== '#') {
- $keys[] = $key;
+function element_children(&$elements, $sort = FALSE) {
+ // Do not attempt to sort elements which have already been sorted.
+ $sort = isset($elements['#sorted']) ? !$elements['#sorted'] : $sort;
+
+ // Filter out properties from the element, leaving only children.
+ $children = array();
+ $sortable = FALSE;
+ foreach ($elements as $key => $value) {
+ if ($key[0] !== '#') {
+ $children[$key] = $value;
+ if (is_array($value) && isset($value['#weight'])) {
+ $sortable = TRUE;
+ }
}
}
- return $keys;
+ // Sort the element if necessary.
+ if ($sort && $sortable) {
+ uasort($children, 'element_sort');
+ }
+ $elements['#sorted'] = TRUE;
+ return array_keys($children);
}
/**
diff --git a/modules/simpletest/tests/common.test b/modules/simpletest/tests/common.test
index a6f1053e6..9d8c1d23f 100644
--- a/modules/simpletest/tests/common.test
+++ b/modules/simpletest/tests/common.test
@@ -535,8 +535,29 @@ class DrupalRenderUnitTestCase extends DrupalWebTestCase {
),
);
$output = drupal_render($elements);
+
// The lowest weight element should appear last in $output.
- $this->assertTrue(strpos($output, $second) > strpos($output, $first), t('Elements were sorted correctly by weight'));
+ $this->assertTrue(strpos($output, $second) > strpos($output, $first), t('Elements were sorted correctly by weight.'));
+
+ // Confirm that the $elements array has '#sorted' set to TRUE.
+ $this->assertTrue($elements['#sorted'], t("'#sorted' => TRUE was added to the array"));
+
+ // Now the same array structure, but with #sorted set to TRUE.
+ $elements = array(
+ 'second' => array(
+ '#weight' => 10,
+ '#markup' => $second,
+ ),
+ 'first' => array(
+ '#weight' => 0,
+ '#markup' => $first,
+ ),
+ '#sorted' => TRUE,
+ );
+ $output = drupal_render($elements);
+
+ // The elements should appear in output in the same order as the array.
+ $this->assertTrue(strpos($output, $second) < strpos($output, $first), t('Elements were not sorted.'));
}
}