Passed
Push — main ( b70ad7...dcfc03 )
by Dylan
02:02
created

URL::is_absolute_url()   B

Complexity

Conditions 7
Paths 28

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 12
c 1
b 0
f 0
nc 28
nop 1
dl 0
loc 23
rs 8.8333
1
<?php
2
3
namespace Lifeboat\SDK\Utils;
4
5
use Lifeboat\SDK\Exceptions\InvalidArgumentException;
6
7
/**
8
 * Class URL
9
 * @package Lifeboat\SDK\Utils
10
 */
11
class URL {
12
13
    /**
14
     * @param string $key
15
     * @param string $value
16
     * @param string $url
17
     * @return string
18
     * @throws InvalidArgumentException If URL is malformed
19
     */
20
    public static function setGetVar(string $key, string $value, string $url): string
21
    {
22
        if (!self::is_absolute_url($url)) {
23
            $isRelative = true;
24
            $url = 'http://dummy.com/' . ltrim($url, '/');
25
        } else {
26
            $isRelative = false;
27
        }
28
29
        // try to parse uri
30
        $parts = parse_url($url);
31
        if (empty($parts)) {
32
            throw new InvalidArgumentException("Can't parse URL: " . $url);
33
        }
34
35
        // Parse params and add new variable
36
        $params = [];
37
        if (isset($parts['query'])) {
38
            parse_str($parts['query'], $params);
39
        }
40
        $params[$key] = $value;
41
42
        // Generate URI segments and formatting
43
        $scheme = (array_key_exists('scheme', $parts)) ? $parts['scheme'] : 'http';
44
        $user = (array_key_exists('user', $parts)) ? $parts['user'] : '';
45
        $port = (array_key_exists('port', $parts) && $parts['port']) ? ':' . $parts['port'] : '';
46
47
        if ($user != '') {
48
            // format in either user:[email protected] or [email protected]
49
            $user .= (array_key_exists('pass', $parts) && $parts['pass']) ? ':' . $parts['pass'] . '@' : '';
50
        }
51
52
        // handle URL params which are existing / new
53
        $params = ($params) ? '?' . http_build_query($params) : '';
54
55
        // Recompile URI segments
56
        $newUri = $scheme . '://' . $user . $parts['host'] . $port . $parts['path'] . $params;
57
58
        if ($isRelative) {
59
            return str_replace('http://dummy.com/', '', $newUri);
60
        }
61
62
        return $newUri;
63
    }
64
65
    /**
66
     * @param string $url
67
     * @return bool
68
     */
69
    public static function is_absolute_url(string $url): bool
70
    {
71
        // Strip off the query and fragment parts of the URL before checking
72
        if (($queryPosition = strpos($url, '?')) !== false) {
73
            $url = substr($url, 0, $queryPosition - 1);
74
        }
75
        if (($hashPosition = strpos($url, '#')) !== false) {
76
            $url = substr($url, 0, $hashPosition - 1);
77
        }
78
        $colonPosition = strpos($url, ':');
79
        $slashPosition = strpos($url, '/');
80
        return (
81
            // Base check for existence of a host on a compliant URL
82
            parse_url($url, PHP_URL_HOST)
83
            // Check for more than one leading slash without a protocol.
84
            // While not a RFC compliant absolute URL, it is completed to a valid URL by some browsers,
85
            // and hence a potential security risk. Single leading slashes are not an issue though.
86
            || preg_match('%^\s*/{2,}%', $url)
87
            || (
88
                // If a colon is found, check if it's part of a valid scheme definition
89
                // (meaning its not preceded by a slash).
90
                $colonPosition !== false
91
                && ($slashPosition === false || $colonPosition < $slashPosition)
92
            )
93
        );
94
    }
95
}
96