PageRenderTime 56ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/cakephp/cakephp/src/Routing/RouteCollection.php

https://bitbucket.org/jorgedavidolmedo/backup_bancard
PHP | 324 lines | 187 code | 28 blank | 109 comment | 24 complexity | 4a4209261cef8453855d38d292f637cc MD5 | raw file
Possible License(s): BSD-3-Clause, JSON, MIT, GPL-3.0
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Routing;
  16. use Cake\Routing\Exception\DuplicateNamedRouteException;
  17. use Cake\Routing\Exception\MissingRouteException;
  18. use Cake\Routing\Route\Route;
  19. /**
  20. * Contains a collection of routes.
  21. *
  22. * Provides an interface for adding/removing routes
  23. * and parsing/generating URLs with the routes it contains.
  24. *
  25. * @internal
  26. */
  27. class RouteCollection
  28. {
  29. /**
  30. * The routes connected to this collection.
  31. *
  32. * @var array
  33. */
  34. protected $_routeTable = [];
  35. /**
  36. * The routes connected to this collection.
  37. *
  38. * @var \Cake\Routing\Route\Route[]
  39. */
  40. protected $_routes = [];
  41. /**
  42. * The hash map of named routes that are in this collection.
  43. *
  44. * @var \Cake\Routing\Route\Route[]
  45. */
  46. protected $_named = [];
  47. /**
  48. * Routes indexed by path prefix.
  49. *
  50. * @var array
  51. */
  52. protected $_paths = [];
  53. /**
  54. * Route extensions
  55. *
  56. * @var array
  57. */
  58. protected $_extensions = [];
  59. /**
  60. * Add a route to the collection.
  61. *
  62. * @param \Cake\Routing\Route\Route $route The route object to add.
  63. * @param array $options Additional options for the route. Primarily for the
  64. * `_name` option, which enables named routes.
  65. * @return void
  66. */
  67. public function add(Route $route, array $options = [])
  68. {
  69. $this->_routes[] = $route;
  70. // Explicit names
  71. if (isset($options['_name'])) {
  72. if (isset($this->_named[$options['_name']])) {
  73. $matched = $this->_named[$options['_name']];
  74. throw new DuplicateNamedRouteException([
  75. 'name' => $options['_name'],
  76. 'url' => $matched->template,
  77. 'duplicate' => $matched,
  78. ]);
  79. }
  80. $this->_named[$options['_name']] = $route;
  81. }
  82. // Generated names.
  83. $name = $route->getName();
  84. if (!isset($this->_routeTable[$name])) {
  85. $this->_routeTable[$name] = [];
  86. }
  87. $this->_routeTable[$name][] = $route;
  88. // Index path prefixes (for parsing)
  89. $path = $route->staticPath();
  90. if (empty($this->_paths[$path])) {
  91. $this->_paths[$path] = [];
  92. krsort($this->_paths);
  93. }
  94. $this->_paths[$path][] = $route;
  95. $extensions = $route->getExtensions();
  96. if (count($extensions) > 0) {
  97. $this->extensions($extensions);
  98. }
  99. }
  100. /**
  101. * Takes the URL string and iterates the routes until one is able to parse the route.
  102. *
  103. * @param string $url URL to parse.
  104. * @param string $method The HTTP method to use.
  105. * @return array An array of request parameters parsed from the URL.
  106. * @throws \Cake\Routing\Exception\MissingRouteException When a URL has no matching route.
  107. */
  108. public function parse($url, $method = '')
  109. {
  110. $decoded = urldecode($url);
  111. foreach (array_keys($this->_paths) as $path) {
  112. if (strpos($decoded, $path) !== 0) {
  113. continue;
  114. }
  115. $queryParameters = null;
  116. if (strpos($url, '?') !== false) {
  117. list($url, $queryParameters) = explode('?', $url, 2);
  118. parse_str($queryParameters, $queryParameters);
  119. }
  120. /* @var \Cake\Routing\Route\Route $route */
  121. foreach ($this->_paths[$path] as $route) {
  122. $r = $route->parse($url, $method);
  123. if ($r === false) {
  124. continue;
  125. }
  126. if ($queryParameters) {
  127. $r['?'] = $queryParameters;
  128. }
  129. return $r;
  130. }
  131. }
  132. throw new MissingRouteException(['url' => $url]);
  133. }
  134. /**
  135. * Get the set of names from the $url. Accepts both older style array urls,
  136. * and newer style urls containing '_name'
  137. *
  138. * @param array $url The url to match.
  139. * @return array The set of names of the url
  140. */
  141. protected function _getNames($url)
  142. {
  143. $plugin = false;
  144. if (isset($url['plugin']) && $url['plugin'] !== false) {
  145. $plugin = strtolower($url['plugin']);
  146. }
  147. $prefix = false;
  148. if (isset($url['prefix']) && $url['prefix'] !== false) {
  149. $prefix = strtolower($url['prefix']);
  150. }
  151. $controller = strtolower($url['controller']);
  152. $action = strtolower($url['action']);
  153. $names = [
  154. "${controller}:${action}",
  155. "${controller}:_action",
  156. "_controller:${action}",
  157. "_controller:_action",
  158. ];
  159. // No prefix, no plugin
  160. if ($prefix === false && $plugin === false) {
  161. return $names;
  162. }
  163. // Only a plugin
  164. if ($prefix === false) {
  165. return [
  166. "${plugin}.${controller}:${action}",
  167. "${plugin}.${controller}:_action",
  168. "${plugin}._controller:${action}",
  169. "${plugin}._controller:_action",
  170. "_plugin.${controller}:${action}",
  171. "_plugin.${controller}:_action",
  172. "_plugin._controller:${action}",
  173. "_plugin._controller:_action",
  174. ];
  175. }
  176. // Only a prefix
  177. if ($plugin === false) {
  178. return [
  179. "${prefix}:${controller}:${action}",
  180. "${prefix}:${controller}:_action",
  181. "${prefix}:_controller:${action}",
  182. "${prefix}:_controller:_action",
  183. "_prefix:${controller}:${action}",
  184. "_prefix:${controller}:_action",
  185. "_prefix:_controller:${action}",
  186. "_prefix:_controller:_action",
  187. ];
  188. }
  189. // Prefix and plugin has the most options
  190. // as there are 4 factors.
  191. return [
  192. "${prefix}:${plugin}.${controller}:${action}",
  193. "${prefix}:${plugin}.${controller}:_action",
  194. "${prefix}:${plugin}._controller:${action}",
  195. "${prefix}:${plugin}._controller:_action",
  196. "${prefix}:_plugin.${controller}:${action}",
  197. "${prefix}:_plugin.${controller}:_action",
  198. "${prefix}:_plugin._controller:${action}",
  199. "${prefix}:_plugin._controller:_action",
  200. "_prefix:${plugin}.${controller}:${action}",
  201. "_prefix:${plugin}.${controller}:_action",
  202. "_prefix:${plugin}._controller:${action}",
  203. "_prefix:${plugin}._controller:_action",
  204. "_prefix:_plugin.${controller}:${action}",
  205. "_prefix:_plugin.${controller}:_action",
  206. "_prefix:_plugin._controller:${action}",
  207. "_prefix:_plugin._controller:_action",
  208. ];
  209. }
  210. /**
  211. * Reverse route or match a $url array with the defined routes.
  212. * Returns either the string URL generate by the route, or false on failure.
  213. *
  214. * @param array $url The url to match.
  215. * @param array $context The request context to use. Contains _base, _port,
  216. * _host, _scheme and params keys.
  217. * @return string|false Either a string on match, or false on failure.
  218. * @throws \Cake\Routing\Exception\MissingRouteException when a route cannot be matched.
  219. */
  220. public function match($url, $context)
  221. {
  222. // Named routes support optimization.
  223. if (isset($url['_name'])) {
  224. $name = $url['_name'];
  225. unset($url['_name']);
  226. $out = false;
  227. if (isset($this->_named[$name])) {
  228. $route = $this->_named[$name];
  229. $out = $route->match($url + $route->defaults, $context);
  230. if ($out) {
  231. return $out;
  232. }
  233. throw new MissingRouteException([
  234. 'url' => $name,
  235. 'context' => $context,
  236. 'message' => 'A named route was found for "%s", but matching failed.',
  237. ]);
  238. }
  239. throw new MissingRouteException(['url' => $name, 'context' => $context]);
  240. }
  241. foreach ($this->_getNames($url) as $name) {
  242. if (empty($this->_routeTable[$name])) {
  243. continue;
  244. }
  245. /* @var \Cake\Routing\Route\Route $route */
  246. foreach ($this->_routeTable[$name] as $route) {
  247. $match = $route->match($url, $context);
  248. if ($match) {
  249. return strlen($match) > 1 ? trim($match, '/') : $match;
  250. }
  251. }
  252. }
  253. throw new MissingRouteException(['url' => var_export($url, true), 'context' => $context]);
  254. }
  255. /**
  256. * Get all the connected routes as a flat list.
  257. *
  258. * @return \Cake\Routing\Route\Route[]
  259. */
  260. public function routes()
  261. {
  262. return $this->_routes;
  263. }
  264. /**
  265. * Get the connected named routes.
  266. *
  267. * @return \Cake\Routing\Route\Route[]
  268. */
  269. public function named()
  270. {
  271. return $this->_named;
  272. }
  273. /**
  274. * Get/set the extensions that the route collection could handle.
  275. *
  276. * @param null|string|array $extensions Either the list of extensions to set,
  277. * or null to get.
  278. * @param bool $merge Whether to merge with or override existing extensions.
  279. * Defaults to `true`.
  280. * @return array The valid extensions.
  281. */
  282. public function extensions($extensions = null, $merge = true)
  283. {
  284. if ($extensions === null) {
  285. return $this->_extensions;
  286. }
  287. $extensions = (array)$extensions;
  288. if ($merge) {
  289. $extensions = array_unique(array_merge(
  290. $this->_extensions,
  291. $extensions
  292. ));
  293. }
  294. return $this->_extensions = $extensions;
  295. }
  296. }