Problem/Motivation

- Core uses uasort in quite a few places, but uasort does not preserve the sort order

Hence while:

$test = [
  'foo:1' => [ '#markup' => 'foo - first' ],
  'bar:2' => [ '#markup' => 'bar - second' ],
];

works

$test = [
  'foo:1' => [ '#markup' => 'foo - first' ],
  'bar:2' => [ '#markup' => 'bar - second' ],
  'first:0' => [ '#markup' => 'little things', '#weight' => -1000 ],
];

does not work when run via Element::children($test, TRUE);

It returns:

Array
(
    [0] => first:0
    [1] => bar:2
    [2] => foo:1
)

which is wrong.

This affects Drupal 7 as well as 8 and is the reason why explicit weights are needed so often in 7 even though it _should_ work without.

Proposed resolution

- Fix the bug, consider using array_multisort or add implicit weights like in FAPI and multiply the rest by a factor.

Remaining tasks

- Discuss
- Fix

User interface changes

API changes

CommentFileSizeAuthor
#76 uasort_does_not-2448765-76.patch7.42 KBBerdir
#66 uasort_does_not-2448765-66.patch7.41 KBnlisgo
#66 interdiff-2448765-63-66.txt2.85 KBnlisgo
#63 interdiff.txt1.1 KBDamien Tournoud
#63 2448765-somefloat.patch6.45 KBDamien Tournoud
#60 interdiff.txt4.73 KBrteijeiro
#60 2448765-60.patch15.87 KBrteijeiro
#58 interdiff.txt7.57 KBvlad.n
#58 2448765-58.patch15.98 KBvlad.n
#56 interdiff.txt1.99 KBvlad.n
#55 2448765-55.patch7.7 KBvlad.n
#54 2448765-new-test-case-54.patch1.33 KBvlad.n
#47 interdiff.txt753 bytesDamien Tournoud
#47 2448765-47.patch6.47 KBDamien Tournoud
#43 2448765-42.patch6.31 KBDamien Tournoud
#40 uasort_does_not-2448765-40.patch6.69 KBnlisgo
#40 interdiff-2448765-38-40.txt1.48 KBnlisgo
#38 uasort_does_not-2448765-38.patch5.09 KBnlisgo
#38 interdiff-2448765-32-38.txt794 bytesnlisgo
#32 uasort_does_not-2448765-32.patch4.17 KBnlisgo
#32 interdiff-2448765-25-32.txt1.77 KBnlisgo
#30 uasort_does_not-2448765-30.patch179.32 KBnlisgo
#30 interdiff-2448765-25-30.txt155.46 KBnlisgo
#25 uasort_does_not-2448765-25.patch3.46 KBnlisgo
#25 interdiff-2448765-21-25.txt1.15 KBnlisgo
#22 interdiff-2448765-16-21.txt1.05 KBnlisgo
#21 uasort_does_not-2448765-21.patch3.45 KBnlisgo
#21 interdiff-2448765-16-21.txt17.31 KBnlisgo
#16 uasort_does_not-2448765-16.patch2.88 KBnlisgo
#16 interdiff-2448765-14-16.txt60.51 KBnlisgo
#14 uasort_does_not-2448765-14.patch1.67 KBnlisgo
#14 interdiff-2448765-10-14.txt0 bytesnlisgo
#10 uasort_does_not-2448765-10.patch0 bytesnlisgo
#6 uasort_does_not-2448765-6-tests.patch820 bytesnlisgo
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Fabianx’s picture

Issue summary: View changes
Fabianx’s picture

Issue tags: +Needs tests, +Novice

Marking with needs tests and Novice to extend unit tests (see IS) for Element::children.

Unfortunately we use uasort() all over core ... (71 files affected), though hopefully most have explicit sort keys set.

nlisgo’s picture

Assigned: Unassigned » nlisgo

Going to take a look at this one.

nlisgo’s picture

@Fabianx what is the expected output for:

<?php

use Drupal\Core\Render\Element;

