Completed
Branch master (016f5c)
by Nico
02:23 queued 01:03
created

URL   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 84
Duplicated Lines 0 %

Test Coverage

Coverage 25.71%

Importance

Changes 0
Metric Value
wmc 17
eloc 33
dl 0
loc 84
c 0
b 0
f 0
ccs 9
cts 35
cp 0.2571
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 2
A port() 0 7 3
A isHttps() 0 3 1
A scheme() 0 3 1
A isValid() 0 13 3
A query() 0 3 1
A path() 0 3 1
A redirectTo() 0 13 4
A host() 0 3 1
1
<?php declare(strict_types=1);
2
3
/**
4
 * @license  http://opensource.org/licenses/mit-license.php MIT
5
 * @link     https://github.com/nicoSWD
6
 * @author   Nicolas Oelgart <[email protected]>
7
 */
8
namespace nicoSWD\SecHeaderCheck\Domain\URL;
9
10
use nicoSWD\SecHeaderCheck\Domain\Header\HttpHeader;
11
12
final class URL
13
{
14
    private const SCHEME_HTTPS = 'https';
15
    private const SCHEME_HTTP = 'http';
16
17
    private const ALLOWED_PROTOCOLS = [
18
        self::SCHEME_HTTP,
19
        self::SCHEME_HTTPS,
20
    ];
21
22
    private $url = '';
23
    private $components = [];
24
25 2
    public function __construct(string $url)
26
    {
27 2
        if (!$this->isValid($url)) {
28
            throw new Exception\InvalidUrlException();
29
        }
30
31 2
        $this->url = $url;
32 2
    }
33
34
    public function scheme(): string
35
    {
36
        return $this->components['scheme'];
37
    }
38
39
    public function isHttps(): bool
40
    {
41
        return $this->scheme() === self::SCHEME_HTTPS;
42
    }
43
44
    public function host(): string
45
    {
46
        return $this->components['host'];
47
    }
48
49
    public function path(): string
50
    {
51
        return $this->components['path'] ?? '/';
52
    }
53
54
    public function query(): string
55
    {
56
        return $this->components['query'] ?? '';
57
    }
58
59
    public function port(): int
60
    {
61
        if (empty($this->components['port'])) {
62
            return $this->scheme() === self::SCHEME_HTTPS ? 443 : 80;
63
        }
64
65
        return (int) $this->components['port'];
66
    }
67
68
    public function redirectTo(HttpHeader $locationHeader): self
69
    {
70
        $newLocation = $locationHeader->value();
71
72
        if (substr($newLocation, 0, 2) === '//') {
73
            $newLocation = sprintf('%s:%s', $this->scheme(), $newLocation);
74
        } elseif ($newLocation[0] === '/') {
75
            $newLocation = sprintf('%s://%s:%d%s', $this->scheme(), $this->host(), $this->port(), $newLocation);
76
        } elseif (!preg_match('~^https?://~', $newLocation)) {
77
            $newLocation = $this->url . $newLocation;
78
        }
79
80
        return new self($newLocation);
81
    }
82
83 2
    private function isValid(string $url): bool
84
    {
85 2
        if (!filter_var($url, FILTER_VALIDATE_URL)) {
86
            return false;
87
        }
88
89 2
        $this->components = parse_url($url);
90
91 2
        if (!isset($this->components['scheme'], $this->components['host'])) {
92
            return false;
93
        }
94
95 2
        return in_array($this->components['scheme'], self::ALLOWED_PROTOCOLS, true);
96
    }
97
}
98