PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.5
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.5
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
wordpress-seo / vendor_prefixed / guzzlehttp / psr7 / src / MessageTrait.php

MessageTrait.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 28.5, at vendor_prefixed/guzzlehttp/psr7/src/MessageTrait.php

273 lines 10.6 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 namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
5
6 use YoastSEO_Vendor\Psr\Http\Message\MessageInterface;
7 use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
8 /**
9 * Trait implementing functionality common to requests and responses.
10 */
11 trait MessageTrait
12 {
13 /** @var string[][] Map of all registered headers, as original name => array of values */
14 private $headers = [];
15 /** @var string[] Map of lowercase header name => original name at registration */
16 private $headerNames = [];
17 /** @var string */
18 private $protocol = '1.1';
19 /** @var StreamInterface|null */
20 private $stream;
21 public function getProtocolVersion() : string
22 {
23 return $this->protocol;
24 }
25 /**
26 * @return static
27 */
28 public function withProtocolVersion($version) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
29 {
30 if (!\is_string($version)) {
31 \YoastSEO_Vendor\trigger_deprecation('guzzlehttp/psr7', '2.11', 'Passing %s to MessageInterface::withProtocolVersion() is deprecated; guzzlehttp/psr7 3.0 requires string.', \get_debug_type($version));
32 }
33 $this->assertProtocolVersion($version);
34 if ($this->protocol === $version) {
35 return $this;
36 }
37 $new = clone $this;
38 $new->protocol = $version;
39 return $new;
40 }
41 public function getHeaders() : array
42 {
43 return $this->headers;
44 }
45 public function hasHeader($header) : bool
46 {
47 return isset($this->headerNames[\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::asciiToLower($header)]);
48 }
49 public function getHeader($header) : array
50 {
51 $header = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::asciiToLower($header);
52 if (!isset($this->headerNames[$header])) {
53 return [];
54 }
55 $header = $this->headerNames[$header];
56 return $this->headers[$header];
57 }
58 public function getHeaderLine($header) : string
59 {
60 return \implode(', ', $this->getHeader($header));
61 }
62 /**
63 * @return static
64 */
65 public function withHeader($header, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
66 {
67 $this->assertHeader($header);
68 $values = \is_array($value) ? $value : [$value];
69 foreach ($values as $item) {
70 if (!\is_string($item) && (\is_scalar($item) || $item === null)) {
71 \YoastSEO_Vendor\trigger_deprecation('guzzlehttp/psr7', '2.11', 'Passing %s to MessageInterface::withHeader() is deprecated; guzzlehttp/psr7 3.0 requires string|string[].', \get_debug_type($item));
72 break;
73 }
74 }
75 $value = $this->normalizeHeaderValue($value);
76 $normalized = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::asciiToLower($header);
77 $new = clone $this;
78 if (isset($new->headerNames[$normalized])) {
79 unset($new->headers[$new->headerNames[$normalized]]);
80 }
81 $new->headerNames[$normalized] = $header;
82 $new->headers[$header] = $value;
83 return $new;
84 }
85 /**
86 * @return static
87 */
88 public function withAddedHeader($header, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
89 {
90 $this->assertHeader($header);
91 $values = \is_array($value) ? $value : [$value];
92 foreach ($values as $item) {
93 if (!\is_string($item) && (\is_scalar($item) || $item === null)) {
94 \YoastSEO_Vendor\trigger_deprecation('guzzlehttp/psr7', '2.11', 'Passing %s to MessageInterface::withAddedHeader() is deprecated; guzzlehttp/psr7 3.0 requires string|string[].', \get_debug_type($item));
95 break;
96 }
97 }
98 $value = $this->normalizeHeaderValue($value);
99 $normalized = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::asciiToLower($header);
100 $new = clone $this;
101 if (isset($new->headerNames[$normalized])) {
102 $header = $this->headerNames[$normalized];
103 $new->headers[$header] = \array_merge($this->headers[$header], $value);
104 } else {
105 $new->headerNames[$normalized] = $header;
106 $new->headers[$header] = $value;
107 }
108 return $new;
109 }
110 /**
111 * @return static
112 */
113 public function withoutHeader($header) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
114 {
115 $normalized = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::asciiToLower($header);
116 if (!isset($this->headerNames[$normalized])) {
117 return $this;
118 }
119 $header = $this->headerNames[$normalized];
120 $new = clone $this;
121 unset($new->headers[$header], $new->headerNames[$normalized]);
122 return $new;
123 }
124 public function getBody() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
125 {
126 if (!$this->stream) {
127 $this->stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor('');
128 }
129 return $this->stream;
130 }
131 /**
132 * @return static
133 */
134 public function withBody(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $body) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
135 {
136 if ($body === $this->stream) {
137 return $this;
138 }
139 $new = clone $this;
140 $new->stream = $body;
141 return $new;
142 }
143 /**
144 * @param (string|string[])[] $headers
145 */
146 private function setHeaders(array $headers) : void
147 {
148 $this->headerNames = $this->headers = [];
149 foreach ($headers as $header => $value) {
150 // Numeric array keys are converted to int by PHP.
151 $header = (string) $header;
152 $this->assertHeader($header);
153 $values = \is_array($value) ? $value : [$value];
154 foreach ($values as $item) {
155 if (!\is_string($item) && (\is_scalar($item) || $item === null)) {
156 \YoastSEO_Vendor\trigger_deprecation('guzzlehttp/psr7', '2.11', 'Passing %s to %s::__construct() is deprecated; guzzlehttp/psr7 3.0 requires string|string[].', \get_debug_type($item), static::class);
157 break;
158 }
159 }
160 $value = $this->normalizeHeaderValue($value);
161 $normalized = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::asciiToLower($header);
162 if (isset($this->headerNames[$normalized])) {
163 $header = $this->headerNames[$normalized];
164 $this->headers[$header] = \array_merge($this->headers[$header], $value);
165 } else {
166 $this->headerNames[$normalized] = $header;
167 $this->headers[$header] = $value;
168 }
169 }
170 }
171 /**
172 * @param mixed $value
173 *
174 * @return string[]
175 */
176 private function normalizeHeaderValue($value) : array
177 {
178 if (\is_array($value) && $value === []) {
179 \YoastSEO_Vendor\trigger_deprecation('guzzlehttp/psr7', '2.11', 'Passing an empty array as a header value is deprecated; guzzlehttp/psr7 3.0 rejects empty header value arrays.');
180 }
181 if (!\is_array($value)) {
182 return $this->trimAndValidateHeaderValues([$value]);
183 }
184 return $this->trimAndValidateHeaderValues($value);
185 }
186 /**
187 * Trims whitespace from the header values.
188 *
189 * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field.
190 *
191 * header-field = field-name ":" OWS field-value OWS
192 * OWS = *( SP / HTAB )
193 *
194 * @param mixed[] $values Header values
195 *
196 * @return string[] Trimmed header values
197 *
198 * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4
199 */
200 private function trimAndValidateHeaderValues(array $values) : array
201 {
202 return \array_map(function ($value) {
203 if (!\is_scalar($value) && null !== $value) {
204 throw new \InvalidArgumentException(\sprintf('Header value must be scalar or null but %s provided.', \is_object($value) ? \get_class($value) : \gettype($value)));
205 }
206 // Convert non-finite floats explicitly, as implicit coercion of
207 // NAN emits a warning on PHP 8.5.
208 if (\is_float($value) && !\is_finite($value)) {
209 $value = \is_nan($value) ? 'NAN' : ($value > 0 ? 'INF' : '-INF');
210 }
211 $trimmed = \trim((string) $value, " \t");
212 $this->assertValue($trimmed);
213 return $trimmed;
214 }, \array_values($values));
215 }
216 /**
217 * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2
218 *
219 * @param mixed $header
220 */
221 private function assertHeader($header) : void
222 {
223 if (!\is_string($header)) {
224 throw new \InvalidArgumentException(\sprintf('Header name must be a string but %s provided.', \is_object($header) ? \get_class($header) : \gettype($header)));
225 }
226 if (!\preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) {
227 throw new \InvalidArgumentException(\sprintf('"%s" is not valid header name.', $header));
228 }
229 }
230 /**
231 * @param mixed $version
232 */
233 private function assertProtocolVersion($version) : void
234 {
235 if (\is_string($version)) {
236 $this->assertNoLineSeparators($version, 'Protocol version');
237 }
238 }
239 private function assertNoLineSeparators(string $value, string $field) : void
240 {
241 if (\strpbrk($value, "\r\n") !== \false) {
242 throw new \InvalidArgumentException($field . ' must not contain CR or LF characters.');
243 }
244 }
245 /**
246 * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2
247 *
248 * field-value = *( field-content / obs-fold )
249 * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
250 * field-vchar = VCHAR / obs-text
251 * VCHAR = %x21-7E
252 * obs-text = %x80-FF
253 * obs-fold = CRLF 1*( SP / HTAB )
254 */
255 private function assertValue(string $value) : void
256 {
257 // The regular expression intentionally does not support the obs-fold production, because as
258 // per RFC 7230#3.2.4:
259 //
260 // A sender MUST NOT generate a message that includes
261 // line folding (i.e., that has any field-value that contains a match to
262 // the obs-fold rule) unless the message is intended for packaging
263 // within the message/http media type.
264 //
265 // Clients must not send a request with line folding and a server sending folded headers is
266 // likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting
267 // folding is not likely to break any legitimate use case.
268 if (!\preg_match('/^[\\x20\\x09\\x21-\\x7E\\x80-\\xFF]*$/D', $value)) {
269 throw new \InvalidArgumentException(\sprintf('"%s" is not valid header value.', $value));
270 }
271 }
272 }
273