--- a/src/FacetManager/DefaultFacetManager.php +++ b/src/FacetManager/DefaultFacetManager.php @@ -511,29 +511,48 @@ * A sorted array of results. */ protected function sortFacetResults(array $active_sort_processors, array $results) { - uasort($results, function ($a, $b) use ($active_sort_processors) { - $return = 0; - foreach ($active_sort_processors as $sort_processor) { - if ($return = $sort_processor->sortResults($a, $b)) { - if ($sort_processor->getConfiguration()['sort'] == 'DESC') { - $return *= -1; + // Key-preserving insertion sort; avoids passing any callback to PHP + // builtins, which corrupts callable arguments inside a resumed Fiber. + $sorted_keys = array_keys($results); + $n = count($sorted_keys); + for ($i = 1; $i < $n; $i++) { + $key_i = $sorted_keys[$i]; + $j = $i - 1; + while ($j >= 0) { + $key_j = $sorted_keys[$j]; + $cmp = 0; + foreach ($active_sort_processors as $sort_processor) { + if ($cmp = $sort_processor->sortResults($results[$key_i], $results[$key_j])) { + if ($sort_processor->getConfiguration()['sort'] == 'DESC') { + $cmp *= -1; + } + break; } + } + if ($cmp < 0) { + $sorted_keys[$j + 1] = $sorted_keys[$j]; + $j--; + } + else { break; } } - return $return; - }); + $sorted_keys[$j + 1] = $key_i; + } + $sorted = []; + foreach ($sorted_keys as $key) { + $sorted[$key] = $results[$key]; + } // Loop over the results and see if they have any children, if they do, fire // a request to this same method again with the children. - foreach ($results as &$result) { + foreach ($sorted as $key => $result) { if (!empty($result->getChildren())) { - $children = $this->sortFacetResults($active_sort_processors, $result->getChildren()); - $result->setChildren($children); + $sorted[$key]->setChildren($this->sortFacetResults($active_sort_processors, $result->getChildren())); } } - return $results; + return $sorted; } }