Passed
Push — master ( 233819...77d4a0 )
by Ch
02:28
created
examples/basic/index.php 2 patches
Indentation   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -26,19 +26,19 @@
 block discarded – undo
26 26
 <pre>
27 27
  <?php
28 28
  if ($match) {
29
-     foreach ($match as $key => $value) {
30
-         echo '<p>' . $key . ': ';
31
-         if (is_array($value)) {
32
-             echo '<ul>';
33
-             foreach ($value as $k => $v) {
34
-                 echo '<li>'.$k.': '.$v.'</li>';
35
-             }
36
-             echo '</ul>';
37
-         } else {
38
-             echo $value;
39
-         }
40
-         echo '</p>';
41
-     }
29
+	 foreach ($match as $key => $value) {
30
+		 echo '<p>' . $key . ': ';
31
+		 if (is_array($value)) {
32
+			 echo '<ul>';
33
+			 foreach ($value as $k => $v) {
34
+				 echo '<li>'.$k.': '.$v.'</li>';
35
+			 }
36
+			 echo '</ul>';
37
+		 } else {
38
+			 echo $value;
39
+		 }
40
+		 echo '</p>';
41
+	 }
42 42
  }
43 43
  ?>
44 44
  </pre>
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -31,7 +31,7 @@
 block discarded – undo