$element = [
  'foo:1' => [ '#markup' => 'foo - first' ],
  'bar:2' => [ '#markup' => 'bar - second' ],
  'first:0' => [ '#markup' => 'little things', '#weight' => -1000 ],
];

$children = Element::children($element, TRUE);
?>

Should it return:

Array
(
    [0] => first:0
    [1] => foo:1
    [2] => bar:2
)
nlisgo’s picture

There are tests around Element::children at Drupal\Tests\Core\Render\ElementTest

nlisgo’s picture

Status: Active » Needs review
FileSize
820 bytes

This test only patch should demonstrate that there is a bug

Status: Needs review » Needs work

The last submitted patch, 6: uasort_does_not-2448765-6-tests.patch, failed testing.

nlisgo’s picture

Now we have some adequate test coverage I will try to fix this tomorrow.

Fabianx’s picture

Thanks for the test! Looks great :).

nlisgo’s picture

Status: Needs work » Needs review
FileSize
0 bytes

I did some debugging and realised that the way that uasort is processing the value comparisons that it will always order things in reverse if they have the same weight. The reason why the following works is because although the sort flag is set when Element::children is called because no child has a weight value it does not get passed to the uasort function because the $sortable variable within the Element::children method only gets set to TRUE if one of the children has a value set for #weight:

<?php
$test = [
  'foo:1' => [ '#markup' => 'foo - first' ],
  'bar:2' => [ '#markup' => 'bar - second' ],
];
$children = Element::children($test, TRUE);
?>

By using array_reverse before uasort is called the expected order is preserved. I have check this works for the latest stable releases of PHP 5.3, 5.4, 5.5 and 5.6.

See https://github.com/nlisgo/uasort_does_not-2448765/pull/1 where I have isolated the example to easily test the solution against different versions of PHP.

Here is the corresponding travis build https://travis-ci.org/nlisgo/uasort_does_not-2448765/builds/54072958.

Fabianx’s picture

#10 That would be nice, but are you sure that that not only makes the problem different.

I would imagine with a reversed array the following to fail instead:

use Drupal\Core\Render\Element;
$element = [
  'last:3' => [ '#markup' => 'little things', '#weight' => 1000 ],
  'foo:1' => [ '#markup' => 'foo - first' ],
  'bar:2' => [ '#markup' => 'bar - second' ],
];
$children = Element::children($element, TRUE);

at least as far as I have understood the sorting algorithm.

Also the sort order is undefined for elements that are the same it says, so while this works for this scenario I can't imagine it working for every scenario.

The solution IMHO is to do like FAPI and set an explicit micro weight or add an index property on a copy of the array and multi-sort by both like Symfony does.

$i = 0;
foreach ($values as $value) {
  $value['#weight'] += $i*0.0001;
}

Or

$i = 0;
foreach ($values as $value) {
  $value['#ua_sort_index'] = $i;
}

then never return 0 in the comparison functions ...

nlisgo’s picture

I'm running a bunch of tests on my github example that I haven't brought over yet. They are all passing with this fix. I am not saying that you're not right.

We should try and come up with a test case that the patch in #10 doesn't work for and then I would happily ditch it.

nlisgo’s picture

I will add the test case in #11.

nlisgo’s picture

@Fabianx you were right. This patch adds a test case like the one in #11 and the fix put forward fails.

Apologies, I didn't export the interdiff properly.

Status: Needs review » Needs work

The last submitted patch, 14: uasort_does_not-2448765-14.patch, failed testing.

nlisgo’s picture

Status: Needs work » Needs review
FileSize
60.51 KB
2.88 KB

I propose that we add a method to the SortArray utility class that can be used in place of all calls to the uasort function.

The benefit of this is that we can solve the problem for all calls of the SortArray::uasort in one place.

This is what it would look like:

<?php

namespace Drupal\Component\Utility;

class SortArray {

  // ...

  public static function uasort(array &$a, callable $value_compare_func) {
    $a = array_reverse($a);
    return uasort($a, $value_compare_func);
  }

  // ...

}
?>

And to call it:

<?php

namespace Drupal\Core\Render;

use Drupal\Component\Utility\SortArray;

class Element {

  // ...

  public static function children(array &$elements, $sort = FALSE) {
    
    // ...
    if ($sort && $sortable) {
      SortArray::uasort($children, 'Drupal\Component\Utility\SortArray::sortByWeightProperty');

      // ...

    }

    // ...

  }

  // ...

}

?>

Status: Needs review » Needs work

The last submitted patch, 16: uasort_does_not-2448765-16.patch, failed testing.

nlisgo’s picture

As you can see the patch in #16 causes no more failures than the patch in #14.

I will proceed with this approach (using SortArray::uasort) and await feedback. I want to be moving in a direction that we can roll a solution out for all calls to the uasort function.

Fabianx’s picture

I am very happy with SortArray::uasort()

That will make the task of replacing all uasort much simpler!

Let's do it!

nlisgo’s picture

Thanks for the pointers @Fabianx. I'm planning out an approach and hope to submit a patch tomorrow.

nlisgo’s picture

Status: Needs work » Needs review
FileSize
17.31 KB
3.45 KB

Please give your feedback on this solution.

nlisgo’s picture

FileSize
1.05 KB

Here is the interdiff. Done properly :)

Status: Needs review » Needs work

The last submitted patch, 21: uasort_does_not-2448765-21.patch, failed testing.

