/laravel_tintuc/vendor/laravel/framework/src/Illuminate/Routing/CompiledRouteCollection.php

https://gitlab.com/nmhieucoder/laravel_tintuc · PHP · 333 lines · 165 code · 40 blank · 128 comment · 11 complexity · ec8b8da53b4795840b81b32f530960f5 MD5 · raw file

  1. <?php
  2. namespace Illuminate\Routing;
  3. use Illuminate\Container\Container;
  4. use Illuminate\Http\Request;
  5. use Illuminate\Support\Collection;
  6. use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
  7. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  8. use Symfony\Component\Routing\Exception\MethodNotAllowedException;
  9. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  10. use Symfony\Component\Routing\Matcher\CompiledUrlMatcher;
  11. use Symfony\Component\Routing\RequestContext;
  12. class CompiledRouteCollection extends AbstractRouteCollection
  13. {
  14. /**
  15. * The compiled routes collection.
  16. *
  17. * @var array
  18. */
  19. protected $compiled = [];
  20. /**
  21. * An array of the route attributes keyed by name.
  22. *
  23. * @var array
  24. */
  25. protected $attributes = [];
  26. /**
  27. * The dynamically added routes that were added after loading the cached, compiled routes.
  28. *
  29. * @var \Illuminate\Routing\RouteCollection|null
  30. */
  31. protected $routes;
  32. /**
  33. * The router instance used by the route.
  34. *
  35. * @var \Illuminate\Routing\Router
  36. */
  37. protected $router;
  38. /**
  39. * The container instance used by the route.
  40. *
  41. * @var \Illuminate\Container\Container
  42. */
  43. protected $container;
  44. /**
  45. * Create a new CompiledRouteCollection instance.
  46. *
  47. * @param array $compiled
  48. * @param array $attributes
  49. * @return void
  50. */
  51. public function __construct(array $compiled, array $attributes)
  52. {
  53. $this->compiled = $compiled;
  54. $this->attributes = $attributes;
  55. $this->routes = new RouteCollection;
  56. }
  57. /**
  58. * Add a Route instance to the collection.
  59. *
  60. * @param \Illuminate\Routing\Route $route
  61. * @return \Illuminate\Routing\Route
  62. */
  63. public function add(Route $route)
  64. {
  65. return $this->routes->add($route);
  66. }
  67. /**
  68. * Refresh the name look-up table.
  69. *
  70. * This is done in case any names are fluently defined or if routes are overwritten.
  71. *
  72. * @return void
  73. */
  74. public function refreshNameLookups()
  75. {
  76. //
  77. }
  78. /**
  79. * Refresh the action look-up table.
  80. *
  81. * This is done in case any actions are overwritten with new controllers.
  82. *
  83. * @return void
  84. */
  85. public function refreshActionLookups()
  86. {
  87. //
  88. }
  89. /**
  90. * Find the first route matching a given request.
  91. *
  92. * @param \Illuminate\Http\Request $request
  93. * @return \Illuminate\Routing\Route
  94. *
  95. * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
  96. * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
  97. */
  98. public function match(Request $request)
  99. {
  100. $matcher = new CompiledUrlMatcher(
  101. $this->compiled, (new RequestContext)->fromRequest(
  102. $trimmedRequest = $this->requestWithoutTrailingSlash($request)
  103. )
  104. );
  105. $route = null;
  106. try {
  107. if ($result = $matcher->matchRequest($trimmedRequest)) {
  108. $route = $this->getByName($result['_route']);
  109. }
  110. } catch (ResourceNotFoundException | MethodNotAllowedException $e) {
  111. try {
  112. return $this->routes->match($request);
  113. } catch (NotFoundHttpException $e) {
  114. //
  115. }
  116. }
  117. if ($route && $route->isFallback) {
  118. try {
  119. $dynamicRoute = $this->routes->match($request);
  120. if (! $dynamicRoute->isFallback) {
  121. $route = $dynamicRoute;
  122. }
  123. } catch (NotFoundHttpException | MethodNotAllowedHttpException $e) {
  124. //
  125. }
  126. }
  127. return $this->handleMatchedRoute($request, $route);
  128. }
  129. /**
  130. * Get a cloned instance of the given request without any trailing slash on the URI.
  131. *
  132. * @param \Illuminate\Http\Request $request
  133. * @return \Illuminate\Http\Request
  134. */
  135. protected function requestWithoutTrailingSlash(Request $request)
  136. {
  137. $trimmedRequest = Request::createFromBase($request);
  138. $parts = explode('?', $request->server->get('REQUEST_URI'), 2);
  139. $trimmedRequest->server->set(
  140. 'REQUEST_URI', rtrim($parts[0], '/').(isset($parts[1]) ? '?'.$parts[1] : '')
  141. );
  142. return $trimmedRequest;
  143. }
  144. /**
  145. * Get routes from the collection by method.
  146. *
  147. * @param string|null $method
  148. * @return \Illuminate\Routing\Route[]
  149. */
  150. public function get($method = null)
  151. {
  152. return $this->getRoutesByMethod()[$method] ?? [];
  153. }
  154. /**
  155. * Determine if the route collection contains a given named route.
  156. *
  157. * @param string $name
  158. * @return bool
  159. */
  160. public function hasNamedRoute($name)
  161. {
  162. return isset($this->attributes[$name]) || $this->routes->hasNamedRoute($name);
  163. }
  164. /**
  165. * Get a route instance by its name.
  166. *
  167. * @param string $name
  168. * @return \Illuminate\Routing\Route|null
  169. */
  170. public function getByName($name)
  171. {
  172. if (isset($this->attributes[$name])) {
  173. return $this->newRoute($this->attributes[$name]);
  174. }
  175. return $this->routes->getByName($name);
  176. }
  177. /**
  178. * Get a route instance by its controller action.
  179. *
  180. * @param string $action
  181. * @return \Illuminate\Routing\Route|null
  182. */
  183. public function getByAction($action)
  184. {
  185. $attributes = collect($this->attributes)->first(function (array $attributes) use ($action) {
  186. if (isset($attributes['action']['controller'])) {
  187. return trim($attributes['action']['controller'], '\\') === $action;
  188. }
  189. return $attributes['action']['uses'] === $action;
  190. });
  191. if ($attributes) {
  192. return $this->newRoute($attributes);
  193. }
  194. return $this->routes->getByAction($action);
  195. }
  196. /**
  197. * Get all of the routes in the collection.
  198. *
  199. * @return \Illuminate\Routing\Route[]
  200. */
  201. public function getRoutes()
  202. {
  203. return collect($this->attributes)
  204. ->map(function (array $attributes) {
  205. return $this->newRoute($attributes);
  206. })
  207. ->merge($this->routes->getRoutes())
  208. ->values()
  209. ->all();
  210. }
  211. /**
  212. * Get all of the routes keyed by their HTTP verb / method.
  213. *
  214. * @return array
  215. */
  216. public function getRoutesByMethod()
  217. {
  218. return collect($this->getRoutes())
  219. ->groupBy(function (Route $route) {
  220. return $route->methods();
  221. })
  222. ->map(function (Collection $routes) {
  223. return $routes->mapWithKeys(function (Route $route) {
  224. if ($domain = $route->getDomain()) {
  225. return [$domain.'/'.$route->uri => $route];
  226. }
  227. return [$route->uri => $route];
  228. })->all();
  229. })
  230. ->all();
  231. }
  232. /**
  233. * Get all of the routes keyed by their name.
  234. *
  235. * @return \Illuminate\Routing\Route[]
  236. */
  237. public function getRoutesByName()
  238. {
  239. return collect($this->getRoutes())
  240. ->keyBy(function (Route $route) {
  241. return $route->getName();
  242. })
  243. ->all();
  244. }
  245. /**
  246. * Resolve an array of attributes to a Route instance.
  247. *
  248. * @param array $attributes
  249. * @return \Illuminate\Routing\Route
  250. */
  251. protected function newRoute(array $attributes)
  252. {
  253. if (empty($attributes['action']['prefix'] ?? '')) {
  254. $baseUri = $attributes['uri'];
  255. } else {
  256. $prefix = trim($attributes['action']['prefix'], '/');
  257. $baseUri = trim(implode(
  258. '/', array_slice(
  259. explode('/', trim($attributes['uri'], '/')),
  260. count($prefix !== '' ? explode('/', $prefix) : [])
  261. )
  262. ), '/');
  263. }
  264. return $this->router->newRoute($attributes['methods'], $baseUri === '' ? '/' : $baseUri, $attributes['action'])
  265. ->setFallback($attributes['fallback'])
  266. ->setDefaults($attributes['defaults'])
  267. ->setWheres($attributes['wheres'])
  268. ->setBindingFields($attributes['bindingFields'])
  269. ->block($attributes['lockSeconds'] ?? null, $attributes['waitSeconds'] ?? null);
  270. }
  271. /**
  272. * Set the router instance on the route.
  273. *
  274. * @param \Illuminate\Routing\Router $router
  275. * @return $this
  276. */
  277. public function setRouter(Router $router)
  278. {
  279. $this->router = $router;
  280. return $this;
  281. }
  282. /**
  283. * Set the container instance on the route.
  284. *
  285. * @param \Illuminate\Container\Container $container
  286. * @return $this
  287. */
  288. public function setContainer(Container $container)
  289. {
  290. $this->container = $container;
  291. return $this;
  292. }
  293. }