diff --git a/src/Illuminate/Routing/Router.php b/src/Illuminate/Routing/Router.php index 691828b3aaf6..5ce26a46f3cb 100644 --- a/src/Illuminate/Routing/Router.php +++ b/src/Illuminate/Routing/Router.php @@ -741,32 +741,7 @@ protected function parseMiddlewareGroup($name) */ protected function sortMiddleware(Collection $middlewares) { - $priority = $this->middlewarePriority; - - $sorted = []; - - foreach ($middlewares as $middleware) { - if (in_array($middleware, $sorted)) { - continue; - } - - if (($index = array_search($middleware, $priority)) !== false) { - $sorted = array_merge( - $sorted, - array_filter( - array_slice($priority, 0, $index), - function ($middleware) use ($middlewares, $sorted) { - return $middlewares->contains($middleware) && - ! in_array($middleware, $sorted); - } - ) - ); - } - - $sorted[] = $middleware; - } - - return $sorted; + return (new SortedMiddleware($this->middlewarePriority, $middlewares))->all(); } /** diff --git a/src/Illuminate/Routing/SortedMiddleware.php b/src/Illuminate/Routing/SortedMiddleware.php new file mode 100644 index 000000000000..76608b1997df --- /dev/null +++ b/src/Illuminate/Routing/SortedMiddleware.php @@ -0,0 +1,76 @@ +all(); + } + + $this->items = $this->sortMiddleware($priorityMap, $middlewares); + } + + /** + * Sort the middlewares by the given priority map. + * + * @param array $priorityMap + * @param array $middlewares + * @return array + */ + protected function sortMiddleware($priorityMap, $middlewares) + { + $lastIndex = 0; + + foreach ($middlewares as $index => $middleware) { + if (! is_string($middleware)) { + continue; + } + + $stripped = head(explode(':', $middleware)); + + if (in_array($stripped, $priorityMap)) { + $priorityIndex = array_search($stripped, $priorityMap); + + if (isset($lastPriorityIndex) && $priorityIndex < $lastPriorityIndex) { + return $this->sortMiddleware( + $priorityMap, array_values($this->spliceMiddleware($middlewares, $index, $lastIndex)) + ); + } else { + $lastIndex = $index; + $lastPriorityIndex = $priorityIndex; + } + } + } + + return $middlewares; + } + + /** + * Splice a middleware into a new position and remove the old entry. + * + * @param array $middlewares + * @param int $from + * @param int $to + * @return array + */ + protected function spliceMiddleware($middlewares, $from, $to) + { + array_splice($middlewares, $to, 0, $middlewares[$from]); + + unset($middlewares[$from + 1]); + + return $middlewares; + } +} diff --git a/tests/Routing/RoutingSortedMiddlewareTest.php b/tests/Routing/RoutingSortedMiddlewareTest.php new file mode 100644 index 000000000000..d3e9fa2b1dba --- /dev/null +++ b/tests/Routing/RoutingSortedMiddlewareTest.php @@ -0,0 +1,54 @@ +assertEquals($expected, (new SortedMiddleware($priority, $middleware))->all()); + + $this->assertEquals([], (new SortedMiddleware(['First'], []))->all()); + $this->assertEquals(['First'], (new SortedMiddleware(['First'], ['First']))->all()); + $this->assertEquals(['First', 'Second'], (new SortedMiddleware(['First', 'Second'], ['Second', 'First']))->all()); + + $closure = function () {}; + $this->assertEquals(['Second', $closure], (new SortedMiddleware(['First', 'Second'], ['Second', $closure]))->all()); + } +}