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
Pull Request — 3.x (#2242)
by
unknown
02:43
created

Router::setContainer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
/**
3
 * Slim Framework (https://slimframework.com)
4
 *
5
 * @link      https://github.com/slimphp/Slim
6
 * @copyright Copyright (c) 2011-2017 Josh Lockhart
7
 * @license   https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License)
8
 */
9
namespace Slim;
10
11
use FastRoute\Dispatcher;
12
use Psr\Container\ContainerInterface;
13
use InvalidArgumentException;
14
use RuntimeException;
15
use Psr\Http\Message\ServerRequestInterface;
16
use FastRoute\RouteCollector;
17
use FastRoute\RouteParser;
18
use FastRoute\RouteParser\Std as StdParser;
19
use Slim\Interfaces\RouteGroupInterface;
20
use Slim\Interfaces\RouterInterface;
21
use Slim\Interfaces\RouteInterface;
22
23
/**
24
 * Router
25
 *
26
 * This class organizes Slim application route objects. It is responsible
27
 * for registering route objects, assigning names to route objects,
28
 * finding routes that match the current HTTP request, and creating
29
 * URLs for a named route.
30
 */
31
class Router implements RouterInterface
32
{
33
    use ContainerAwareTrait;
34
35
    /**
36
     * Parser
37
     *
38
     * @var \FastRoute\RouteParser
39
     */
40
    protected $routeParser;
41
42
    /**
43
     * Base path used in pathFor()
44
     *
45
     * @var string
46
     */
47
    protected $basePath = '';
48
49
    /**
50
     * Path to fast route cache file. Set to false to disable route caching
51
     *
52
     * @var string|False
53
     */
54
    protected $cacheFile = false;
55
56
    /**
57
     * Routes
58
     *
59
     * @var Route[]
60
     */
61
    protected $routes = [];
62
63
    /**
64
     * Route counter incrementer
65
     * @var int
66
     */
67
    protected $routeCounter = 0;
68
69
    /**
70
     * Route groups
71
     *
72
     * @var RouteGroup[]
73
     */
74
    protected $routeGroups = [];
75
76
    /**
77
     * @var \FastRoute\Dispatcher
78
     */
79
    protected $dispatcher;
80
81
    /**
82
     * Create new router
83
     *
84
     * @param RouteParser   $parser
85
     */
86
    public function __construct(RouteParser $parser = null)
87
    {
88
        $this->routeParser = $parser ?: new StdParser;
89
    }
90
91
    /**
92
     * Set the base path used in pathFor()
93
     *
94
     * @param string $basePath
95
     *
96
     * @return self
97
     */
98
    public function setBasePath($basePath)
99
    {
100
        if (!is_string($basePath)) {
101
            throw new InvalidArgumentException('Router basePath must be a string');
102
        }
103
104
        $this->basePath = $basePath;
105
106
        return $this;
107
    }
108
109
    /**
110
     * Set path to fast route cache file. If this is false then route caching is disabled.
111
     *
112
     * @param string|false $cacheFile
113
     *
114
     * @return self
115
     */
116
    public function setCacheFile($cacheFile)
117
    {
118
        if (!is_string($cacheFile) && $cacheFile !== false) {
119
            throw new InvalidArgumentException('Router cacheFile must be a string or false');
120
        }
121
122
        $this->cacheFile = $cacheFile;
123
124
        if ($cacheFile !== false && !is_writable(dirname($cacheFile))) {
125
            throw new RuntimeException('Router cacheFile directory must be writable');
126
        }
127
128
129
        return $this;
130
    }
131
132
    /**
133
     * Add route
134
     *
135
     * @param  string[] $methods Array of HTTP methods
136
     * @param  string   $pattern The route pattern
137
     * @param  callable $handler The route callable
138
     *
139
     * @return RouteInterface
140
     *
141
     * @throws InvalidArgumentException if the route pattern isn't a string
142
     */
143
    public function map($methods, $pattern, $handler)
144
    {
145
        if (!is_string($pattern)) {
146
            throw new InvalidArgumentException('Route pattern must be a string');
147
        }
148
149
        // Prepend parent group pattern(s)
150
        if ($this->routeGroups) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->routeGroups of type Slim\RouteGroup[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
151
            $pattern = $this->processGroups() . $pattern;
152
        }
153
154
        // According to RFC methods are defined in uppercase (See RFC 7231)
155
        $methods = array_map("strtoupper", $methods);
156
157
        // Add route
158
        $route = $this->createRoute($methods, $pattern, $handler);
159
        $this->routes[$route->getIdentifier()] = $route;
160
        $this->routeCounter++;
161
162
        return $route;
163
    }
164
165
    /**
166
     * Dispatch router for HTTP request
167
     *
168
     * @param  ServerRequestInterface $request The current HTTP request object
169
     *
170
     * @return array
171
     *
172
     * @link   https://github.com/nikic/FastRoute/blob/master/src/Dispatcher.php
173
     */
174
    public function dispatch(ServerRequestInterface $request)
175
    {
176
        $uri = '/' . ltrim($request->getUri()->getPath(), '/');
177
178
        return $this->createDispatcher()->dispatch(
179
            $request->getMethod(),
180
            $uri
181
        );
182
    }
183
184
    /**
185
     * Create a new Route object
186
     *
187
     * @param  string[] $methods Array of HTTP methods
188
     * @param  string   $pattern The route pattern
189
     * @param  callable $callable The route callable
190
     *
191
     * @return \Slim\Interfaces\RouteInterface
192
     */
193
    protected function createRoute($methods, $pattern, $callable)
194
    {
195
        $route = new Route($methods, $pattern, $callable, $this->routeGroups, $this->routeCounter);
196
        if (!empty($this->container)) {
197
            $route->setContainer($this->getContainer());
198
        }
199
200
        return $route;
201
    }
202
203
    /**
204
     * @return \FastRoute\Dispatcher
205
     */
206
    protected function createDispatcher()
207
    {
208
        if ($this->dispatcher) {
209
            return $this->dispatcher;
210
        }
211
212
        $routeDefinitionCallback = function (RouteCollector $r) {
213
            foreach ($this->getRoutes() as $route) {
214
                $r->addRoute($route->getMethods(), $route->getPattern(), $route->getIdentifier());
215
            }
216
        };
217
218
        if ($this->cacheFile) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cacheFile of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
219
            $this->dispatcher = \FastRoute\cachedDispatcher($routeDefinitionCallback, [
220
                'routeParser' => $this->routeParser,
221
                'cacheFile' => $this->cacheFile,
222
            ]);
223
        } else {
224
            $this->dispatcher = \FastRoute\simpleDispatcher($routeDefinitionCallback, [
225
                'routeParser' => $this->routeParser,
226
            ]);
227
        }
228
229
        return $this->dispatcher;
230
    }
231
232
    /**
233
     * @param \FastRoute\Dispatcher $dispatcher
234
     */
235
    public function setDispatcher(Dispatcher $dispatcher)
236
    {
237
        $this->dispatcher = $dispatcher;
238
    }
239
240
    /**
241
     * Get route objects
242
     *
243
     * @return Route[]
244
     */
245
    public function getRoutes()
246
    {
247
        return $this->routes;
248
    }
249
250
    /**
251
     * Get named route object
252
     *
253
     * @param string $name        Route name
254
     *
255
     * @return Route
256
     *
257
     * @throws RuntimeException   If named route does not exist
258
     */
259
    public function getNamedRoute($name)
260
    {
261
        foreach ($this->routes as $route) {
262
            if ($name == $route->getName()) {
263
                return $route;
264
            }
265
        }
266
        throw new RuntimeException('Named route does not exist for name: ' . $name);
267
    }
268
269
    /**
270
     * Remove named route
271
     *
272
     * @param string $name        Route name
273
     *
274
     * @throws RuntimeException   If named route does not exist
275
     */
276
    public function removeNamedRoute($name)
277
    {
278
        $route = $this->getNamedRoute($name);
279
280
        // no exception, route exists, now remove by id
281
        unset($this->routes[$route->getIdentifier()]);
282
    }
283
284
    /**
285
     * Process route groups
286
     *
287
     * @return string A group pattern to prefix routes with
288
     */
289
    protected function processGroups()
290
    {
291
        $pattern = "";
292
        foreach ($this->routeGroups as $group) {
293
            $pattern .= $group->getPattern();
294
        }
295
        return $pattern;
296
    }
297
298
    /**
299
     * Add a route group to the array
300
     *
301
     * @param string   $pattern
302
     * @param callable $callable
303
     *
304
     * @return RouteGroupInterface
305
     */
306
    public function pushGroup($pattern, $callable)
307
    {
308
        $group = new RouteGroup($pattern, $callable);
309
        array_push($this->routeGroups, $group);
310
        return $group;
311
    }
312
313
    /**
314
     * Removes the last route group from the array
315
     *
316
     * @return RouteGroup|bool The RouteGroup if successful, else False
317
     */
318
    public function popGroup()
319
    {
320
        $group = array_pop($this->routeGroups);
321
        return $group instanceof RouteGroup ? $group : false;
0 ignored issues
show
Bug Compatibility introduced by
The expression $group instanceof \Slim\...Group ? $group : false; of type Slim\RouteGroup|false adds the type Slim\RouteGroup to the return on line 321 which is incompatible with the return type declared by the interface Slim\Interfaces\RouterInterface::popGroup of type boolean.
Loading history...
322
    }
323
324
    /**
325
     * @param $identifier
326
     * @return \Slim\Interfaces\RouteInterface
327
     */
328
    public function lookupRoute($identifier)
329
    {
330
        if (!isset($this->routes[$identifier])) {
331
            throw new RuntimeException('Route not found, looks like your route cache is stale.');
332
        }
333
        return $this->routes[$identifier];
334
    }
335
336
    /**
337
     * Build the path for a named route excluding the base path
338
     *
339
     * @param string $name        Route name
340
     * @param array  $data        Named argument replacement data
341
     * @param array  $queryParams Optional query string parameters
342
     *
343
     * @return string
344
     *
345
     * @throws RuntimeException         If named route does not exist
346
     * @throws InvalidArgumentException If required data not provided
347
     */
348
    public function relativePathFor($name, array $data = [], array $queryParams = [])
349
    {
350
        $route = $this->getNamedRoute($name);
351
        $pattern = $route->getPattern();
352
353
        $routeDatas = $this->routeParser->parse($pattern);
354
        // $routeDatas is an array of all possible routes that can be made. There is
355
        // one routedata for each optional parameter plus one for no optional parameters.
356
        //
357
        // The most specific is last, so we look for that first.
358
        $routeDatas = array_reverse($routeDatas);
359
360
        $segments = [];
361
        foreach ($routeDatas as $routeData) {
362
            foreach ($routeData as $item) {
363
                if (is_string($item)) {
364
                    // this segment is a static string
365
                    $segments[] = $item;
366
                    continue;
367
                }
368
369
                // This segment has a parameter: first element is the name
370
                if (!array_key_exists($item[0], $data)) {
371
                    // we don't have a data element for this segment: cancel
372
                    // testing this routeData item, so that we can try a less
373
                    // specific routeData item.
374
                    $segments = [];
375
                    $segmentName = $item[0];
376
                    break;
377
                }
378
                $segments[] = $data[$item[0]];
379
            }
380
            if (!empty($segments)) {
381
                // we found all the parameters for this route data, no need to check
382
                // less specific ones
383
                break;
384
            }
385
        }
386
387
        if (empty($segments)) {
388
            throw new InvalidArgumentException('Missing data for URL segment: ' . $segmentName);
389
        }
390
        $url = implode('', $segments);
391
392
        if ($queryParams) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $queryParams of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
393
            $url .= '?' . http_build_query($queryParams);
394
        }
395
396
        return $url;
397
    }
