PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/slim/slim/Slim/Route.php

https://gitlab.com/mmk2410/rangitaki
PHP | 381 lines | 158 code | 39 blank | 184 comment | 11 complexity | b4e9c666378860b7c701ade73d2b9d1e MD5 | raw file
  1. <?php
  2. /**
  3. * Slim Framework (https://slimframework.com)
  4. *
  5. * @link https://github.com/slimphp/Slim
  6. * @copyright Copyright (c) 2011-2016 Josh Lockhart
  7. * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
  8. */
  9. namespace Slim;
  10. use Exception;
  11. use Throwable;
  12. use InvalidArgumentException;
  13. use Psr\Http\Message\ServerRequestInterface;
  14. use Psr\Http\Message\ResponseInterface;
  15. use Slim\Exception\SlimException;
  16. use Slim\Handlers\Strategies\RequestResponse;
  17. use Slim\Interfaces\InvocationStrategyInterface;
  18. use Slim\Interfaces\RouteInterface;
  19. /**
  20. * Route
  21. */
  22. class Route extends Routable implements RouteInterface
  23. {
  24. use MiddlewareAwareTrait;
  25. /**
  26. * HTTP methods supported by this route
  27. *
  28. * @var string[]
  29. */
  30. protected $methods = [];
  31. /**
  32. * Route identifier
  33. *
  34. * @var string
  35. */
  36. protected $identifier;
  37. /**
  38. * Route name
  39. *
  40. * @var null|string
  41. */
  42. protected $name;
  43. /**
  44. * Parent route groups
  45. *
  46. * @var RouteGroup[]
  47. */
  48. protected $groups;
  49. private $finalized = false;
  50. /**
  51. * Output buffering mode
  52. *
  53. * One of: false, 'prepend' or 'append'
  54. *
  55. * @var boolean|string
  56. */
  57. protected $outputBuffering = 'append';
  58. /**
  59. * Route parameters
  60. *
  61. * @var array
  62. */
  63. protected $arguments = [];
  64. /**
  65. * The callable payload
  66. *
  67. * @var callable
  68. */
  69. protected $callable;
  70. /**
  71. * Create new route
  72. *
  73. * @param string|string[] $methods The route HTTP methods
  74. * @param string $pattern The route pattern
  75. * @param callable $callable The route callable
  76. * @param RouteGroup[] $groups The parent route groups
  77. * @param int $identifier The route identifier
  78. */
  79. public function __construct($methods, $pattern, $callable, $groups = [], $identifier = 0)
  80. {
  81. $this->methods = is_string($methods) ? [$methods] : $methods;
  82. $this->pattern = $pattern;
  83. $this->callable = $callable;
  84. $this->groups = $groups;
  85. $this->identifier = 'route' . $identifier;
  86. }
  87. /**
  88. * Finalize the route in preparation for dispatching
  89. */
  90. public function finalize()
  91. {
  92. if ($this->finalized) {
  93. return;
  94. }
  95. $groupMiddleware = [];
  96. foreach ($this->getGroups() as $group) {
  97. $groupMiddleware = array_merge($group->getMiddleware(), $groupMiddleware);
  98. }
  99. $this->middleware = array_merge($this->middleware, $groupMiddleware);
  100. foreach ($this->getMiddleware() as $middleware) {
  101. $this->addMiddleware($middleware);
  102. }
  103. $this->finalized = true;
  104. }
  105. /**
  106. * Get route callable
  107. *
  108. * @return callable
  109. */
  110. public function getCallable()
  111. {
  112. return $this->callable;
  113. }
  114. /**
  115. * This method enables you to override the Route's callable
  116. *
  117. * @param string|\Closure $callable
  118. */
  119. public function setCallable($callable)
  120. {
  121. $this->callable = $callable;
  122. }
  123. /**
  124. * Get route methods
  125. *
  126. * @return string[]
  127. */
  128. public function getMethods()
  129. {
  130. return $this->methods;
  131. }
  132. /**
  133. * Get parent route groups
  134. *
  135. * @return RouteGroup[]
  136. */
  137. public function getGroups()
  138. {
  139. return $this->groups;
  140. }
  141. /**
  142. * Get route name
  143. *
  144. * @return null|string
  145. */
  146. public function getName()
  147. {
  148. return $this->name;
  149. }
  150. /**
  151. * Get route identifier
  152. *
  153. * @return string
  154. */
  155. public function getIdentifier()
  156. {
  157. return $this->identifier;
  158. }
  159. /**
  160. * Get output buffering mode
  161. *
  162. * @return boolean|string
  163. */
  164. public function getOutputBuffering()
  165. {
  166. return $this->outputBuffering;
  167. }
  168. /**
  169. * Set output buffering mode
  170. *
  171. * One of: false, 'prepend' or 'append'
  172. *
  173. * @param boolean|string $mode
  174. *
  175. * @throws InvalidArgumentException If an unknown buffering mode is specified
  176. */
  177. public function setOutputBuffering($mode)
  178. {
  179. if (!in_array($mode, [false, 'prepend', 'append'], true)) {
  180. throw new InvalidArgumentException('Unknown output buffering mode');
  181. }
  182. $this->outputBuffering = $mode;
  183. }
  184. /**
  185. * Set route name
  186. *
  187. * @param string $name
  188. *
  189. * @return self
  190. *
  191. * @throws InvalidArgumentException if the route name is not a string
  192. */
  193. public function setName($name)
  194. {
  195. if (!is_string($name)) {
  196. throw new InvalidArgumentException('Route name must be a string');
  197. }
  198. $this->name = $name;
  199. return $this;
  200. }
  201. /**
  202. * Set a route argument
  203. *
  204. * @param string $name
  205. * @param string $value
  206. *
  207. * @return self
  208. */
  209. public function setArgument($name, $value)
  210. {
  211. $this->arguments[$name] = $value;
  212. return $this;
  213. }
  214. /**
  215. * Replace route arguments
  216. *
  217. * @param array $arguments
  218. *
  219. * @return self
  220. */
  221. public function setArguments(array $arguments)
  222. {
  223. $this->arguments = $arguments;
  224. return $this;
  225. }
  226. /**
  227. * Retrieve route arguments
  228. *
  229. * @return array
  230. */
  231. public function getArguments()
  232. {
  233. return $this->arguments;
  234. }
  235. /**
  236. * Retrieve a specific route argument
  237. *
  238. * @param string $name
  239. * @param mixed $default
  240. *
  241. * @return mixed
  242. */
  243. public function getArgument($name, $default = null)
  244. {
  245. if (array_key_exists($name, $this->arguments)) {
  246. return $this->arguments[$name];
  247. }
  248. return $default;
  249. }
  250. /********************************************************************************
  251. * Route Runner
  252. *******************************************************************************/
  253. /**
  254. * Prepare the route for use
  255. *
  256. * @param ServerRequestInterface $request
  257. * @param array $arguments
  258. */
  259. public function prepare(ServerRequestInterface $request, array $arguments)
  260. {
  261. // Add the arguments
  262. foreach ($arguments as $k => $v) {
  263. $this->setArgument($k, $v);
  264. }
  265. }
  266. /**
  267. * Run route
  268. *
  269. * This method traverses the middleware stack, including the route's callable
  270. * and captures the resultant HTTP response object. It then sends the response
  271. * back to the Application.
  272. *
  273. * @param ServerRequestInterface $request
  274. * @param ResponseInterface $response
  275. *
  276. * @return ResponseInterface
  277. */
  278. public function run(ServerRequestInterface $request, ResponseInterface $response)
  279. {
  280. // Finalise route now that we are about to run it
  281. $this->finalize();
  282. // Traverse middleware stack and fetch updated response
  283. return $this->callMiddlewareStack($request, $response);
  284. }
  285. /**
  286. * Dispatch route callable against current Request and Response objects
  287. *
  288. * This method invokes the route object's callable. If middleware is
  289. * registered for the route, each callable middleware is invoked in
  290. * the order specified.
  291. *
  292. * @param ServerRequestInterface $request The current Request object
  293. * @param ResponseInterface $response The current Response object
  294. * @return \Psr\Http\Message\ResponseInterface
  295. * @throws \Exception if the route callable throws an exception
  296. */
  297. public function __invoke(ServerRequestInterface $request, ResponseInterface $response)
  298. {
  299. $this->callable = $this->resolveCallable($this->callable);
  300. /** @var InvocationStrategyInterface $handler */
  301. $handler = isset($this->container) ? $this->container->get('foundHandler') : new RequestResponse();
  302. // invoke route callable
  303. if ($this->outputBuffering === false) {
  304. $newResponse = $handler($this->callable, $request, $response, $this->arguments);
  305. } else {
  306. try {
  307. ob_start();
  308. $newResponse = $handler($this->callable, $request, $response, $this->arguments);
  309. $output = ob_get_clean();
  310. // @codeCoverageIgnoreStart
  311. } catch (Throwable $e) {
  312. ob_end_clean();
  313. throw $e;
  314. // @codeCoverageIgnoreEnd
  315. } catch (Exception $e) {
  316. ob_end_clean();
  317. throw $e;
  318. }
  319. }
  320. if ($newResponse instanceof ResponseInterface) {
  321. // if route callback returns a ResponseInterface, then use it
  322. $response = $newResponse;
  323. } elseif (is_string($newResponse)) {
  324. // if route callback returns a string, then append it to the response
  325. if ($response->getBody()->isWritable()) {
  326. $response->getBody()->write($newResponse);
  327. }
  328. }
  329. if (!empty($output) && $response->getBody()->isWritable()) {
  330. if ($this->outputBuffering === 'prepend') {
  331. // prepend output buffer content
  332. $body = new Http\Body(fopen('php://temp', 'r+'));
  333. $body->write($output . $response->getBody());
  334. $response = $response->withBody($body);
  335. } elseif ($this->outputBuffering === 'append') {
  336. // append output buffer content
  337. $response->getBody()->write($output);
  338. }
  339. }
  340. return $response;
  341. }
  342. }