Completed
Push — master ( d94b34...85a373 )
by smiley
01:50
created

UriExtended::isAbsolute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Class UriExtended
4
 *
5
 * @filesource   UriExtended.php
6
 * @created      06.03.2019
7
 * @package      chillerlan\HTTP\Psr7
8
 * @author       smiley <[email protected]>
9
 * @copyright    2019 smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\HTTP\Psr7;
14
15
use Psr\Http\Message\UriInterface;
16
17
/**
18
 * Additional non-PSR Uri methods
19
 */
20
class UriExtended extends Uri{
21
22
	/**
23
	 * @see \parse_url()
24
	 *
25
	 * @param array $parts
26
	 *
27
	 * @return \Psr\Http\Message\UriInterface|\chillerlan\HTTP\Psr7\Uri
28
	 */
29
	public static function fromParts(array $parts):UriInterface{
30
		$uri = new self;
31
32
		$uri->parseUriParts($parts);
33
		$uri->validateState();
34
35
		return $uri;
36
	}
37
38
	/**
39
	 * Whether the URI is absolute, i.e. it has a scheme.
40
	 *
41
	 * An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true
42
	 * if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative
43
	 * to another URI, the base URI. Relative references can be divided into several forms:
44
	 * - network-path references, e.g. '//example.com/path'
45
	 * - absolute-path references, e.g. '/path'
46
	 * - relative-path references, e.g. 'subpath'
47
	 *
48
	 * @return bool
49
	 * @see  Uri::isNetworkPathReference
50
	 * @see  Uri::isAbsolutePathReference
51
	 * @see  Uri::isRelativePathReference
52
	 * @link https://tools.ietf.org/html/rfc3986#section-4
53
	 */
54
	public function isAbsolute():bool{
55
		return $this->getScheme() !== '';
56
	}
57
58
	/**
59
	 * Whether the URI is a network-path reference.
60
	 *
61
	 * A relative reference that begins with two slash characters is termed an network-path reference.
62
	 *
63
	 * @return bool
64
	 * @link https://tools.ietf.org/html/rfc3986#section-4.2
65
	 */
66
	public function isNetworkPathReference():bool{
67
		return $this->getScheme() === '' && $this->getAuthority() !== '';
68
	}
69
70
	/**
71
	 * Whether the URI is a absolute-path reference.
72
	 *
73
	 * A relative reference that begins with a single slash character is termed an absolute-path reference.
74
	 *
75
	 * @return bool
76
	 * @link https://tools.ietf.org/html/rfc3986#section-4.2
77
	 */
78
	public function isAbsolutePathReference():bool{
79
		return $this->getScheme() === '' && $this->getAuthority() === '' && isset($this->getPath()[0]) && $this->getPath()[0] === '/';
80
	}
81
82
	/**
83
	 * Whether the URI is a relative-path reference.
84
	 *
85
	 * A relative reference that does not begin with a slash character is termed a relative-path reference.
86
	 *
87
	 * @return bool
88
	 * @link https://tools.ietf.org/html/rfc3986#section-4.2
89
	 */
90
	public function isRelativePathReference():bool{
91
		return $this->getScheme() === '' && $this->getAuthority() === '' && (!isset($this->getPath()[0]) || $this->getPath()[0] !== '/');
92
	}
93
94
	/**
95
	 * removes a specific query string value.
96
	 *
97
	 * Any existing query string values that exactly match the provided key are
98
	 * removed.
99
	 *
100
	 * @param string $key Query string key to remove.
101
	 *
102
	 * @return \Psr\Http\Message\UriInterface|\chillerlan\HTTP\Psr7\UriExtended
103
	 */
104
	public function withoutQueryValue($key):UriExtended{
105
		$current = $this->getQuery();
106
107
		if($current === ''){
108
			return $this;
109
		}
110
111
		$decodedKey = rawurldecode($key);
112
113
		$result = array_filter(explode('&', $current), function($part) use ($decodedKey){
114
			return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
115
		});
116
117
		/** @noinspection PhpIncompatibleReturnTypeInspection */
118
		return $this->withQuery(implode('&', $result));
119
	}
120
121
	/**
122
	 * adds a specific query string value.
123
	 *
124
	 * Any existing query string values that exactly match the provided key are
125
	 * removed and replaced with the given key value pair.
126
	 *
127
	 * A value of null will set the query string key without a value, e.g. "key"
128
	 * instead of "key=value".
129
	 *
130
	 * @param string      $key   Key to set.
131
	 * @param string|null $value Value to set
132
	 *
133
	 * @return \Psr\Http\Message\UriInterface|\chillerlan\HTTP\Psr7\UriExtended
134
	 */
135
	public function withQueryValue($key, $value):UriExtended{
136
		$current = $this->getQuery();
137
138
		if($current === ''){
139
			$result = [];
140
		}
141
		else{
142
			$decodedKey = rawurldecode($key);
143
			$result     = array_filter(explode('&', $current), function($part) use ($decodedKey){
144
				return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
145
			});
146
		}
147
148
		// Query string separators ("=", "&") within the key or value need to be encoded
149
		// (while preventing double-encoding) before setting the query string. All other
150
		// chars that need percent-encoding will be encoded by withQuery().
151
		$replaceQuery = ['=' => '%3D', '&' => '%26'];
152
		$key          = strtr($key, $replaceQuery);
153
154
		$result[] = $value !== null
155
			? $key.'='.strtr($value, $replaceQuery)
156
			: $key;
157
158
		/** @noinspection PhpIncompatibleReturnTypeInspection */
159
		return $this->withQuery(implode('&', $result));
160
	}
161
162
}
163