398
399
400
    /**
401
     * Build the path for a named route including the base path
402
     *
403
     * @param string $name        Route name
404
     * @param array  $data        Named argument replacement data
405
     * @param array  $queryParams Optional query string parameters
406
     *
407
     * @return string
408
     *
409
     * @throws RuntimeException         If named route does not exist
410
     * @throws InvalidArgumentException If required data not provided
411
     */
412
    public function pathFor($name, array $data = [], array $queryParams = [])
413
    {
414
        $url = $this->relativePathFor($name, $data, $queryParams);
415
416
        if ($this->basePath) {
417
            $url = $this->basePath . $url;
418
        }
419
420
        return $url;
421
    }
422
423
    /**
424
     * Build the path for a named route.
425
     *
426
     * This method is deprecated. Use pathFor() from now on.
427
     *
428
     * @param string $name        Route name
429
     * @param array  $data        Named argument replacement data
430
     * @param array  $queryParams Optional query string parameters
431
     *
432
     * @return string
433
     *
434
     * @throws RuntimeException         If named route does not exist
435
     * @throws InvalidArgumentException If required data not provided
436
     */
437
    public function urlFor($name, array $data = [], array $queryParams = [])
438
    {
439
        trigger_error('urlFor() is deprecated. Use pathFor() instead.', E_USER_DEPRECATED);
440
        return $this->pathFor($name, $data, $queryParams);
441
    }
442
}
443