Fabianx’s picture

  1. +++ b/core/lib/Drupal/Component/Utility/SortArray.php
    @@ -15,6 +15,38 @@
    +    foreach ($a as $k => $v) {
    +      $a[$k]['#ua_sort_index'] = $i*0.0001;
    +      $i++;
    

    You can just put it to = $i;

    No need to multiply.

  2. +++ b/core/lib/Drupal/Component/Utility/SortArray.php
    @@ -15,6 +15,38 @@
    +    foreach ($a as $k => $v) {
    +      unset($a[$k]['#ua_sort_index']);
    +    }
    

    Not sure we need to check if the input is actual arrays or such ...

  3. +++ b/core/lib/Drupal/Component/Utility/SortArray.php
    @@ -128,7 +160,12 @@ public static function sortByKeyInt($a, $b, $key) {
    +      if ($key != '#ua_sort_index') {
    +        return static::sortByKeyInt($a, $b, '#ua_sort_index');
    +      }
    +      else {
    +        return 0;
    +      }
    

    As that is called a lot, you can just do it inline maybe?

And there are failing tests, but the overall approach I like :).

nlisgo’s picture

Status: Needs work » Needs review
FileSize
1.15 KB
3.46 KB

I am addressing the feedback in #24.

Still investigating why the tests are failing.

It should be noted that all tests in Drupal\Tests\Core\Render\ElementTest are passing.

Status: Needs review » Needs work

The last submitted patch, 25: uasort_does_not-2448765-25.patch, failed testing.

nlisgo’s picture

Is it possible that the failures are due to the fact that tests have been written around behaviour that is unexpected. I know this is true for at least one of the cases:

top of menu_test.links.task.yml

menu_test.local_task_test_tasks_view:
  route_name: menu_test.local_task_test_tasks_view
  title: View
  base_route: menu_test.local_task_test_tasks_view
menu_test.local_task_test_tasks_edit:
  route_name: menu_test.local_task_test_tasks_edit
  title: Edit
  base_route: menu_test.local_task_test_tasks_view
menu_test.local_task_test_tasks_settings:
  route_name: menu_test.local_task_test_tasks_settings
  title: Settings
  base_route: menu_test.local_task_test_tasks_view

Yet the current test is checking the order as follows in Drupal\system\Tests\Menu\LocalTasksTest::testPluginLocalTask

<?php
    // Verify that local tasks appear as defined in the router.
    $this->drupalGet(Url::fromRoute('menu_test.local_task_test_tasks_view'));
    $this->assertLocalTasks([
      ['menu_test.local_task_test_tasks_view', []],
      ['menu_test.local_task_test_tasks_settings', []],
      ['menu_test.local_task_test_tasks_edit', []],
    ]);
?>

If the test describes the expected behaviour then we need alter menu_test.links.task.yml

dawehner’s picture

I think you are totally right, the test assumed the odd/bad behaviour of uasort. Feel free to change Drupal\system\Tests\Menu\LocalTasksTest::testPluginLocalTask, is its clearly not what actually is intended.

Fabianx’s picture

+++ b/core/lib/Drupal/Component/Utility/SortArray.php
@@ -15,6 +15,42 @@
+  public static function uasort(array &$a, callable $value_compare_func) {
+    $i = 0;

Maybe we should call this

uasortOnArrays or uasortOnKeyIndex, because if you pass it two arrays full of objects, it fails to protect ...

nlisgo’s picture

Status: Needs work » Needs review
FileSize
155.46 KB
179.32 KB

Addressing feedback in #28 and #29.

Status: Needs review » Needs work

The last submitted patch, 30: uasort_does_not-2448765-30.patch, failed testing.

nlisgo’s picture

Status: Needs work » Needs review
FileSize
1.77 KB
4.17 KB

Reroll after rebase.

Status: Needs review » Needs work

The last submitted patch, 32: uasort_does_not-2448765-32.patch, failed testing.

nlisgo’s picture

Assigned: nlisgo » Unassigned

There are 2 test cases that are failing. When I run the tests locally and introduce debugging code around uasortOnArrays and compare the input array with the weights to the altered array after it is passed to the compare function we see that the altered array is in the order that we would expect which is why our next tests for ElementTest are passing.

The effect of the change to the Element class using SortArray::uasortOnArrays rather than uasort is a slight difference in the order of values in the array supplied to the sort function for values in the array that have the same #weight property.

In the case of the Drupal\comment\Tests\CommentPagerTest::testTwoPagers test the result is that the 2 pagers being tested are output in a different order. It is hard for me to know whether it is acceptable to just change the tests for Drupal\comment\Tests\CommentPagerTest::testTwoPagers to reflect the new order or whether it represents a bug that needs to be fixed. The nature of that test is to check that 2 pagers can work on the same page and that can be determined whichever order the pagers are output.

In the case of Drupal\search\Tests\SearchConfigSettingsFormTest::testDefaultSearchPageOrdering the test checks the url's of the first 2 primary tabs. The effect of introducing SortArray::uasortOnArrays is that the order of the primary tabs has gone from:

  1. /search/node
  2. /search/user
  3. /search/dummy_path

to:

  1. /search/node
  2. /search/dummy_path
  3. /search/user

I'm not sure that when this test was written whether the /search/dummy_path primary tab was available. If it had been then can we be sure that this test was not written to reflect the behaviour that was observed instead of the expected behaviour. We will need to investigate the implementation of the search feature to determine whether the primary tabs should really be expected to appear /search/node and then /search/user.

When we roll out the use of SortArray::uasortOnArrays no doubt we will find some other similar cases of tests failing where the tests may have been written to cover the observed behaviour instead of the expected behaviour.

I'm unassigning myself from the task for now to invite someone else to take this on who may see a clearer way forward but I am happy to continue looking into this just don't have much availability at the moment.

nlisgo’s picture

I can confirm that the search page primary tabs are being output in the expected order. The existing test Drupal\search\Tests\SearchConfigSettingsFormTest::testDefaultSearchPageOrdering just covers the observed behaviour. The dummy_search_type and user_search have the same weight but dummy_search_type appears before user_search in the source array.

The output below is a var_dump of the SearchLocalTask->getDerivativeDefinitions on the 8.0.x branch.

array (size=3)
  'node_search' => 
    array (size=4)
      'title' => string 'Content' (length=7)
      'route_name' => string 'search.view_node_search' (length=23)
      'base_route' => string 'search.plugins:node_search' (length=26)
      'weight' => int -10
  'dummy_search_type' => 
    array (size=4)
      'title' => string 'Dummy search type' (length=17)
      'route_name' => string 'search.view_dummy_search_type' (length=29)
      'base_route' => string 'search.plugins:node_search' (length=26)
      'weight' => int 0
  'user_search' => 
    array (size=4)
      'title' => string 'Users' (length=5)
      'route_name' => string 'search.view_user_search' (length=23)
      'base_route' => string 'search.plugins:node_search' (length=26)
      'weight' => int 0
Fabianx’s picture

Then it is fine to change the test :).

Source Order == Destination Order (after applying weights) is the way to go.

nlisgo’s picture

OK, well I will change that test and move to investigating why the pagers are appearing in a different order than has been observed without our changes here.

nlisgo’s picture

Status: Needs work » Needs review
FileSize
794 bytes
5.09 KB

Addressing failing test with Drupal\search\Tests\SearchConfigSettingsFormTest::testDefaultSearchPageOrdering as the test in place was just covering observed behaviour instead of expected. uasort was altering the order of the array in an unexpected way.

See #35 and #36.

Status: Needs review » Needs work

The last submitted patch, 38: uasort_does_not-2448765-38.patch, failed testing.

nlisgo’s picture

Status: Needs work » Needs review
FileSize
1.48 KB
6.69 KB

There seems to be a bug with the current display of the comment field. Even on the 8.0.x branch if I add a new comment field to the Article content type (field_comment_2) and then go to manage display for the content type. If I give the comment field a weight of 20 and the field_comment_2 field a weight of 30 the comment field still appears last of all the fields on the node page.

I will do some search on the issue queue to see if any one has raised an issue for this, if not I will create one.

In an effort to move forward with this issue I have amended the test for Drupal\comment\Tests\CommentPagerTest::testTwoPagers to target the pager for each comment field by specifying a class selector. That way it doesn't matter what order the fields are output. Since the test is to check that 2 pagers can work on the same page rather than check that the order of the fields is as expected I thought this offered a way forward.

Status: Needs review » Needs work

The last submitted patch, 40: uasort_does_not-2448765-40.patch, failed testing.

nlisgo’s picture

Damien Tournoud’s picture

FileSize
6.31 KB

While we are at it, we should pick an implementation that doesn't require a mind-boggling number of function calls to do the sorting:

  • Instead of calling uasort() which requires something like O(n*log(n)) calls to the comparison function, we prepare a weight array and sort that directly with asort(). We have to scan the array anyway in the current implementation.
  • If the weight is not defined, we initialize to ($i / $count), a weight that is between 0 and 1, in order of insertion. (This is the same trick the Form API is using, we can probably remove that other code.)

No interdiff, the test modifications are the same as #40, everything else is new.

Damien Tournoud’s picture

Status: Needs work » Needs review
Damien Tournoud’s picture

Additionally, we should wonder if we shouldn't guarantee order of insertion at the same weight, even if the weight is defined.

Status: Needs review » Needs work

The last submitted patch, 43: 2448765-42.patch, failed testing.

Damien Tournoud’s picture

FileSize
6.47 KB
753 bytes

The tests actually assume that we keep insertion order at equal weight, whatever the weight.

Damien Tournoud’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 47: 2448765-47.patch, failed testing.

nlisgo’s picture

Damian thanks for your input on this issue.

Whatever approach we take, and you make a really good case for moving away from uasort, it would be great to abstract a sort function for ordering of Element::children as there are many other instances throughout the codebase of using uasort that could share the same solution.

Fabianx’s picture

#45: We definitely should, likely that just means adding $i / $count to the other weights as well, right? *edit: as done by #47 already).

Also we should probably split off element_children as a sub-task of this, as I 100% agree that the asort() fix is way way nicer, but uasort is used all over the place in core possibly wrongly.

Damien Tournoud’s picture

The checkboxes / radios tests fail because they assume that non-integer weights are supported. They are not, and they haven't ever been, at least in the Form API, given this code in FormBuilder::doBuildForm():

      if (!isset($element[$key]['#weight'])) {
        $element[$key]['#weight'] = $count/1000;
      }

The checkboxes / radios ordering only works right now because *all* the weights of the children are set.

Any opinion on the following?

(1) Is everyone OK to explicitly stop support float weights?

(2) Should we trigger a warning on float weights in Element::children(), like we currently do for non-array elements?

(3) About checkboxes / radios: if you add a child element that is not in the #options array, where should it go? Above all the others? Below all the others?

nlisgo’s picture

My position on questions in #52.

On point 1, I have no objection. If we stop supporting floats it makes sense to do point 2. Point 3, I don't know enough about it, do we have and instances of that in core currently. Do we need to have an answer for point 3 to progress?

vlad.n’s picture

Added test method for invalid render element weights (not integer values).

vlad.n’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
7.7 KB

Added integer value constraint for render element weight. If a weight is not integer value an exception with '"@key" has an invalid weight' message will be raised. I have used the patch from #47.

vlad.n’s picture

FileSize
1.99 KB

Attached interdiff.

Status: Needs review » Needs work

The last submitted patch, 55: 2448765-55.patch, failed testing.

vlad.n’s picture

FileSize
15.98 KB
7.57 KB

Did some refactorization on some files that used float weights.

vlad.n’s picture

Status: Needs work » Needs review
rteijeiro’s picture

FileSize
15.87 KB
4.73 KB

Re-rolled and fixed a few nitpicks and coding standards.

The last submitted patch, 58: 2448765-58.patch, failed testing.

The last submitted patch, 54: 2448765-new-test-case-54.patch, failed testing.

Damien Tournoud’s picture

FileSize
6.45 KB
1.1 KB

Unfortunately, most of those fixes are wrong, and show that test coverage is extremely spotty around weights outside the render system.

Alternatively, instead of removing support for float weights completely, we could remove support for float weights below a certain precision, for example 0.001. That would keep existing code like:

$element[$key]['#weight'] = $count/1000;

or

$weight += 0.001;

work untouched, but we still keep the performance gains of only sorting float values.

This is an experiment with #47 + supporting up to 0.001 weights.

The last submitted patch, 60: 2448765-60.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 63: 2448765-somefloat.patch, failed testing.

nlisgo’s picture

The test that I had written to improve the targeting of the appropriate next link for the pager was not working as the class used to target it was not connected with the specific field but connected with its' position.

nlisgo’s picture

Status: Needs work » Needs review
stefan.r’s picture

Title: uasort does NOT preserve sort order, but core assumes so (Element::children, css sort, ...) » uasort does NOT preserve sort order, but core assumes so (Element::children, css sort, ...) - This makes tests fail in PHP7
Issue tags: +php7
Parent issue: » #2454439: [META] Support PHP 7

Related PHP7 test fails:

5) Drupal\Tests\Core\Config\Entity\ConfigEntityBaseUnitTest::testSort
Failed asserting that two variables reference the same object.

