PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.18.0
GiveWP – Donation Plugin and Fundraising Platform v4.18.0
4.18.0.1 4.18.0 4.17.0 4.16.9 4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 All 258 releases
give / vendor / vendor-prefixed / nyholm / psr7 / src / MessageTrait.php

MessageTrait.php in GiveWP – Donation Plugin and Fundraising Platform 4.18.0, at vendor/vendor-prefixed/nyholm/psr7/src/MessageTrait.php

236 lines 7.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Give\Vendors\Nyholm\Psr7;
6
7 use Give\Vendors\Psr\Http\Message\MessageInterface;
8 use Give\Vendors\Psr\Http\Message\StreamInterface;
9
10 /**
11 * Trait implementing functionality common to requests and responses.
12 *
13 * @author Michael Dowling and contributors to guzzlehttp/psr7
14 * @author Tobias Nyholm <[email protected]>
15 * @author Martijn van der Ven <[email protected]>
16 *
17 * @internal should not be used outside of Nyholm/Psr7 as it does not fall under our BC promise
18 */
19 trait MessageTrait
20 {
21 /** @var array Map of all registered headers, as original name => array of values */
22 private $headers = [];
23
24 /** @var array Map of lowercase header name => original name at registration */
25 private $headerNames = [];
26
27 /** @var string */
28 private $protocol = '1.1';
29
30 /** @var StreamInterface|null */
31 private $stream;
32
33 public function getProtocolVersion(): string
34 {
35 return $this->protocol;
36 }
37
38 /**
39 * @return static
40 */
41 public function withProtocolVersion($version): MessageInterface
42 {
43 if (!\is_scalar($version)) {
44 throw new \InvalidArgumentException('Protocol version must be a string');
45 }
46
47 if ($this->protocol === $version) {
48 return $this;
49 }
50
51 $new = clone $this;
52 $new->protocol = (string) $version;
53
54 return $new;
55 }
56
57 public function getHeaders(): array
58 {
59 return $this->headers;
60 }
61
62 public function hasHeader($header): bool
63 {
64 return isset($this->headerNames[\strtr($header, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')]);
65 }
66
67 public function getHeader($header): array
68 {
69 if (!\is_string($header)) {
70 throw new \InvalidArgumentException('Header name must be an RFC 7230 compatible string');
71 }
72
73 $header = \strtr($header, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
74 if (!isset($this->headerNames[$header])) {
75 return [];
76 }
77
78 $header = $this->headerNames[$header];
79
80 return $this->headers[$header];
81 }
82
83 public function getHeaderLine($header): string
84 {
85 return \implode(', ', $this->getHeader($header));
86 }
87
88 /**
89 * @return static
90 */
91 public function withHeader($header, $value): MessageInterface
92 {
93 $value = $this->validateAndTrimHeader($header, $value);
94 $normalized = \strtr($header, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
95
96 $new = clone $this;
97 if (isset($new->headerNames[$normalized])) {
98 unset($new->headers[$new->headerNames[$normalized]]);
99 }
100 $new->headerNames[$normalized] = $header;
101 $new->headers[$header] = $value;
102
103 return $new;
104 }
105
106 /**
107 * @return static
108 */
109 public function withAddedHeader($header, $value): MessageInterface
110 {
111 if (!\is_string($header) || '' === $header) {
112 throw new \InvalidArgumentException('Header name must be an RFC 7230 compatible string');
113 }
114
115 $new = clone $this;
116 $new->setHeaders([$header => $value]);
117
118 return $new;
119 }
120
121 /**
122 * @return static
123 */
124 public function withoutHeader($header): MessageInterface
125 {
126 if (!\is_string($header)) {
127 throw new \InvalidArgumentException('Header name must be an RFC 7230 compatible string');
128 }
129
130 $normalized = \strtr($header, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
131 if (!isset($this->headerNames[$normalized])) {
132 return $this;
133 }
134
135 $header = $this->headerNames[$normalized];
136 $new = clone $this;
137 unset($new->headers[$header], $new->headerNames[$normalized]);
138
139 return $new;
140 }
141
142 public function getBody(): StreamInterface
143 {
144 if (null === $this->stream) {
145 $this->stream = Stream::create('');
146 }
147
148 return $this->stream;
149 }
150
151 /**
152 * @return static
153 */
154 public function withBody(StreamInterface $body): MessageInterface
155 {
156 if ($body === $this->stream) {
157 return $this;
158 }
159
160 $new = clone $this;
161 $new->stream = $body;
162
163 return $new;
164 }
165
166 private function setHeaders(array $headers): void
167 {
168 foreach ($headers as $header => $value) {
169 if (\is_int($header)) {
170 // If a header name was set to a numeric string, PHP will cast the key to an int.
171 // We must cast it back to a string in order to comply with validation.
172 $header = (string) $header;
173 }
174 $value = $this->validateAndTrimHeader($header, $value);
175 $normalized = \strtr($header, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
176 if (isset($this->headerNames[$normalized])) {
177 $header = $this->headerNames[$normalized];
178 $this->headers[$header] = \array_merge($this->headers[$header], $value);
179 } else {
180 $this->headerNames[$normalized] = $header;
181 $this->headers[$header] = $value;
182 }
183 }
184 }
185
186 /**
187 * Make sure the header complies with RFC 7230.
188 *
189 * Header names must be a non-empty string consisting of token characters.
190 *
191 * Header values must be strings consisting of visible characters with all optional
192 * leading and trailing whitespace stripped. This method will always strip such
193 * optional whitespace. Note that the method does not allow folding whitespace within
194 * the values as this was deprecated for almost all instances by the RFC.
195 *
196 * header-field = field-name ":" OWS field-value OWS
197 * field-name = 1*( "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^"
198 * / "_" / "`" / "|" / "~" / %x30-39 / ( %x41-5A / %x61-7A ) )
199 * OWS = *( SP / HTAB )
200 * field-value = *( ( %x21-7E / %x80-FF ) [ 1*( SP / HTAB ) ( %x21-7E / %x80-FF ) ] )
201 *
202 * @see https://tools.ietf.org/html/rfc7230#section-3.2.4
203 */
204 private function validateAndTrimHeader($header, $values): array
205 {
206 if (!\is_string($header) || 1 !== \preg_match("@^[!#$%&'*+.^_`|~0-9A-Za-z-]+$@D", $header)) {
207 throw new \InvalidArgumentException('Header name must be an RFC 7230 compatible string');
208 }
209
210 if (!\is_array($values)) {
211 // This is simple, just one value.
212 if ((!\is_numeric($values) && !\is_string($values)) || 1 !== \preg_match("@^[ \t\x21-\x7E\x80-\xFF]*$@", (string) $values)) {
213 throw new \InvalidArgumentException('Header values must be RFC 7230 compatible strings');
214 }
215
216 return [\trim((string) $values, " \t")];
217 }
218
219 if (empty($values)) {
220 throw new \InvalidArgumentException('Header values must be a string or an array of strings, empty array given');
221 }
222
223 // Assert Non empty array
224 $returnValues = [];
225 foreach ($values as $v) {
226 if ((!\is_numeric($v) && !\is_string($v)) || 1 !== \preg_match("@^[ \t\x21-\x7E\x80-\xFF]*$@D", (string) $v)) {
227 throw new \InvalidArgumentException('Header values must be RFC 7230 compatible strings');
228 }
229
230 $returnValues[] = \trim((string) $v, " \t");
231 }
232
233 return $returnValues;
234 }
235 }
236