mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #4549 from kinglozzer/pulls/recursion-arraylist-sort
FIX: Recursion errors when sorting objects with circular dependencies (fixes #4464)
This commit is contained in:
commit
17e97babf1
@ -422,6 +422,11 @@ class ArrayList extends ViewableData implements SS_List, SS_Filterable, SS_Sorta
|
||||
throw new InvalidArgumentException("Bad arguments passed to sort()");
|
||||
}
|
||||
|
||||
// Store the original keys of the items as a sort fallback, so we can preserve the original order in the event
|
||||
// that array_multisort is unable to work out a sort order for them. This also prevents array_multisort trying
|
||||
// to inspect object properties which can result in errors with circular dependencies
|
||||
$originalKeys = array_keys($this->items);
|
||||
|
||||
// This the main sorting algorithm that supports infinite sorting params
|
||||
$multisortArgs = array();
|
||||
$values = array();
|
||||
@ -442,6 +447,8 @@ class ArrayList extends ViewableData implements SS_List, SS_Filterable, SS_Sorta
|
||||
$multisortArgs[] = &$sortDirection[$column];
|
||||
}
|
||||
|
||||
$multisortArgs[] = &$originalKeys;
|
||||
|
||||
$list = clone $this;
|
||||
// As the last argument we pass in a reference to the items that all the sorting will be applied upon
|
||||
$multisortArgs[] = &$list->items;
|
||||
|
@ -425,6 +425,30 @@ class ArrayListTest extends SapphireTest {
|
||||
$this->assertEquals($list->last()->ID, 3, 'Bert.3 should be last in the list');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that we don't cause recursion errors with array_multisort() and circular dependencies
|
||||
*/
|
||||
public function testSortWithCircularDependencies() {
|
||||
$itemA = new stdClass;
|
||||
$childA = new stdClass;
|
||||
$itemA->child = $childA;
|
||||
$childA->parent = $itemA;
|
||||
$itemA->Sort = 1;
|
||||
|
||||
$itemB = new stdClass;
|
||||
$childB = new stdClass;
|
||||
$itemB->child = $childB;
|
||||
$childB->parent = $itemB;
|
||||
$itemB->Sort = 1;
|
||||
|
||||
$items = new ArrayList;
|
||||
$items->add($itemA);
|
||||
$items->add($itemB);
|
||||
|
||||
// This call will trigger a fatal error if there are issues with circular dependencies
|
||||
$items->sort('Sort');
|
||||
}
|
||||
|
||||
/**
|
||||
* $list->filter('Name', 'bob'); // only bob in the list
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user