core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php:447
                                           
FAILURES!                                  
Tests: 3079, Assertions: 33482, Failures: 5.
1) Drupal\Tests\block\Unit\BlockRepositoryTest::testGetVisibleBlocksPerRegion with data set #0 (array(array(true, 'top', 0), array(false, 'bottom', 0), array(true, 'bottom', 5), array(true, 'bottom', -5)), array(array('block1'), array(), array('block4', 'block3')))
Failed asserting that Array &0 (
    'top' => Array &1 (
        0 => 'block1'
    )
    'center' => Array &2 ()
    'bottom' => Array &3 (
        0 => 'block4'
        1 => 'block3'
    )
) is identical to Array &0 (
    'top' => Array &1 (
        0 => 'block1'
    )
    'center' => Array &2 ()
    'bottom' => Array &3 (
        0 => 'block3'
        1 => 'block4'
    )
).

core/modules/block/tests/src/Unit/BlockRepositoryTest.php:112

2) Drupal\Tests\user\Unit\PermissionHandlerTest::testBuildPermissionsSortPerModule
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
Array (
-    0 => 'access_module_a1'
-    1 => 'access_module_a2'
+    0 => 'access_module_a2'
+    1 => 'access_module_a1'
)

core/modules/user/tests/src/Unit/PermissionHandlerTest.php:199
Fabianx’s picture

