Issue #2756297 by hgoto, David_Rothstein, mcdruid, izmeez, pcambra, joseph.olstad, MustangGB, Fabianx, stefan.r, catch, kiamlaluno: element_children sort order inconsistent between PHP 5 and PHP 7

merge-requests/21/head
mcdruid 2020-11-24 21:19:26 +00:00
parent ccf81627dd
commit 86e0022d36
2 changed files with 43 additions and 6 deletions

View File

@ -6653,30 +6653,41 @@ function element_children(&$elements, $sort = FALSE) {
$sort = isset($elements['#sorted']) ? !$elements['#sorted'] : $sort;
// Filter out properties from the element, leaving only children.
$children = array();
$count = count($elements);
$child_weights = array();
$i = 0;
$sortable = FALSE;
foreach ($elements as $key => $value) {
if (is_int($key) || $key === '' || $key[0] !== '#') {
$children[$key] = $value;
if (is_array($value) && isset($value['#weight'])) {
$weight = $value['#weight'];
$sortable = TRUE;
}
else {
$weight = 0;
}
// Support weights with up to three digit precision and conserve the
// insertion order.
$child_weights[$key] = floor($weight * 1000) + $i / $count;
}
$i++;
}
// Sort the children if necessary.
if ($sort && $sortable) {
uasort($children, 'element_sort');
asort($child_weights);
// Put the sorted children back into $elements in the correct order, to
// preserve sorting if the same element is passed through
// element_children() twice.
foreach ($children as $key => $child) {
foreach ($child_weights as $key => $weight) {
$value = $elements[$key];
unset($elements[$key]);
$elements[$key] = $child;
$elements[$key] = $value;
}
$elements['#sorted'] = TRUE;
}
return array_keys($children);
return array_keys($child_weights);
}
/**

View File

@ -2051,6 +2051,32 @@ class DrupalRenderTestCase extends DrupalWebTestCase {
// The elements should appear in output in the same order as the array.
$this->assertTrue(strpos($output, $second) < strpos($output, $first), 'Elements were not sorted.');
// The order of children with same weight should be preserved.
$element_mixed_weight = array(
'child5' => array('#weight' => 10),
'child3' => array('#weight' => -10),
'child1' => array(),
'child4' => array('#weight' => 10),
'child2' => array(),
'child6' => array('#weight' => 10),
'child9' => array(),
'child8' => array('#weight' => 10),
'child7' => array(),
);
$expected = array(
'child3',
'child1',
'child2',
'child9',
'child7',
'child5',
'child4',
'child6',
'child8',
);
$this->assertEqual($expected, element_children($element_mixed_weight, TRUE), 'Order of elements with the same weight is preserved.');
}
/**