1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* @inspiration |
5
|
|
|
* https://github.com/drupal/drupal/blob/8.8.x/core/lib/Drupal/Component/Utility/UrlHelper.php |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace Nip\Utility; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Class Url |
12
|
|
|
* @package Nip\Utility |
13
|
|
|
*/ |
14
|
|
|
class Url |
15
|
|
|
{ |
16
|
|
|
/** |
17
|
|
|
* The list of allowed protocols. |
18
|
|
|
* |
19
|
|
|
* @var array |
20
|
|
|
*/ |
21
|
|
|
protected static $allowedProtocols = ['http', 'https']; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Parses an array into a valid, rawurlencoded query string. |
25
|
|
|
* |
26
|
|
|
* |
27
|
|
|
* rawurlencode() is RFC3986 compliant, and as a consequence RFC3987 |
28
|
|
|
* compliant. The latter defines the required format of "URLs" in HTML5. |
29
|
|
|
* urlencode() is almost the same as rawurlencode(), except that it encodes |
30
|
|
|
* spaces as "+" instead of "%20". This makes its result non compliant to |
31
|
|
|
* RFC3986 and as a consequence non compliant to RFC3987 and as a consequence |
32
|
|
|
* not valid as a "URL" in HTML5. |
33
|
|
|
* |
34
|
|
|
* @param array $query |
35
|
|
|
* The query parameter array to be processed, |
36
|
|
|
* e.g. \Drupal::request()->query->all(). |
37
|
|
|
* @param string $parent |
38
|
|
|
* Internal use only. Used to build the $query array key for nested items. |
39
|
|
|
* |
40
|
|
|
* @return string |
41
|
|
|
* A rawurlencoded string which can be used as or appended to the URL query |
42
|
|
|
* string. |
43
|
|
|
* |
44
|
|
|
* @ingroup php_wrappers |
45
|
|
|
* @todo Remove this function once PHP 5.4 is required as we can use just |
46
|
|
|
* http_build_query() directly. |
47
|
|
|
* |
48
|
|
|
*/ |
49
|
|
|
public static function buildQuery(array $query, $parent = '') |
50
|
|
|
{ |
51
|
|
|
$params = []; |
52
|
|
|
|
53
|
|
|
foreach ($query as $key => $value) { |
54
|
|
|
$key = ($parent ? $parent . '[' . rawurlencode($key) . ']' : rawurlencode($key)); |
55
|
|
|
|
56
|
|
|
// Recurse into children. |
57
|
|
|
if (is_array($value)) { |
58
|
|
|
$params[] = static::buildQuery($value, $key); |
59
|
|
|
} // If a query parameter value is NULL, only append its key. |
60
|
|
|
elseif (!isset($value)) { |
61
|
|
|
$params[] = $key; |
62
|
|
|
} else { |
63
|
|
|
// For better readability of paths in query strings, we decode slashes. |
64
|
|
|
$params[] = $key . '=' . str_replace('%2F', '/', rawurlencode($value)); |
65
|
|
|
} |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
return implode('&', $params); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* Reverse of the PHP built-in function parse_url |
73
|
|
|
* |
74
|
|
|
* @see http://php.net/parse_url |
75
|
|
|
* @param $url |
76
|
|
|
* @return string |
77
|
|
|
*/ |
78
|
|
|
public static function build($url) |
79
|
|
|
{ |
80
|
|
|
$scheme = isset($url['scheme']) ? $url['scheme'] . '://' : ''; |
81
|
|
|
$host = isset($url['host']) ? $url['host'] : ''; |
82
|
|
|
$port = isset($url['port']) ? ':' . $url['port'] : ''; |
83
|
|
|
$user = isset($url['user']) ? $url['user'] : ''; |
84
|
|
|
$pass = isset($url['pass']) ? ':' . $url['pass'] : ''; |
85
|
|
|
$pass = ($user || $pass) ? "$pass@" : ''; |
86
|
|
|
$path = isset($url['path']) ? $url['path'] : ''; |
87
|
|
|
$query = isset($url['query']) && $url['query'] ? '?' . $url['query'] : ''; |
88
|
|
|
$fragment = isset($url['fragment']) ? '#' . $url['fragment'] : ''; |
89
|
|
|
|
90
|
|
|
return $scheme . $user . $pass . $host . $port . $path . $query . $fragment; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Verifies the syntax of the given URL. |
95
|
|
|
* |
96
|
|
|
* This function should only be used on actual URLs. It should not be used for |
97
|
|
|
* Drupal menu paths, which can contain arbitrary characters. |
98
|
|
|
* Valid values per RFC 3986. |
99
|
|
|
* |
100
|
|
|
* @param string $url |
101
|
|
|
* The URL to verify. |
102
|
|
|
* @param bool $absolute |
103
|
|
|
* Whether the URL is absolute (beginning with a scheme such as "http:"). |
104
|
|
|
* |
105
|
|
|
* @return bool |
106
|
|
|
* TRUE if the URL is in a valid format, FALSE otherwise. |
107
|
|
|
*/ |
108
|
3 |
|
public static function isValid($url, $absolute = true) |
109
|
|
|
{ |
110
|
3 |
|
if ($absolute) { |
111
|
3 |
|
return (bool)preg_match( |
112
|
3 |
|
" |
113
|
|
|
/^ # Start at the beginning of the text |
114
|
|
|
(?:ftp|https?|feed):\/\/ # Look for ftp, http, https or feed schemes |
115
|
|
|
(?: # Userinfo (optional) which is typically |
116
|
|
|
(?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)* # a username or a username and password |
117
|
|
|
(?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@ # combination |
118
|
|
|
)? |
119
|
|
|
(?: |
120
|
|
|
(?:[a-z0-9\-\.]|%[0-9a-f]{2})+ # A domain name or a IPv4 address |
121
|
|
|
|(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\]) # or a well formed IPv6 address |
122
|
|
|
) |
123
|
|
|
(?::[0-9]+)? # Server port number (optional) |
124
|
|
|
(?:[\/|\?] |
125
|
|
|
(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional) |
126
|
|
|
*)? |
127
|
|
|
$/xi", |
128
|
|
|
$url |
129
|
|
|
); |
130
|
|
|
} else { |
131
|
|
|
return (bool)preg_match("/^(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})+$/i", $url); |
132
|
|
|
} |
133
|
|
|
} |
134
|
|
|
} |
135
|
|
|
|