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 ( d3a8d3...1b7f44 )
by Quim
02:43
created

Router::addRouteProvider()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

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