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 ( 19a2b9...aa694f )
by Quim
02:16
created

Router::addPattern()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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