Should we make this a meta issue and split off the new Element::children() solution (I very much like it!) to a sub-issue of this one?

dawehner’s picture

+++ b/core/lib/Drupal/Core/Render/Element.php
@@ -93,21 +101,24 @@ public static function children(array &$elements, $sort = FALSE) {
-      uasort($children, 'Drupal\Component\Utility\SortArray::sortByWeightProperty');
+      asort($child_weights);

Its certainly no slow down +1

stefan.r’s picture

This patch also fixes 4 PHP7 test fails as mentioned by Berdir in the parent :)
#2454439: [META] Support PHP 7

Fabianx’s picture

Title: uasort does NOT preserve sort order, but core assumes so (Element::children, css sort, ...) - This makes tests fail in PHP7 » Element::children sort order undefined and slower than it could be - This makes tests fail in PHP7
Priority: Major » Critical
Issue tags: +Performance
Related issues: +#2466097: uasort() does NOT preserve sort order, but core assumes so (Element::children, css sort, ...)

- Critical as this solves a lot of PHP7 things directly
- Created meta #2466097: uasort() does NOT preserve sort order, but core assumes so (Element::children, css sort, ...) for the remainder of the UASort scope problems (and nlisgo's nice uasort generic patches)

Will review the code again, but last I looked it was RTBC.

