GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 5c5c4b...19a2b9 )
by Quim
02:25
created

Router::__construct()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 10
ccs 8
cts 8
cp 1
rs 9.4286
cc 3
eloc 6
nc 3
nop 1
crap 3
1
<?php
2
namespace QuimCalpe\Router;
3
4
use QuimCalpe\Router\Route\Route;
5
use QuimCalpe\Router\Route\ParsedRoute;
6
use QuimCalpe\Router\Exception\MethodNotAllowedException;
7
use QuimCalpe\Router\Exception\RouteNotFoundException;
8
9
class Router
10
{
11
    private $trailing_slash_check = true;
12
    private $routes = [];
13
    private $route_names = [];
14
    private $regexp_map = [
15
        '/\{([A-Za-z]\w*)\}/' => '(?<$1>[^/]+)',
16
        '/\{([A-Za-z]\w*):word\}/' => '(?<$1>\w+)',
17
        '/\{([A-Za-z]\w*):number\}/' => '(?<$1>\d+)',
18
        '/\{([A-Za-z]\w*):slug\}/' => '(?<$1>[A-Za-z0-9_-]+)',
19
        '/\{([A-Za-z]\w*):([^}]+)\}/' => '(?<$1>$2)',
20
        '/\//' => '\/'
21
    ];
22
    private static $parsed_regexp = []; // cache
23
24
    /**
25
     * Creates a new Router.
26
     *
27
     * @param Route[] $routes
28
     *      (Optional) Array of Route value objects to create.
29
     *
30
     * @throws \RunTimeException
31
     *      Thrown if array not contains Router instances.
32
     */
33 20
    public function __construct(array $routes = [])
34
    {
35 20
        foreach ($routes as $uri => $route) {
36 9
            if ($route instanceof Route) {
37 8
                $this->add($route);
38 8
            } else {
39 1
                throw new \RunTimeException("An array of QuimCalpe\Router\Route\Route instances is required since 1.0.0");
40
            }
41 19
        }
42 19
    }
43
44
    /**
45
     * Registers a route.
46
     *
47
     * @param Route $route
48
     *      Route Value Object.
49
     */
50 9
    public function add(Route $route)
51
    {
52 9
        $this->addRoute($route->methods(), $route->uri(), $route->handler(), $route->name());
53 9
    }
54
55
    /**
56
     * Registers a route.
57
     *
58
     * @param string|array $methods
59
     *      Either a single HTTP verb, or an array of verbs.
60
     * @param string $uri
61
     *      URI pattern to match for this route.
62
     * @param string $handler
63
     *      ClassName::methodName to invoke for this route. If methodName
64
     *      is not present, a method of 'index' is assumed.
65
     * @param string $name
66
     *      (Optional) An unique name for this route.
67
     */
68 19
    public function addRoute($methods, $uri, $handler, $name = null)
69
    {
70 19
        if (is_string($name) && trim($name) !== "") {
71 2
            $this->route_names[$name] = $uri;
72 2
        }
73 19
        foreach ((array)$methods as $method) {
74 19
            $method = strtoupper($method);
75 19
            if (!isset($this->routes[$method])) {
76 19
                $this->routes[$method] = [];
77 19
            }
78 19
            $this->routes[$method][$uri] = $handler;
79 19
        }
80 19
    }
81
82
    /**
83
     * Syntactic sugar: registers a HEAD route.
84
     *
85
     * @param string $uri
86
     * @param string $handler
87
     * @param string $name
88
     *      (Optional) An unique name for this route.
89
     */
90 1
    public function addHead($uri, $handler, $name = null)
91
    {
92 1
        $this->addRoute("HEAD", $uri, $handler, $name);
93 1
    }
94
95
    /**
96
     * Syntactic sugar: registers a GET route.
97
     *
98
     * @param string $uri
99
     * @param string $handler
100
     * @param string $name
101
     *      (Optional) An unique name for this route.
102
     */
103 1
    public function addGet($uri, $handler, $name = null)
104
    {
105 1
        $this->addRoute("GET", $uri, $handler, $name);
106 1
    }
107
108
    /**
109
     * Syntactic sugar: registers a DELETE route.
110
     *
111
     * @param string $uri
112
     * @param string $handler
113
     * @param string $name
114
     *      (Optional) An unique name for this route.
115
     */
116 1
    public function addDelete($uri, $handler, $name = null)
117
    {
118 1
        $this->addRoute("DELETE", $uri, $handler, $name);
119 1
    }
120
121
    /**
122
     * Syntactic sugar: registers an OPTIONS route.
123
     *
124
     * @param string $uri
125
     * @param string $handler
126
     * @param string $name
127
     *      (Optional) An unique name for this route.
128
     */
129 1
    public function addOptions($uri, $handler, $name = null)
130
    {
131 1
        $this->addRoute("OPTIONS", $uri, $handler, $name);
132 1
    }
133
134
    /**
135
     * Syntactic sugar: registers a PATCH route.
136
     *
137
     * @param string $uri
138
     * @param string $handler
139
     * @param string $name
140
     *      (Optional) An unique name for this route.
141
     */
142 1
    public function addPatch($uri, $handler, $name = null)
143
    {
144 1
        $this->addRoute("PATCH", $uri, $handler, $name);
145 1
    }
146
147
    /**
148
     * Syntactic sugar: registers a POST route.
149
     *
150
     * @param string $uri
151
     * @param string $handler
152
     * @param string $name
153
     *      (Optional) An unique name for this route.
154
     */
155 1
    public function addPost($uri, $handler, $name = null)
156
    {
157 1
        $this->addRoute("POST", $uri, $handler, $name);
158 1
    }
159
160
    /**
161
     * Syntactic sugar: registers a PUT route.
162
     *
163
     * @param string $uri
164
     * @param string $handler
165
     * @param string $name
166
     *      (Optional) An unique name for this route.
167
     */
168 1
    public function addPut($uri, $handler, $name = null)
169
    {
170 1
        $this->addRoute("PUT", $uri, $handler, $name);
171 1
    }
172
173
    /**
174
     * Disables distinguishing an extra slash on the end of incoming URIs as a
175
     * different URL.
176
     */
177 1
    public function disableTrailingSlashCheck()
178
    {
179 1
        $this->trailing_slash_check = false;
180 1
    }
181
182
    /**
183
     * Registers a matching pattern for URI parameters.
184
     *
185
     * @param string $name
186
     *      Name which will appear within curly-braces in URI patterns.
187
     * @param string $regexp
188
     *      Regexp substitution pattern.
189
     */
190 1
    public function addPattern($name, $regexp)
191
    {
192 1
        $this->regexp_map = ['/\{(\w+):'.$name.'\}/' => '(?<$1>'.$regexp.')'] + $this->regexp_map;
193 1
    }
194
195
    /**
196
     * Finds the uri associated with a given name.
197
     *
198
     * @param string $name
199
     *      Name of the route to find.
200
     * @param array $parameters
201
     *      (Optional) Parameters to complete the URI.
202
     *
203
     * @return string|null
204
     */
205 2
    public function findURI($name, $parameters = [])
206
    {
207 2
        if (array_key_exists($name, $this->route_names)) {
208 2
            $foundUri = $this->route_names[$name];
209
            // insert provided parameters on his slot
210 2
            foreach ($parameters as $parameter => $value) {
211 1
                $foundUri = preg_replace("/\{(".$parameter.")(\:\w+)?\}/i", $value, $foundUri);
212 2
            }
213 2
            return $foundUri;
214
        }
215 1
    }
216
217
    /**
218
     * Parses an incoming method and URI, and returns a matching route.
219
     *
220
     * @param string $method
221
     *      HTTP verb to find a match on.
222
     * @param string $uri
223
     *      URI pattern to find a match on.
224
     * @param string $prefix
225
     *      (Optional) Prefix to prepend to URI path.
226
     *
227
     * @return ParsedRoute
228
     *
229
     * @throws MethodNotAllowedException
230
     *      Thrown if a handler is registered for this route, but it is not
231
     *      configured to handle this verb.
232
     * @throws RouteNotFoundException
233
     *      Thrown if there is no handler registered for this route.
234
     */
235 17
    public function parse($method, $uri, $prefix = "")
236
    {
237 17
        $uri = trim(explode("?", $uri)[0]);
238 17
        if ($prefix !== "" && substr($prefix, 0, 1) !== "/") {
239 1
            $prefix = "/".$prefix;
240 1
        }
241
        try {
242 17
            return $this->findMatches($method, $uri, $prefix);
243 4
        } catch (RouteNotFoundException $e) {
244 4
            $allowed_methods = [];
245 4
            foreach ($this->routes as $available_method => $routes) {
246
                try {
247 4
                    $this->findMatches($available_method, $uri, $prefix);
248 1
                    $allowed_methods[] = $available_method;
249 4
                } catch (RouteNotFoundException $e) {
250
                    // not found, skip
251
                }
252 4
            }
253 4
            if (count($allowed_methods)) {
254 1
                throw new MethodNotAllowedException(implode(", ", $allowed_methods));
255
            } else {
256 3
                throw new RouteNotFoundException("No route for '{$uri}' found");
257
            }
258
        }
259
    }
260
261
    /**
262
     * Finds the first matching route for a given method and URI.
263
     *
264
     * @param string $method
265
     *      HTTP verb to find a match on.
266
     * @param string $uri
267
     *      URI pattern to find a match on.
268
     * @param string $prefix
269
     *      (Optional) Prefix to prepend to URI path.
270
     *
271
     * @return ParsedRoute
272
     *
273
     * @throws RouteNotFoundException
274
     */
275 17
    private function findMatches($method, $uri, $prefix = "")
276
    {
277 17
        if (isset($this->routes[strtoupper($method)])) {
278 17
            foreach (array_keys($this->routes[strtoupper($method)]) as $route) {
279 17
                $parsed_regexp = $this->prepareRouteRegexp($prefix.$route);
280 17
                if (preg_match_all("/^".$parsed_regexp.($this->trailing_slash_check ? "" : "\/?")."$/i", $uri, $matches, PREG_SET_ORDER)) {
281 14
                    if (count($matches)) {
282 14
                        $matches = array_diff_key($matches[0], range(0, count($matches[0])));
283 14
                    }
284 14
                    return new ParsedRoute($this->routes[strtoupper($method)][$route], $matches);
285
                }
286 10
            }
287 4
        }
288 4
        throw new RouteNotFoundException("No route for '{$uri}' found");
289
    }
290
291
    /**
292
     * Applies standard regexp patterns to an incoming URI route.
293
     *
294
     * @param string $route
295
     *
296
     * @return string
297
     */
298 17
    private function prepareRouteRegexp($route)
299
    {
300 17
        if (!array_key_exists($route, self::$parsed_regexp)) {
301 5
            self::$parsed_regexp[$route] = preg_replace(array_keys($this->regexp_map), array_values($this->regexp_map), $route);
302 5
        }
303 17
        return self::$parsed_regexp[$route];
304
    }
305
}
306