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.
Passed
Push — master ( 5cefd1...492078 )
by Anton
04:08
created

Uri::applyParts()   C

Complexity

Conditions 9
Paths 256

Size

Total Lines 21
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 19
c 1
b 0
f 0
nc 256
nop 1
dl 0
loc 21
rs 6.5222
1
<?php
2
namespace RingCentral\Psr7;
3
4
use Psr\Http\Message\UriInterface;
5
6
/**
7
 * Basic PSR-7 URI implementation.
8
 *
9
 * @link https://github.com/phly/http This class is based upon
10
 *     Matthew Weier O'Phinney's URI implementation in phly/http.
11
 */
12
class Uri implements UriInterface
13
{
14
    private static $schemes = array(
15
        'http'  => 80,
16
        'https' => 443,
17
    );
18
19
    private static $charUnreserved = 'a-zA-Z0-9_\-\.~';
20
    private static $charSubDelims = '!\$&\'\(\)\*\+,;=';
21
    private static $replaceQuery = array('=' => '%3D', '&' => '%26');
22
23
    /** @var string Uri scheme. */
24
    private $scheme = '';
25
26
    /** @var string Uri user info. */
27
    private $userInfo = '';
28
29
    /** @var string Uri host. */
30
    private $host = '';
31
32
    /** @var int|null Uri port. */
33
    private $port;
34
35
    /** @var string Uri path. */
36
    private $path = '';
37
38
    /** @var string Uri query string. */
39
    private $query = '';
40
41
    /** @var string Uri fragment. */
42
    private $fragment = '';
43
44
    /**
45
     * @param string $uri URI to parse and wrap.
46
     */
47
    public function __construct($uri = '')
48
    {
49
        if ($uri != null) {
50
            $parts = parse_url($uri);
51
            if ($parts === false) {
52
                throw new \InvalidArgumentException("Unable to parse URI: $uri");
53
            }
54
            $this->applyParts($parts);
55
        }
56
    }
57
58
    public function __toString()
59
    {
60
        return self::createUriString(
61
            $this->scheme,
62
            $this->getAuthority(),
63
            $this->getPath(),
64
            $this->query,
65
            $this->fragment
66
        );
67
    }
68
69
    /**
70
     * Removes dot segments from a path and returns the new path.
71
     *
72
     * @param string $path
73
     *
74
     * @return string
75
     * @link http://tools.ietf.org/html/rfc3986#section-5.2.4
76
     */
77
    public static function removeDotSegments($path)
78
    {
79
        static $noopPaths = array('' => true, '/' => true, '*' => true);
80
        static $ignoreSegments = array('.' => true, '..' => true);
81
82
        if (isset($noopPaths[$path])) {
83
            return $path;
84
        }
85
86
        $results = array();
87
        $segments = explode('/', $path);
88
        foreach ($segments as $segment) {
89
            if ($segment == '..') {
90
                array_pop($results);
91
            } elseif (!isset($ignoreSegments[$segment])) {
92
                $results[] = $segment;
93
            }
94
        }
95
96
        $newPath = implode('/', $results);
97
        // Add the leading slash if necessary
98
        if (substr($path, 0, 1) === '/' &&
99
            substr($newPath, 0, 1) !== '/'
100
        ) {
101
            $newPath = '/' . $newPath;
102
        }
103
104
        // Add the trailing slash if necessary
105
        if ($newPath != '/' && isset($ignoreSegments[end($segments)])) {
106
            $newPath .= '/';
107
        }
108
109
        return $newPath;
110
    }
111
112
    /**
113
     * Resolve a base URI with a relative URI and return a new URI.
114
     *
115
     * @param UriInterface $base Base URI
116
     * @param string       $rel  Relative URI
117
     *
118
     * @return UriInterface
119
     */
120
    public static function resolve(UriInterface $base, $rel)
121
    {
122
        if ($rel === null || $rel === '') {
123
            return $base;
124
        }
125
126
        if (!($rel instanceof UriInterface)) {
0 ignored issues
show
introduced by
$rel is never a sub-type of Psr\Http\Message\UriInterface.
Loading history...
127
            $rel = new self($rel);
128
        }
129
130
        // Return the relative uri as-is if it has a scheme.
131
        if ($rel->getScheme()) {
132
            return $rel->withPath(static::removeDotSegments($rel->getPath()));
133
        }
134
135
        $relParts = array(
136
            'scheme'    => $rel->getScheme(),
137
            'authority' => $rel->getAuthority(),
138
            'path'      => $rel->getPath(),
139
            'query'     => $rel->getQuery(),
140
            'fragment'  => $rel->getFragment()
141
        );
142
143
        $parts = array(
144
            'scheme'    => $base->getScheme(),
145
            'authority' => $base->getAuthority(),
146
            'path'      => $base->getPath(),
147
            'query'     => $base->getQuery(),
148
            'fragment'  => $base->getFragment()
149
        );
150
151
        if (!empty($relParts['authority'])) {
152
            $parts['authority'] = $relParts['authority'];
153
            $parts['path'] = self::removeDotSegments($relParts['path']);
154
            $parts['query'] = $relParts['query'];
155
            $parts['fragment'] = $relParts['fragment'];
156
        } elseif (!empty($relParts['path'])) {
157
            if (substr($relParts['path'], 0, 1) == '/') {
158
                $parts['path'] = self::removeDotSegments($relParts['path']);
159
                $parts['query'] = $relParts['query'];
160
                $parts['fragment'] = $relParts['fragment'];
161
            } else {
162
                if (!empty($parts['authority']) && empty($parts['path'])) {
163
                    $mergedPath = '/';
164
                } else {
165
                    $mergedPath = substr($parts['path'], 0, strrpos($parts['path'], '/') + 1);
166
                }
167
                $parts['path'] = self::removeDotSegments($mergedPath . $relParts['path']);
168
                $parts['query'] = $relParts['query'];
169
                $parts['fragment'] = $relParts['fragment'];
170
            }
171
        } elseif (!empty($relParts['query'])) {
172
            $parts['query'] = $relParts['query'];
173
        } elseif ($relParts['fragment'] != null) {
174
            $parts['fragment'] = $relParts['fragment'];
175
        }
176
177
        return new self(static::createUriString(
178
            $parts['scheme'],
179
            $parts['authority'],
180
            $parts['path'],
181
            $parts['query'],
182
            $parts['fragment']
183
        ));
184
    }
185
186
    /**
187
     * Create a new URI with a specific query string value removed.
188
     *
189
     * Any existing query string values that exactly match the provided key are
190
     * removed.
191
     *
192
     * Note: this function will convert "=" to "%3D" and "&" to "%26".
193
     *
194
     * @param UriInterface $uri URI to use as a base.
195
     * @param string       $key Query string key value pair to remove.
196
     *
197
     * @return UriInterface
198
     */
199
    public static function withoutQueryValue(UriInterface $uri, $key)
200
    {
201
        $current = $uri->getQuery();
202
        if (!$current) {
203
            return $uri;
204
        }
205
206
        $result = array();
207
        foreach (explode('&', $current) as $part) {
208
            $subParts = explode('=', $part);
209
            if ($subParts[0] !== $key) {
210
                $result[] = $part;
211
            };
212
        }
213
214
        return $uri->withQuery(implode('&', $result));
215
    }
216
217
    /**
218
     * Create a new URI with a specific query string value.
219
     *
220
     * Any existing query string values that exactly match the provided key are
221
     * removed and replaced with the given key value pair.
222
     *
223
     * Note: this function will convert "=" to "%3D" and "&" to "%26".
224
     *
225
     * @param UriInterface $uri URI to use as a base.
226
     * @param string $key   Key to set.
227
     * @param string $value Value to set.
228
     *
229
     * @return UriInterface
230
     */
231
    public static function withQueryValue(UriInterface $uri, $key, $value)
232
    {
233
        $current = $uri->getQuery();
234
        $key = strtr($key, self::$replaceQuery);
235
236
        if (!$current) {
237
            $result = array();
238
        } else {
239
            $result = array();
240
            foreach (explode('&', $current) as $part) {
241
                $subParts = explode('=', $part);
242
                if ($subParts[0] !== $key) {
243
                    $result[] = $part;
244
                };
245
            }
246
        }
247
248
        if ($value !== null) {
0 ignored issues
show
introduced by
The condition $value !== null is always true.
Loading history...
249
            $result[] = $key . '=' . strtr($value, self::$replaceQuery);
250
        } else {
251
            $result[] = $key;
252
        }
253
254
        return $uri->withQuery(implode('&', $result));
255
    }
256
257
    /**
258
     * Create a URI from a hash of parse_url parts.
259
     *
260
     * @param array $parts
261
     *
262
     * @return self
263
     */
264
    public static function fromParts(array $parts)
265
    {
266
        $uri = new self();
267
        $uri->applyParts($parts);
268
        return $uri;
269
    }
270
271
    public function getScheme()
272
    {
273
        return $this->scheme;
274
    }
275
276
    public function getAuthority()
277
    {
278
        if (empty($this->host)) {
279
            return '';
280
        }
281
282
        $authority = $this->host;
283
        if (!empty($this->userInfo)) {
284
            $authority = $this->userInfo . '@' . $authority;
285
        }
286
287
        if ($this->isNonStandardPort($this->scheme, $this->host, $this->port)) {
288
            $authority .= ':' . $this->port;
289
        }
290
291
        return $authority;
292
    }
293
294
    public function getUserInfo()
295
    {
296
        return $this->userInfo;
297
    }
298
299
    public function getHost()
300
    {
301
        return $this->host;
302
    }
303
304
    public function getPort()
305
    {
306
        return $this->port;
307
    }
308
309
    public function getPath()
310
    {
311
        return $this->path == null ? '' : $this->path;
312
    }
313
314
    public function getQuery()
315
    {
316
        return $this->query;
317
    }
318
319
    public function getFragment()
320
    {
321
        return $this->fragment;
322
    }
323
324
    public function withScheme($scheme)
325
    {
326
        $scheme = $this->filterScheme($scheme);
327
328
        if ($this->scheme === $scheme) {
329
            return $this;
330
        }
331
332
        $new = clone $this;
333
        $new->scheme = $scheme;
334
        $new->port = $new->filterPort($new->scheme, $new->host, $new->port);
335
        return $new;
336
    }
337
338
    public function withUserInfo($user, $password = null)
339
    {
340
        $info = $user;
341
        if ($password) {
342
            $info .= ':' . $password;
343
        }
344
345
        if ($this->userInfo === $info) {
346
            return $this;
347
        }
348
349
        $new = clone $this;
350
        $new->userInfo = $info;
351
        return $new;
352
    }
353
354
    public function withHost($host)
355
    {
356
        if ($this->host === $host) {
357
            return $this;
358
        }
359
360
        $new = clone $this;
361
        $new->host = $host;
362
        return $new;
363
    }
364
365
    public function withPort($port)
366
    {
367
        $port = $this->filterPort($this->scheme, $this->host, $port);
368
369
        if ($this->port === $port) {
370
            return $this;
371
        }
372
373
        $new = clone $this;
374
        $new->port = $port;
375
        return $new;
376
    }
377
378
    public function withPath($path)
379
    {
380
        if (!is_string($path)) {
381
            throw new \InvalidArgumentException(
382
                'Invalid path provided; must be a string'
383
            );
384
        }
385
386
        $path = $this->filterPath($path);
387
388
        if ($this->path === $path) {
389
            return $this;
390
        }
391
392
        $new = clone $this;
393
        $new->path = $path;
394
        return $new;
395
    }
396
397
    public function withQuery($query)
398
    {
399
        if (!is_string($query) && !method_exists($query, '__toString')) {
400
            throw new \InvalidArgumentException(
401
                'Query string must be a string'
402
            );
403
        }
404
405
        $query = (string) $query;
406
        if (substr($query, 0, 1) === '?') {
407
            $query = substr($query, 1);
408
        }
409
410
        $query = $this->filterQueryAndFragment($query);
411
412
        if ($this->query === $query) {
413
            return $this;
414
        }
415
416
        $new = clone $this;
417
        $new->query = $query;
418
        return $new;
419
    }
420
421
    public function withFragment($fragment)
422
    {
423
        if (substr($fragment, 0, 1) === '#') {
424
            $fragment = substr($fragment, 1);
425
        }
426
427
        $fragment = $this->filterQueryAndFragment($fragment);
428
429
        if ($this->fragment === $fragment) {
430
            return $this;
431
        }
432
433
        $new = clone $this;
434
        $new->fragment = $fragment;
435
        return $new;
436
    }
437
438
    /**
439
     * Apply parse_url parts to a URI.
440
     *
441
     * @param $parts Array of parse_url parts to apply.
442
     */
443
    private function applyParts(array $parts)
444
    {
445
        $this->scheme = isset($parts['scheme'])
446
            ? $this->filterScheme($parts['scheme'])
447
            : '';
448
        $this->userInfo = isset($parts['user']) ? $parts['user'] : '';
449
        $this->host = isset($parts['host']) ? $parts['host'] : '';
450
        $this->port = !empty($parts['port'])
451
            ? $this->filterPort($this->scheme, $this->host, $parts['port'])
452
            : null;
453
        $this->path = isset($parts['path'])
454
            ? $this->filterPath($parts['path'])
455
            : '';
456
        $this->query = isset($parts['query'])
457
            ? $this->filterQueryAndFragment($parts['query'])
458
            : '';
459
        $this->fragment = isset($parts['fragment'])
460
            ? $this->filterQueryAndFragment($parts['fragment'])
461
            : '';
462
        if (isset($parts['pass'])) {
463
            $this->userInfo .= ':' . $parts['pass'];
464
        }
465
    }
466
467
    /**
468
     * Create a URI string from its various parts
469
     *
470
     * @param string $scheme
471
     * @param string $authority
472
     * @param string $path
473
     * @param string $query
474
     * @param string $fragment
475
     * @return string
476
     */
477
    private static function createUriString($scheme, $authority, $path, $query, $fragment)
478
    {
479
        $uri = '';
480
481
        if (!empty($scheme)) {
482
            $uri .= $scheme . '://';
483
        }
484
485
        if (!empty($authority)) {
486
            $uri .= $authority;
487
        }
488
489
        if ($path != null) {
490
            // Add a leading slash if necessary.
491
            if ($uri && substr($path, 0, 1) !== '/') {
492
                $uri .= '/';
493
            }
494
            $uri .= $path;
495
        }
496
497
        if ($query != null) {
498
            $uri .= '?' . $query;
499
        }
500
501
        if ($fragment != null) {
502
            $uri .= '#' . $fragment;
503
        }
504
505
        return $uri;
506
    }
507
508
    /**
509
     * Is a given port non-standard for the current scheme?
510
     *
511
     * @param string $scheme
512
     * @param string $host
513
     * @param int $port
514
     * @return bool
515
     */
516
    private static function isNonStandardPort($scheme, $host, $port)
517
    {
518
        if (!$scheme && $port) {
519
            return true;
520
        }
521
522
        if (!$host || !$port) {
523
            return false;
524
        }
525
526
        return !isset(static::$schemes[$scheme]) || $port !== static::$schemes[$scheme];
0 ignored issues
show
Bug introduced by
Since $schemes is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $schemes to at least protected.
Loading history...
527
    }
528
529
    /**
530
     * @param string $scheme
531
     *
532
     * @return string
533
     */
534
    private function filterScheme($scheme)
535
    {
536
        $scheme = strtolower($scheme);
537
        $scheme = rtrim($scheme, ':/');
538
539
        return $scheme;
540
    }
541
542
    /**
543
     * @param string $scheme
544
     * @param string $host
545
     * @param int $port
546
     *
547
     * @return int|null
548
     *
549
     * @throws \InvalidArgumentException If the port is invalid.
550
     */
551
    private function filterPort($scheme, $host, $port)
552
    {
553
        if (null !== $port) {
0 ignored issues
show
introduced by
The condition null !== $port is always true.
Loading history...
554
            $port = (int) $port;
555
            if (1 > $port || 0xffff < $port) {
556
                throw new \InvalidArgumentException(
557
                    sprintf('Invalid port: %d. Must be between 1 and 65535', $port)
558
                );
559
            }
560
        }
561
562
        return $this->isNonStandardPort($scheme, $host, $port) ? $port : null;
563
    }
564
565
    /**
566
     * Filters the path of a URI
567
     *
568
     * @param $path
569
     *
570
     * @return string
571
     */
572
    private function filterPath($path)
573
    {
574
        return preg_replace_callback(
575
            '/(?:[^' . self::$charUnreserved . self::$charSubDelims . ':@\/%]+|%(?![A-Fa-f0-9]{2}))/',
576
            array($this, 'rawurlencodeMatchZero'),
577
            $path
578
        );
579
    }
580
581
    /**
582
     * Filters the query string or fragment of a URI.
583
     *
584
     * @param $str
585
     *
586
     * @return string
587
     */
588
    private function filterQueryAndFragment($str)
589
    {
590
        return preg_replace_callback(
591
            '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/',
592
            array($this, 'rawurlencodeMatchZero'),
593
            $str
594
        );
595
    }
596
597
    private function rawurlencodeMatchZero(array $match)
598
    {
599
        return rawurlencode($match[0]);
600
    }
601
}
602