Fabianx’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs Drupal 8 critical triage

RTBC, test changes and code changes look good.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 66: uasort_does_not-2448765-66.patch, failed testing.

Fabianx’s picture

Issue tags: +Needs reroll
Berdir’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs reroll
FileSize
7.42 KB

Patch still applied with git apply -3. Conflicted on String/SafeMarkup context changes.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 76: uasort_does_not-2448765-76.patch, failed testing.

webchick’s picture

That Drupal\migrate_drupal\Tests\d6\MigrateFileTest test is known to have random fails. Re-testing.

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 76: uasort_does_not-2448765-76.patch, failed testing.

Status: Needs work » Needs review
Berdir’s picture

Status: Needs review » Reviewed & tested by the community

Failed twice on that, strange. Green again, so RTBC again I guess.

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Hopefully that's not a sign of things to come. ;)

Committed and pushed to 8.0.x. Thanks!

  • webchick committed 9fd632c on 8.0.x
    Issue #2448765 by nlisgo, Damien Tournoud, vlad.n, rteijeiro, Berdir,...
xjm’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

donquixote’s picture

We don't need to play with floats for stable sort.
#2522712: Simplify Element::children() stable sort.

Fabianx’s picture

Version: 8.0.x-dev » 7.x-dev
Status: Closed (fixed) » Active
Issue tags: +Needs backport to D7
Parent issue: #2454439: [META] Support PHP 7 » #2656548: Fully support PHP 7.0 in Drupal 7
Related issues: +#2454439: [META] Support PHP 7

I am almost 100% sure this needs to be backported to D7 as well - even if tests don't fail.

And I am stealing this issue from its parent.

catch’s picture

Version: 7.x-dev » 8.1.x-dev
Status: Active » Fixed
Parent issue: #2656548: Fully support PHP 7.0 in Drupal 7 » #2454439: [META] Support PHP 7

I've opened a separate 7.x backport issue for this at #2756297: element_children sort order inconsistent between PHP 5 and PHP 7 [Drupal 7 backport] per (updated in May) backport policy: https://www.drupal.org/core/backport-policy

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.