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

URL::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
c 0
b 0
f 0
ccs 3
cts 4
cp 0.75
rs 10
cc 2
nc 2
nop 1
crap 2.0625
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