31 31
          if (is_array($value)) {
32 32
              echo '<ul>';
33 33
              foreach ($value as $k => $v) {
34
-                 echo '<li>'.$k.': '.$v.'</li>';
34
+                 echo '<li>' . $k . ': ' . $v . '</li>';
35 35
              }
36 36
              echo '</ul>';
37 37
          } else {
Please login to merge, or discard this patch.
Router.php 1 patch
Indentation   +195 added lines, -195 removed lines patch added patch discarded remove patch
@@ -6,199 +6,199 @@
 block discarded – undo
6 6
 
7 7
 class Router
8 8
 {
9
-    protected $routes = [];
10
-    protected $namedRoutes = [];
11
-    protected $basePath = '';
12
-    protected $all = ['get', 'post'];
13
-    protected $server;
14
-    /**
15
-     * @var RouterParser
16
-     */
17
-    private $parser;
18
-
19
-    /**
20
-     * Create router in one call from config.
21
-     *
22
-     * @param RouterParser $parser
23
-     * @param array $routes
24
-     * @param string $basePath
25
-     * @param array|null $server
26
-     */
27
-    public function __construct(RouterParser $parser, $routes = [], $basePath = '', $server = null)
28
-    {
29
-        $this->setRoutes($routes);
30
-        $this->setBasePath($basePath);
31
-        $this->parser = $parser;
32
-        $this->server = $server;
33
-    }
34
-
35
-    /**
36
-     * Map a route to a target
37
-     *
38
-     * @param string $method One of 5 HTTP Methods, or a pipe-separated list of multiple HTTP Methods (GET|POST|PATCH|PUT|DELETE)
39
-     * @param string $route The route regex, custom regex must start with an @. You can use multiple pre-set regex filters, like [i:id]
40
-     * @param mixed $target The target where this route should point to. Can be anything.
41
-     * @param string $routeName Optional name of this route. Supply if you want to reverse route this url in your application.
42
-     */
43
-    public function map($method, $route, $target, $routeName = null)
44
-    {
45
-        if (is_string($routeName)) {
46
-            $this->handleException($routeName, "Can not redeclare route '%s'", true);
47
-            $this->namedRoutes[$routeName] = $route;
48
-        }
49
-
50
-        $this->routes[] = array($method, $route, $target, $routeName);
51
-    }
52
-
53
-    /**
54
-     * Reversed routing
55
-     * Generate the URL for a named route. Replace regexes with supplied parameters
56
-     *
57
-     * @param string $routeName The name of the route.
58
-     * @param array $params Associative array of parameters to replace placeholders with.
59
-     *
60
-     * @return string The URL of the route with named parameters in place.
61
-     */
62
-    public function generate($routeName, array $params = [])
63
-    {
64
-        $this->handleException($routeName, "Route '%s' does not exist.", false);
65
-
66
-        $route = $this->namedRoutes[$routeName];
67
-
68
-        return $this->parser->generate($this->basePath, $route, $params);
69
-    }
70
-
71
-    /**
72
-     * Match a given Request Url against stored routes
73
-     * @param string $requestUrl
74
-     * @param string $requestMethod
75
-     *
76
-     * @return array|boolean Array with route information on success, false on failure (no match).
77
-     */
78
-    public function match($requestUrl = null, $requestMethod = null)
79
-    {
80
-        $requestUrl = $this->getRequestUrl($requestUrl);
81
-
82
-        // set Request Method if it isn't passed as a parameter
83
-        if (is_null($requestMethod)) {
84
-            $requestMethod = $this->server['REQUEST_METHOD'];
85
-        }
86
-
87
-        foreach ($this->routes as $handler) {
88
-            if (!$this->parser->methodMatch($handler[0], $requestMethod, $handler[1], $requestUrl)) {
89
-                continue;
90
-            }
91
-
92
-            return array(
93
-                'target' => $handler[2],
94
-                'params' => array_filter($this->parser->getParams(), function ($k) {
95
-                    return !is_numeric($k);
96
-                }, ARRAY_FILTER_USE_KEY),
97
-                'name'   => $handler[3]
98
-            );
99
-        }
100
-
101
-        return false;
102
-    }
103
-
104
-    /**
105
-     * @param $method
106
-     * @param $arguments
107
-     *
108
-     * @throws RouterException
109
-     */
110
-    public function __call($method, $arguments)
111
-    {
112
-        if (!in_array($method, array('get', 'post', 'delete', 'put', 'patch', 'update', 'all'))) {
113
-            throw new RouterException($method . ' not exist in the '. __CLASS__);
114
-        }
115
-
116
-        $methods = $method == 'all' ? implode('|', $this->all) : $method;
117
-
118
-        $route = array_merge([$methods], $arguments);
119
-
120
-        call_user_func_array([$this, 'map'], $route);
121
-    }
122
-
123
-    /**
124
-     * Retrieves all routes.
125
-     * Useful if you want to process or display routes.
126
-     *
127
-     * @return array All routes.
128
-     */
129
-    public function getRoutes()
130
-    {
131
-        return $this->routes;
132
-    }
133
-
134
-    /**
135
-     * Add multiple routes at once from array in the following format:
136
-     *
137
-     *   $routes = array(
138
-     *      array($method, $route, $target, $name)
139
-     *   );
140
-     *
141
-     * @param array|Traversable $routes
142
-     *
143
-     * @return void
144
-     */
145
-    public function setRoutes($routes)
146
-    {
147
-        if (!is_array($routes) && !$routes instanceof Traversable) {
148
-            throw new RouterException('Routes should be an array or an instance of Traversable');
149
-        }
150
-        if (!empty($routes)) {
151
-            foreach ($routes as $route) {
152
-                call_user_func_array(array($this, 'map'), $route);
153
-            }
154
-        }
155
-    }
156
-
157
-    /**
158
-     * Set the base path.
159
-     * Useful if you are running your application from a subdirectory.
160
-     *
161
-     * @param $basePath
162
-     */
163
-    public function setBasePath($basePath)
164
-    {
165
-        $this->basePath = $basePath;
166
-    }
167
-
168
-    /**
169
-     * @param $routeName
170
-     * @param $message
171
-     * @param bool $cmpTo
172
-     *
173
-     * @throws RouterException
174
-     */
175
-    private function handleException($routeName, $message, $cmpTo)
176
-    {
177
-        if (array_key_exists($routeName, $this->namedRoutes) === $cmpTo) {
178
-            throw new RouterException(sprintf($message, $routeName));
179
-        }
180
-    }
181
-
182
-    /**
183
-     * @param $requestUrl
184
-     *
185
-     * @return mixed
186
-     */
187
-    private function getRequestUrl($requestUrl = null)
188
-    {
189
-        // set Request Url if it isn't passed as parameter
190
-        if (is_null($requestUrl)) {
191
-            $requestUrl = parse_url($this->server['REQUEST_URI'], PHP_URL_PATH);
192
-        }
193
-
194
-        return str_replace($this->basePath, '', strtok($requestUrl, '?'));
195
-    }
196
-
197
-    /**
198
-     * @return RouterParser
199
-     */
200
-    public function getParser()
201
-    {
202
-        return $this->parser;
203
-    }
9
+	protected $routes = [];
10
+	protected $namedRoutes = [];
11
+	protected $basePath = '';
12
+	protected $all = ['get', 'post'];
13
+	protected $server;
14
+	/**
15
+	 * @var RouterParser
16
+	 */
17
+	private $parser;
18
+
19
+	/**
20
+	 * Create router in one call from config.
21
+	 *
22
+	 * @param RouterParser $parser
23
+	 * @param array $routes
24
+	 * @param string $basePath
25
+	 * @param array|null $server
26
+	 */
27
+	public function __construct(RouterParser $parser, $routes = [], $basePath = '', $server = null)
28
+	{
29
+		$this->setRoutes($routes);
30
+		$this->setBasePath($basePath);
31
+		$this->parser = $parser;
32
+		$this->server = $server;
33
+	}
34
+
35
+	/**
36
+	 * Map a route to a target
37
+	 *
38
+	 * @param string $method One of 5 HTTP Methods, or a pipe-separated list of multiple HTTP Methods (GET|POST|PATCH|PUT|DELETE)
39
+	 * @param string $route The route regex, custom regex must start with an @. You can use multiple pre-set regex filters, like [i:id]
40
+	 * @param mixed $target The target where this route should point to. Can be anything.
41
+	 * @param string $routeName Optional name of this route. Supply if you want to reverse route this url in your application.
42
+	 */
43
+	public function map($method, $route, $target, $routeName = null)
44
+	{
45
+		if (is_string($routeName)) {
46
+			$this->handleException($routeName, "Can not redeclare route '%s'", true);
47
+			$this->namedRoutes[$routeName] = $route;
48
+		}
49
+
50
+		$this->routes[] = array($method, $route, $target, $routeName);
51
+	}
52
+
53
+	/**
54
+	 * Reversed routing
55
+	 * Generate the URL for a named route. Replace regexes with supplied parameters
56
+	 *
57
+	 * @param string $routeName The name of the route.
58
+	 * @param array $params Associative array of parameters to replace placeholders with.
59
+	 *
60
+	 * @return string The URL of the route with named parameters in place.
61
+	 */
62
+	public function generate($routeName, array $params = [])
63
+	{
64
+		$this->handleException($routeName, "Route '%s' does not exist.", false);
65
+
66
+		$route = $this->namedRoutes[$routeName];
67
+
68
+		return $this->parser->generate($this->basePath, $route, $params);
69
+	}
70
+
71
+	/**
72
+	 * Match a given Request Url against stored routes
73
+	 * @param string $requestUrl
74
+	 * @param string $requestMethod
75
+	 *
76
+	 * @return array|boolean Array with route information on success, false on failure (no match).
77
+	 */
78
+	public function match($requestUrl = null, $requestMethod = null)
79
+	{
80
+		$requestUrl = $this->getRequestUrl($requestUrl);
81
+
82
+		// set Request Method if it isn't passed as a parameter
83
+		if (is_null($requestMethod)) {
84
+			$requestMethod = $this->server['REQUEST_METHOD'];
85
+		}
86
+
87
+		foreach ($this->routes as $handler) {
88
+			if (!$this->parser->methodMatch($handler[0], $requestMethod, $handler[1], $requestUrl)) {
89
+				continue;
90
+			}
91
+
92
+			return array(
93
+				'target' => $handler[2],
94
+				'params' => array_filter($this->parser->getParams(), function ($k) {
95
+					return !is_numeric($k);
96
+				}, ARRAY_FILTER_USE_KEY),
97
+				'name'   => $handler[3]
98
+			);
99
+		}
100
+
101
+		return false;
102
+	}
103
+
104
+	/**
105
+	 * @param $method
106
+	 * @param $arguments
107
+	 *
108
+	 * @throws RouterException
109
+	 */
110
+	public function __call($method, $arguments)
111
+	{
112
+		if (!in_array($method, array('get', 'post', 'delete', 'put', 'patch', 'update', 'all'))) {
113
+			throw new RouterException($method . ' not exist in the '. __CLASS__);
114
+		}
115
+
116
+		$methods = $method == 'all' ? implode('|', $this->all) : $method;
117
+
118
+		$route = array_merge([$methods], $arguments);
119
+
120
+		call_user_func_array([$this, 'map'], $route);
121
+	}
122
+
123
+	/**
124
+	 * Retrieves all routes.
125
+	 * Useful if you want to process or display routes.
126
+	 *
127
+	 * @return array All routes.
128
+	 */
129
+	public function getRoutes()
130
+	{
131
+		return $this->routes;
132
+	}
133
+
134
+	/**
135
+	 * Add multiple routes at once from array in the following format:
136
+	 *
137
+	 *   $routes = array(
138
+	 *      array($method, $route, $target, $name)
139
+	 *   );
140
+	 *
141
+	 * @param array|Traversable $routes
142
+	 *
143
+	 * @return void
144
+	 */
145
+	public function setRoutes($routes)
146
+	{
147
+		if (!is_array($routes) && !$routes instanceof Traversable) {
148
+			throw new RouterException('Routes should be an array or an instance of Traversable');
149
+		}
150
+		if (!empty($routes)) {
151
+			foreach ($routes as $route) {
152
+				call_user_func_array(array($this, 'map'), $route);
153
+			}
154
+		}
155
+	}
156
+
157
+	/**
158
+	 * Set the base path.
159
+	 * Useful if you are running your application from a subdirectory.
160
+	 *
161
+	 * @param $basePath
162
+	 */
163
+	public function setBasePath($basePath)
164
+	{
165
+		$this->basePath = $basePath;
166
+	}
167
+
168
+	/**
169
+	 * @param $routeName
170
+	 * @param $message
171
+	 * @param bool $cmpTo
172
+	 *
173
+	 * @throws RouterException
174
+	 */
175
+	private function handleException($routeName, $message, $cmpTo)
176
+	{
177
+		if (array_key_exists($routeName, $this->namedRoutes) === $cmpTo) {
178
+			throw new RouterException(sprintf($message, $routeName));
179
+		}
180
+	}
181
+
182
+	/**
183
+	 * @param $requestUrl
184
+	 *
185
+	 * @return mixed
186
+	 */
187
+	private function getRequestUrl($requestUrl = null)
188
+	{
189
+		// set Request Url if it isn't passed as parameter
190
+		if (is_null($requestUrl)) {
191
+			$requestUrl = parse_url($this->server['REQUEST_URI'], PHP_URL_PATH);
192
+		}
193
+
194
+		return str_replace($this->basePath, '', strtok($requestUrl, '?'));
195
+	}
196
+
197
+	/**
198
+	 * @return RouterParser
199
+	 */
200
+	public function getParser()
201
+	{
202
+		return $this->parser;
203
+	}
204 204
 }
Please login to merge, or discard this patch.
RouterParser.php 1 patch
Indentation   +213 added lines, -213 removed lines patch added patch discarded remove patch
@@ -3,217 +3,217 @@
 block discarded – undo
3 3
 
4 4
 class RouterParser implements RouterParserInterface
5 5
 {
6
-    protected $params = [];
7
-    protected $matchTypes = [
8
-        'i'  => '[0-9]++',
9
-        'a'  => '[0-9A-Za-z]++',
10
-        'h'  => '[0-9A-Fa-f]++',
11
-        '*'  => '.+?',
12
-        '**' => '.++',
13
-        ''   => '[^/\.]++'
14
-    ];
15
-
16
-    /**
17
-     * Create router in one call from config.
18
-     *
19
-     * @param array $matchTypes
20
-     */
21
-    public function __construct($matchTypes = [])
22
-    {
23
-        $this->setMatchTypes($matchTypes);
24
-    }
25
-
26
-    /**
27
-     * Add named match types. It uses array_merge so keys can be overwritten.
28
-     *
29
-     * @param array $matchTypes The key is the name and the value is the regex.
30
-     */
31
-    public function setMatchTypes($matchTypes)
32
-    {
33
-        $this->matchTypes = array_merge($this->matchTypes, $matchTypes);
34
-    }
35
-
36
-    /**
37
-     * Get the url from a route name
38
-     *
39
-     * @param string $basePath
40
-     * @param string $route
41
-     * @param array $params
42
-     *
43
-     * @return string
44
-     */
45
-    public function generate($basePath, $route, array $params)
46
-    {
47
-        $url = $basePath . $route;
48
-
49
-        if (preg_match_all('`(/|\.|)\[([^:\]]*+)(?::([^:\]]*+))?\](\?|)`', $route, $matches, PREG_SET_ORDER)) {
50
-            foreach ($matches as $match) {
51
-                $block  = $match[0];
52
-                $pre    = $match[1];
53
-                $param  = $match[3];
54
-
55
-                if ($pre) {
56
-                    $block = substr($block, 1);
57
-                }
58
-
59
-                if (isset($params[$param])) {
60
-                    $url = str_replace($block, $params[$param], $url);
61
-                } elseif ($match[4]) {
62
-                    $url = str_replace($pre . $block, '', $url);
63
-                }
64
-            }
65
-        }
66
-
67
-        return $url;
68
-    }
69
-
70
-    /**
71
-     * @param string $method
72
-     * @param string $requestMethod
73
-     * @param string $routeString
74
-     * @param string $requestUrl
75
-     *
76
-     * @return mixed
77
-     */
78
-    public function methodMatch($method, $requestMethod, $routeString, $requestUrl)
79
-    {
80
-        $methods = explode('|', $method);
81
-
82
-        if (preg_grep("/{$requestMethod}/i", $methods)) {
83
-            if ($routeString == '*') {
84
-                return true;
85
-            } elseif (isset($routeString[0]) && $routeString[0] == '@') {
86
-                return preg_match('`' . substr($routeString, 1) . '`u', $requestUrl, $this->params);
87
-            } elseif (($position = strpos($routeString, '[')) === false) {
88
-                return strcmp($requestUrl, $routeString) === 0;
89
-            }
90
-            if (strncmp($requestUrl, $routeString, $position) !== 0) {
91
-                return false;
92
-            }
93
-
94
-            return preg_match($this->compileRoute($routeString, $requestUrl), $requestUrl, $this->params);
95
-        }
96
-
97
-        return false;
98
-    }
99
-
100
-    /**
101
-     * Compile the regex for a given route (EXPENSIVE)
102
-     *
103
-     * @param $routeString
104
-     * @param $requestUrl
105
-     *
106
-     * @return string
107
-     */
108
-    private function compileRoute($routeString, $requestUrl)
109
-    {
110
-        $route = $this->getRoute($routeString, $requestUrl);
111
-
112
-        if (preg_match_all('`(/|\.|)\[([^:\]]*+)(?::([^:\]]*+))?\](\?|)`', $route, $matches, PREG_SET_ORDER)) {
113
-            $matchTypes = $this->matchTypes;
114
-            foreach ($matches as $match) {
115
-                list($block, $pre, $type, $param, $optional) = $match;
116
-                $pattern = $this->getRoutePattern($matchTypes, $pre, $type, $param, $optional);
117
-                $route = str_replace($block, $pattern, $route);
118
-            }
119
-        }
120
-
121
-        return "`^$route$`u";
122
-    }
123
-
124
-    /**
125
-     * @param $matchTypes
126
-     * @param $pre
127
-     * @param $type
128
-     * @param $param
129
-     * @param $optional
130
-     *
131
-     * @return string
132
-     */
133
-    private function getRoutePattern($matchTypes, $pre, $type, $param, $optional)
134
-    {
135
-        if (isset($matchTypes[$type])) {
136
-            $type = $matchTypes[$type];
137
-        }
138
-        if ($pre === '.') {
139
-            $pre = '\.';
140
-        }
141
-
142
-        //Older versions of PCRE require the 'P' in (?P<named>)
143
-        return '(?:'
144
-            . ($pre !== '' ? $pre : null)
145
-            . '('
146
-            . ($param !== '' ? "?P<$param>" : null)
147
-            . $type
148
-            . '))'
149
-            . ($optional !== '' ? '?' : null);
150
-    }
151
-
152
-    /**
153
-     * @param $routeString
154
-     * @param $requestUrl
155
-     *
156
-     * @return bool|string
157
-     */
158
-    private function getRoute($routeString, $requestUrl)
159
-    {
160
-        $iPointer = $jPointer = 0;
161
-        $nPointer = isset($routeString[0]) ? $routeString[0] : null;
162
-        $regex = $route = false;
163
-
164
-        // Find the longest non-regex substring and match it against the URI
165
-        while (true) {
166
-            if (!isset($routeString[$iPointer])) {
167
-                break;
168
-            }
169
-            if ($regex === false) {
170
-                if (!$this->getRouteRegexCheck($nPointer, $jPointer, $iPointer, $routeString, $requestUrl)) {
171
-                    continue;
172
-                }
173
-                $jPointer++;
174
-            }
175
-            $route .= $routeString[$iPointer++];
176
-        }
177
-
178
-        return $route;
179
-    }
180
-
181
-    /**
182
-     * @param $nPointer
183
-     * @param $jPointer
184
-     * @param $iPointer
185
-     * @param $routeString
186
-     * @param $requestUrl
187
-     *
188
-     * @return bool
189
-     */
190
-    private function getRouteRegexCheck($nPointer, $jPointer, $iPointer, $routeString, $requestUrl)
191
-    {
192
-        $cPointer = $nPointer;
193
-        $regex = in_array($cPointer, array('[', '(', '.'));
194
-        if (!$regex && isset($routeString[$iPointer+1])) {
195
-            $nPointer = $routeString[$iPointer + 1];
196
-            $regex = in_array($nPointer, array('?', '+', '*', '{'));
197
-        }
198
-        if (!$regex && $cPointer !== '/' && (!isset($requestUrl[$jPointer]) || $cPointer !== $requestUrl[$jPointer])) {
199
-            return false;
200
-        }
201
-        return true;
202
-    }
203
-
204
-    /**
205
-     * @return array
206
-     */
207
-    public function getParams()
208
-    {
209
-        return $this->params;
210
-    }
211
-
212
-    /**
213
-     * @return array
214
-     */
215
-    public function getMatchTypes()
216
-    {
217
-        return $this->matchTypes;
218
-    }
6
+	protected $params = [];
7
+	protected $matchTypes = [
8
+		'i'  => '[0-9]++',
9
+		'a'  => '[0-9A-Za-z]++',
10
+		'h'  => '[0-9A-Fa-f]++',
11
+		'*'  => '.+?',
12
+		'**' => '.++',
13
+		''   => '[^/\.]++'
14
+	];
15
+
16
+	/**
17
+	 * Create router in one call from config.
18
+	 *
19
+	 * @param array $matchTypes
20
+	 */
21
+	public function __construct($matchTypes = [])
22
+	{
23
+		$this->setMatchTypes($matchTypes);
24
+	}
25
+
26
+	/**
27
+	 * Add named match types. It uses array_merge so keys can be overwritten.
28
+	 *
29
+	 * @param array $matchTypes The key is the name and the value is the regex.
30
+	 */
31
+	public function setMatchTypes($matchTypes)
32
+	{
33
+		$this->matchTypes = array_merge($this->matchTypes, $matchTypes);
34
+	}
35
+
36
+	/**
37
+	 * Get the url from a route name
38
+	 *
39
+	 * @param string $basePath
40
+	 * @param string $route
41
+	 * @param array $params
42
+	 *
43
+	 * @return string
44
+	 */
45
+	public function generate($basePath, $route, array $params)
46
+	{
47
+		$url = $basePath . $route;
48
+
49
+		if (preg_match_all('`(/|\.|)\[([^:\]]*+)(?::([^:\]]*+))?\](\?|)`', $route, $matches, PREG_SET_ORDER)) {
50
+			foreach ($matches as $match) {
51
+				$block  = $match[0];
52
+				$pre    = $match[1];
53
+				$param  = $match[3];
54
+
55
+				if ($pre) {
56
+					$block = substr($block, 1);
57
+				}
58
+
59
+				if (isset($params[$param])) {
60
+					$url = str_replace($block, $params[$param], $url);
61
+				} elseif ($match[4]) {
62
+					$url = str_replace($pre . $block, '', $url);
63
+				}
64
+			}
65
+		}
66
+
67
+		return $url;
68
+	}
69
+
70
+	/**
71
+	 * @param string $method
72
+	 * @param string $requestMethod
73
+	 * @param string $routeString
74
+	 * @param string $requestUrl
75
+	 *
76
+	 * @return mixed
77
+	 */
78
+	public function methodMatch($method, $requestMethod, $routeString, $requestUrl)
79
+	{
80
+		$methods = explode('|', $method);
81
+
82
+		if (preg_grep("/{$requestMethod}/i", $methods)) {
83
+			if ($routeString == '*') {
84
+				return true;
85
+			} elseif (isset($routeString[0]) && $routeString[0] == '@') {
86
+				return preg_match('`' . substr($routeString, 1) . '`u', $requestUrl, $this->params);
87
+			} elseif (($position = strpos($routeString, '[')) === false) {
88
+				return strcmp($requestUrl, $routeString) === 0;
89
+			}
90
+			if (strncmp($requestUrl, $routeString, $position) !== 0) {
91
+				return false;
92
+			}
93
+
94
+			return preg_match($this->compileRoute($routeString, $requestUrl), $requestUrl, $this->params);
95
+		}
96
+
97
+		return false;
98
+	}
99
+
100
+	/**
101
+	 * Compile the regex for a given route (EXPENSIVE)
102
+	 *
103
+	 * @param $routeString
104
+	 * @param $requestUrl
105
+	 *
106
+	 * @return string
107
+	 */
108
+	private function compileRoute($routeString, $requestUrl)
109
+	{
110
+		$route = $this->getRoute($routeString, $requestUrl);
111
+
112
+		if (preg_match_all('`(/|\.|)\[([^:\]]*+)(?::([^:\]]*+))?\](\?|)`', $route, $matches, PREG_SET_ORDER)) {
113
+			$matchTypes = $this->matchTypes;
114
+			foreach ($matches as $match) {
115
+				list($block, $pre, $type, $param, $optional) = $match;
116
+				$pattern = $this->getRoutePattern($matchTypes, $pre, $type, $param, $optional);
117
+				$route = str_replace($block, $pattern, $route);
118
+			}
119
+		}
120
+
121
+		return "`^$route$`u";
122
+	}
123
+
124
+	/**
125
+	 * @param $matchTypes
126
+	 * @param $pre
127
+	 * @param $type
128
+	 * @param $param
129
+	 * @param $optional
130
+	 *
131
+	 * @return string
132
+	 */
133
+	private function getRoutePattern($matchTypes, $pre, $type, $param, $optional)
134
+	{
135
+		if (isset($matchTypes[$type])) {
136
+			$type = $matchTypes[$type];
137
+		}
138
+		if ($pre === '.') {
139
+			$pre = '\.';
140
+		}
141
+
142
+		//Older versions of PCRE require the 'P' in (?P<named>)
143
+		return '(?:'
144
+			. ($pre !== '' ? $pre : null)
145
+			. '('
146
+			. ($param !== '' ? "?P<$param>" : null)
147
+			. $type
148
+			. '))'
149
+			. ($optional !== '' ? '?' : null);
150
+	}
151
+
152
+	/**
153
+	 * @param $routeString
154
+	 * @param $requestUrl
155
+	 *
156
+	 * @return bool|string
157
+	 */
158
+	private function getRoute($routeString, $requestUrl)
159
+	{
160
+		$iPointer = $jPointer = 0;
161
+		$nPointer = isset($routeString[0]) ? $routeString[0] : null;
162
+		$regex = $route = false;
163
+
164
+		// Find the longest non-regex substring and match it against the URI
165
+		while (true) {
166
+			if (!isset($routeString[$iPointer])) {
167
+				break;
168
+			}
169
+			if ($regex === false) {
170
+				if (!$this->getRouteRegexCheck($nPointer, $jPointer, $iPointer, $routeString, $requestUrl)) {
171
+					continue;
172
+				}
173
+				$jPointer++;
174
+			}
175
+			$route .= $routeString[$iPointer++];
176
+		}
177
+
178
+		return $route;
179
+	}
180
+
181
+	/**
182
+	 * @param $nPointer
183
+	 * @param $jPointer
184
+	 * @param $iPointer
185
+	 * @param $routeString
186
+	 * @param $requestUrl
187
+	 *
188
+	 * @return bool
189
+	 */
190
+	private function getRouteRegexCheck($nPointer, $jPointer, $iPointer, $routeString, $requestUrl)
191
+	{
192
+		$cPointer = $nPointer;
193
+		$regex = in_array($cPointer, array('[', '(', '.'));
194
+		if (!$regex && isset($routeString[$iPointer+1])) {
195
+			$nPointer = $routeString[$iPointer + 1];
196
+			$regex = in_array($nPointer, array('?', '+', '*', '{'));
197
+		}
198
+		if (!$regex && $cPointer !== '/' && (!isset($requestUrl[$jPointer]) || $cPointer !== $requestUrl[$jPointer])) {
199
+			return false;
200
+		}
201
+		return true;
202
+	}
203
+
204
+	/**
205
+	 * @return array
206
+	 */
207
+	public function getParams()
208
+	{
209
+		return $this->params;
210
+	}
211
+
212
+	/**
213
+	 * @return array
214
+	 */
215
+	public function getMatchTypes()
216
+	{
217
+		return $this->matchTypes;
218
+	}
219 219
 }
Please login to merge, or discard this patch.