/vendor/cakephp/cakephp/src/Routing/RouteCollection.php
https://gitlab.com/vannh/portal_training · PHP · 305 lines · 172 code · 27 blank · 106 comment · 23 complexity · fbc68fbbffd91074b464ff51db048e0c MD5 · raw file
- <?php
- /**
- * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
- * @link http://cakephp.org CakePHP(tm) Project
- * @since 3.0.0
- * @license http://www.opensource.org/licenses/mit-license.php MIT License
- */
- namespace Cake\Routing;
- use Cake\Routing\Exception\MissingRouteException;
- use Cake\Routing\Route\Route;
- /**
- * Contains a collection of routes.
- *
- * Provides an interface for adding/removing routes
- * and parsing/generating URLs with the routes it contains.
- *
- * @internal
- */
- class RouteCollection
- {
- /**
- * The routes connected to this collection.
- *
- * @var array
- */
- protected $_routeTable = [];
- /**
- * The routes connected to this collection.
- *
- * @var array
- */
- protected $_routes = [];
- /**
- * The hash map of named routes that are in this collection.
- *
- * @var array
- */
- protected $_named = [];
- /**
- * Routes indexed by path prefix.
- *
- * @var array
- */
- protected $_paths = [];
- /**
- * Route extensions
- *
- * @var array
- */
- protected $_extensions = [];
- /**
- * Add a route to the collection.
- *
- * @param \Cake\Routing\Route\Route $route The route object to add.
- * @param array $options Additional options for the route. Primarily for the
- * `_name` option, which enables named routes.
- * @return void
- */
- public function add(Route $route, array $options = [])
- {
- $this->_routes[] = $route;
- // Explicit names
- if (isset($options['_name'])) {
- $this->_named[$options['_name']] = $route;
- }
- // Generated names.
- $name = $route->getName();
- if (!isset($this->_routeTable[$name])) {
- $this->_routeTable[$name] = [];
- }
- $this->_routeTable[$name][] = $route;
- // Index path prefixes (for parsing)
- $path = $route->staticPath();
- if (empty($this->_paths[$path])) {
- $this->_paths[$path] = [];
- krsort($this->_paths);
- }
- $this->_paths[$path][] = $route;
- $extensions = $route->extensions();
- if ($extensions) {
- $this->extensions($extensions);
- }
- }
- /**
- * Takes the URL string and iterates the routes until one is able to parse the route.
- *
- * @param string $url URL to parse.
- * @return array An array of request parameters parsed from the URL.
- * @throws \Cake\Routing\Exception\MissingRouteException When a URL has no matching route.
- */
- public function parse($url)
- {
- foreach (array_keys($this->_paths) as $path) {
- if (strpos($url, $path) !== 0) {
- continue;
- }
- $queryParameters = null;
- if (strpos($url, '?') !== false) {
- list($url, $queryParameters) = explode('?', $url, 2);
- parse_str($queryParameters, $queryParameters);
- }
- foreach ($this->_paths[$path] as $route) {
- $r = $route->parse($url);
- if ($r === false) {
- continue;
- }
- if ($queryParameters) {
- $r['?'] = $queryParameters;
- }
- return $r;
- }
- }
- throw new MissingRouteException(['url' => $url]);
- }
- /**
- * Get the set of names from the $url. Accepts both older style array urls,
- * and newer style urls containing '_name'
- *
- * @param array $url The url to match.
- * @return array The set of names of the url
- */
- protected function _getNames($url)
- {
- $plugin = false;
- if (isset($url['plugin']) && $url['plugin'] !== false) {
- $plugin = strtolower($url['plugin']);
- }
- $prefix = false;
- if (isset($url['prefix']) && $url['prefix'] !== false) {
- $prefix = strtolower($url['prefix']);
- }
- $controller = strtolower($url['controller']);
- $action = strtolower($url['action']);
- $names = [
- "${controller}:${action}",
- "${controller}:_action",
- "_controller:${action}",
- "_controller:_action"
- ];
- // No prefix, no plugin
- if ($prefix === false && $plugin === false) {
- return $names;
- }
- // Only a plugin
- if ($prefix === false) {
- return [
- "${plugin}.${controller}:${action}",
- "${plugin}.${controller}:_action",
- "${plugin}._controller:${action}",
- "${plugin}._controller:_action",
- "_plugin.${controller}:${action}",
- "_plugin.${controller}:_action",
- "_plugin._controller:${action}",
- "_plugin._controller:_action",
- ];
- }
- // Only a prefix
- if ($plugin === false) {
- return [
- "${prefix}:${controller}:${action}",
- "${prefix}:${controller}:_action",
- "${prefix}:_controller:${action}",
- "${prefix}:_controller:_action",
- "_prefix:${controller}:${action}",
- "_prefix:${controller}:_action",
- "_prefix:_controller:${action}",
- "_prefix:_controller:_action"
- ];
- }
- // Prefix and plugin has the most options
- // as there are 4 factors.
- return [
- "${prefix}:${plugin}.${controller}:${action}",
- "${prefix}:${plugin}.${controller}:_action",
- "${prefix}:${plugin}._controller:${action}",
- "${prefix}:${plugin}._controller:_action",
- "${prefix}:_plugin.${controller}:${action}",
- "${prefix}:_plugin.${controller}:_action",
- "${prefix}:_plugin._controller:${action}",
- "${prefix}:_plugin._controller:_action",
- "_prefix:${plugin}.${controller}:${action}",
- "_prefix:${plugin}.${controller}:_action",
- "_prefix:${plugin}._controller:${action}",
- "_prefix:${plugin}._controller:_action",
- "_prefix:_plugin.${controller}:${action}",
- "_prefix:_plugin.${controller}:_action",
- "_prefix:_plugin._controller:${action}",
- "_prefix:_plugin._controller:_action",
- ];
- }
- /**
- * Reverse route or match a $url array with the defined routes.
- * Returns either the string URL generate by the route, or false on failure.
- *
- * @param array $url The url to match.
- * @param array $context The request context to use. Contains _base, _port,
- * _host, _scheme and params keys.
- * @return string|false Either a string on match, or false on failure.
- * @throws \Cake\Routing\Exception\MissingRouteException when a route cannot be matched.
- */
- public function match($url, $context)
- {
- // Named routes support optimization.
- if (isset($url['_name'])) {
- $name = $url['_name'];
- unset($url['_name']);
- $out = false;
- if (isset($this->_named[$name])) {
- $route = $this->_named[$name];
- $out = $route->match($url + $route->defaults, $context);
- }
- if ($out) {
- return $out;
- }
- throw new MissingRouteException(['url' => $name, 'context' => $context]);
- }
- foreach ($this->_getNames($url) as $name) {
- if (empty($this->_routeTable[$name])) {
- continue;
- }
- foreach ($this->_routeTable[$name] as $route) {
- $match = $route->match($url, $context);
- if ($match) {
- return strlen($match) > 1 ? trim($match, '/') : $match;
- }
- }
- }
- throw new MissingRouteException(['url' => var_export($url, true), 'context' => $context]);
- }
- /**
- * Get all the connected routes as a flat list.
- *
- * @return array
- */
- public function routes()
- {
- return $this->_routes;
- }
- /**
- * Get the connected named routes.
- *
- * @return array
- */
- public function named()
- {
- return $this->_named;
- }
- /**
- * Get/set the extensions that the route collection could handle.
- *
- * @param null|string|array $extensions Either the list of extensions to set,
- * or null to get.
- * @param bool $merge Whether to merge with or override existing extensions.
- * Defaults to `true`.
- * @return array The valid extensions.
- */
- public function extensions($extensions = null, $merge = true)
- {
- if ($extensions === null) {
- return $this->_extensions;
- }
- $extensions = (array)$extensions;
- if ($merge) {
- $extensions = array_unique(array_merge(
- $this->_extensions,
- $extensions
- ));
- }
- return $this->_extensions = $extensions;
- }
- }