1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: namespace Cake\Routing\Middleware;
16:
17: use Cake\Cache\Cache;
18: use Cake\Core\HttpApplicationInterface;
19: use Cake\Core\PluginApplicationInterface;
20: use Cake\Http\MiddlewareQueue;
21: use Cake\Http\Runner;
22: use Cake\Routing\Exception\RedirectException;
23: use Cake\Routing\Router;
24: use Psr\Http\Message\ResponseInterface;
25: use Psr\Http\Message\ServerRequestInterface;
26: use Zend\Diactoros\Response\RedirectResponse;
27:
28: 29: 30: 31:
32: class RoutingMiddleware
33: {
34: 35: 36:
37: const ROUTE_COLLECTION_CACHE_KEY = 'routeCollection';
38:
39: 40: 41: 42: 43:
44: protected $app;
45:
46: 47: 48: 49: 50: 51:
52: protected $cacheConfig;
53:
54: 55: 56: 57: 58: 59:
60: public function __construct(HttpApplicationInterface $app = null, $cacheConfig = null)
61: {
62: if ($app === null) {
63: deprecationWarning(
64: 'RoutingMiddleware should be passed an application instance. ' .
65: 'Failing to do so can cause plugin routes to not behave correctly.'
66: );
67: }
68: $this->app = $app;
69: $this->cacheConfig = $cacheConfig;
70: }
71:
72: 73: 74: 75: 76: 77: 78: 79: 80:
81: protected function loadRoutes()
82: {
83: if (!$this->app) {
84: return;
85: }
86:
87: $routeCollection = $this->buildRouteCollection();
88: Router::setRouteCollection($routeCollection);
89: }
90:
91: 92: 93: 94: 95:
96: protected function buildRouteCollection()
97: {
98: if (Cache::enabled() && $this->cacheConfig !== null) {
99: return Cache::remember(static::ROUTE_COLLECTION_CACHE_KEY, function () {
100: return $this->prepareRouteCollection();
101: }, $this->cacheConfig);
102: }
103:
104: return $this->prepareRouteCollection();
105: }
106:
107: 108: 109: 110: 111:
112: protected function prepareRouteCollection()
113: {
114: $builder = Router::createRouteBuilder('/');
115: $this->app->routes($builder);
116: if ($this->app instanceof PluginApplicationInterface) {
117: $this->app->pluginRoutes($builder);
118: }
119:
120: return Router::getRouteCollection();
121: }
122:
123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133:
134: public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
135: {
136: $this->loadRoutes();
137: try {
138: Router::setRequestContext($request);
139: $params = (array)$request->getAttribute('params', []);
140: $middleware = [];
141: if (empty($params['controller'])) {
142: $parsedBody = $request->getParsedBody();
143: if (is_array($parsedBody) && isset($parsedBody['_method'])) {
144: $request = $request->withMethod($parsedBody['_method']);
145: }
146: $params = Router::parseRequest($request) + $params;
147: if (isset($params['_middleware'])) {
148: $middleware = $params['_middleware'];
149: unset($params['_middleware']);
150: }
151: $request = $request->withAttribute('params', $params);
152: }
153: } catch (RedirectException $e) {
154: return new RedirectResponse(
155: $e->getMessage(),
156: $e->getCode(),
157: $response->getHeaders()
158: );
159: }
160: $matching = Router::getRouteCollection()->getMiddleware($middleware);
161: if (!$matching) {
162: return $next($request, $response);
163: }
164: $matching[] = $next;
165: $middleware = new MiddlewareQueue($matching);
166: $runner = new Runner();
167:
168: return $runner->run($middleware, $request, $response);
169: }
170: }
171: