3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15 * This software consists of voluntary contributions made by many individuals
16 * and is licensed under the MIT license.
21 use Fig\Http\Message\RequestMethodInterface;
24 * Routing class to match request URL's against given routes and map them to a controller action.
29 * RouteCollection that holds all Route objects
31 * @var RouteCollection
33 private $routes = array();
36 * Array to store named routes in, used for reverse routing.
39 private $namedRoutes = array();
42 * The base REQUEST_URI. Gets prepended to all route url's.
45 private $basePath = '';
48 * @param RouteCollection $collection
50 public function __construct(RouteCollection $collection)
52 $this->routes = $collection;
54 foreach ($this->routes->all() as $route) {
55 $name = $route->getName();
57 $this->namedRoutes[$name] = $route;
63 * Set the base _url - gets prepended to all route _url's.
66 public function setBasePath($basePath)
68 $this->basePath = rtrim($basePath, '/');
72 * Matches the current request against mapped routes
74 public function matchCurrentRequest()
77 isset($_POST['_method'])
78 && ($_method = strtoupper($_POST['_method']))
79 && in_array($_method, array(RequestMethodInterface::METHOD_PUT, RequestMethodInterface::METHOD_DELETE), true)
80 ) ? $_method : $_SERVER['REQUEST_METHOD'];
82 $requestUrl = $_SERVER['REQUEST_URI'];
84 // strip GET variables from URL
85 if (($pos = strpos($requestUrl, '?')) !== false) {
86 $requestUrl = substr($requestUrl, 0, $pos);
89 return $this->match($requestUrl, $requestMethod);
93 * Match given request _url and request method and see if a route has been defined for it
94 * If so, return route's target
95 * If called multiple times
97 * @param string $requestUrl
98 * @param string $requestMethod
102 public function match($requestUrl, $requestMethod = RequestMethodInterface::METHOD_GET)
104 $currentDir = dirname($_SERVER['SCRIPT_NAME']);
106 foreach ($this->routes->all() as $routes) {
107 // compare server request method with route's allowed http methods
108 if (! in_array($requestMethod, (array)$routes->getMethods(), true)) {
112 if ('/' !== $currentDir) {
113 $requestUrl = str_replace($currentDir, '', $requestUrl);
116 $route = rtrim($routes->getRegex(), '/');
117 $pattern = '@^' . preg_quote($this->basePath) . $route . '/?$@i';
118 if (!preg_match($pattern, $requestUrl, $matches)) {
124 if (preg_match_all('/:([\w-%]+)/', $routes->getUrl(), $argument_keys)) {
125 // grab array with matches
126 $argument_keys = $argument_keys[1];
128 // check arguments number
130 if(count($argument_keys) !== (count($matches) -1)) {
134 // loop trough parameter names, store matching value in $params array
135 foreach ($argument_keys as $key => $name) {
136 if (isset($matches[$key+1])) {
137 $params[$name] = $matches[$key+1];
142 $routes->setParameters($params);
152 * Reverse route a named route
155 * @param array $params Optional array of parameters to use in URL
159 * @return string The url to the route
161 public function generate($routeName, array $params = array())
163 // Check if route exists
164 if (!isset($this->namedRoutes[$routeName])) {
165 throw new Exception("No route with the name $routeName has been found.");
168 /** @var \PHPRouter\Route $route */
169 $route = $this->namedRoutes[$routeName];
170 $url = $route->getUrl();
172 // replace route url with given parameters
173 if ($params && preg_match_all('/:(\w+)/', $url, $param_keys)) {
174 // grab array with matches
175 $param_keys = $param_keys[1];
177 // loop trough parameter names, store matching value in $params array
178 foreach ($param_keys as $key) {
179 if (isset($params[$key])) {
180 $url = preg_replace('/:'.preg_quote($key,'/').'/', $params[$key], $url, 1);
189 * Create routes by array, and return a Router object
191 * @param array $config provide by Config::loadFromFile()
194 public static function parseConfig(array $config)
196 $collection = new RouteCollection();
197 foreach ($config['routes'] as $name => $route) {
198 $collection->attachRoute(new Route($route[0], array(
199 '_controller' => str_replace('.', '::', $route[1]),
200 'methods' => $route[2],
205 $router = new Router($collection);
206 if (isset($config['base_path'])) {
207 $router->setBasePath($config['base_path']);