PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / trunk
Yoast SEO – Advanced SEO with real-time guidance and built-in AI vtrunk
28.6 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 All 130 releases
← All changes | vendor_prefixed/guzzlehttp/psr7/src/MessageTrait.php +100 -47 18.9 → trunk View file →
@@ -1,8 +1,10 @@
1 1 <?php
2 2
3 +declare (strict_types=1);
3 4 namespace YoastSEO_Vendor\GuzzleHttp\Psr7;
4 5
6 +use YoastSEO_Vendor\Psr\Http\Message\MessageInterface;
5 7 use YoastSEO_Vendor\Psr\Http\Message\StreamInterface;
6 8 /**
7 9 * Trait implementing functionality common to requests and responses.
8 10 */
@@ -7,22 +9,29 @@
7 9 * Trait implementing functionality common to requests and responses.
8 10 */
9 11 trait MessageTrait
10 12 {
11 - /** @var array Map of all registered headers, as original name => array of values */
13 + /** @var string[][] Map of all registered headers, as original name => array of values */
12 14 private $headers = [];
13 - /** @var array Map of lowercase header name => original name at registration */
15 + /** @var string[] Map of lowercase header name => original name at registration */
14 16 private $headerNames = [];
15 17 /** @var string */
16 18 private $protocol = '1.1';
17 19 /** @var StreamInterface|null */
18 20 private $stream;
19 - public function getProtocolVersion()
21 + public function getProtocolVersion() : string
20 22 {
21 23 return $this->protocol;
22 24 }
23 - public function withProtocolVersion($version)
25 + /**
26 + * @return static
27 + */
28 + public function withProtocolVersion($version) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
24 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);
25 34 if ($this->protocol === $version) {
26 35 return $this;
27 36 }
28 37 $new = clone $this;
@@ -28,19 +37,19 @@
28 37 $new = clone $this;
29 38 $new->protocol = $version;
30 39 return $new;
31 40 }
32 - public function getHeaders()
41 + public function getHeaders() : array
33 42 {
34 43 return $this->headers;
35 44 }
36 - public function hasHeader($header)
45 + public function hasHeader($header) : bool
37 46 {
38 - return isset($this->headerNames[\strtolower($header)]);
47 + return isset($this->headerNames[\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::asciiToLower($header)]);
39 48 }
40 - public function getHeader($header)
49 + public function getHeader($header) : array
41 50 {
42 - $header = \strtolower($header);
51 + $header = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::asciiToLower($header);
43 52 if (!isset($this->headerNames[$header])) {
44 53 return [];
45 54 }
46 55 $header = $this->headerNames[$header];
@@ -45,17 +54,27 @@
45 54 }
46 55 $header = $this->headerNames[$header];
47 56 return $this->headers[$header];
48 57 }
49 - public function getHeaderLine($header)
58 + public function getHeaderLine($header) : string
50 59 {
51 60 return \implode(', ', $this->getHeader($header));
52 61 }
53 - public function withHeader($header, $value)
62 + /**
63 + * @return static
64 + */
65 + public function withHeader($header, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
54 66 {
55 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 + }
56 75 $value = $this->normalizeHeaderValue($value);
57 - $normalized = \strtolower($header);
76 + $normalized = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::asciiToLower($header);
58 77 $new = clone $this;
59 78 if (isset($new->headerNames[$normalized])) {
60 79 unset($new->headers[$new->headerNames[$normalized]]);
61 80 }
@@ -62,13 +81,23 @@
62 81 $new->headerNames[$normalized] = $header;
63 82 $new->headers[$header] = $value;
64 83 return $new;
65 84 }
66 - public function withAddedHeader($header, $value)
85 + /**
86 + * @return static
87 + */
88 + public function withAddedHeader($header, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
67 89 {
68 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 + }
69 98 $value = $this->normalizeHeaderValue($value);
70 - $normalized = \strtolower($header);
99 + $normalized = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::asciiToLower($header);
71 100 $new = clone $this;
72 101 if (isset($new->headerNames[$normalized])) {
73 102 $header = $this->headerNames[$normalized];
74 103 $new->headers[$header] = \array_merge($this->headers[$header], $value);
@@ -77,11 +106,14 @@
77 106 $new->headers[$header] = $value;
78 107 }
79 108 return $new;
80 109 }
81 - public function withoutHeader($header)
110 + /**
111 + * @return static
112 + */
113 + public function withoutHeader($header) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
82 114 {
83 - $normalized = \strtolower($header);
115 + $normalized = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::asciiToLower($header);
84 116 if (!isset($this->headerNames[$normalized])) {
85 117 return $this;
86 118 }
87 119 $header = $this->headerNames[$normalized];
@@ -88,9 +120,9 @@
88 120 $new = clone $this;
89 121 unset($new->headers[$header], $new->headerNames[$normalized]);
90 122 return $new;
91 123 }
92 - public function getBody()
124 + public function getBody() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface
93 125 {
94 126 if (!$this->stream) {
95 127 $this->stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor('');
96 128 }
@@ -95,9 +127,12 @@
95 127 $this->stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor('');
96 128 }
97 129 return $this->stream;
98 130 }
99 - public function withBody(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $body)
131 + /**
132 + * @return static
133 + */
134 + public function withBody(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $body) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface
100 135 {
101 136 if ($body === $this->stream) {
102 137 return $this;
103 138 }
@@ -104,20 +139,27 @@
104 139 $new = clone $this;
105 140 $new->stream = $body;
106 141 return $new;
107 142 }
108 - private function setHeaders(array $headers)
143 + /**
144 + * @param (string|string[])[] $headers
145 + */
146 + private function setHeaders(array $headers) : void
109 147 {
110 148 $this->headerNames = $this->headers = [];
111 149 foreach ($headers as $header => $value) {
112 - if (\is_int($header)) {
113 - // Numeric array keys are converted to int by PHP but having a header name '123' is not forbidden by the spec
114 - // and also allowed in withHeader(). So we need to cast it to string again for the following assertion to pass.
115 - $header = (string) $header;
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 + }
116 159 }
117 - $this->assertHeader($header);
118 160 $value = $this->normalizeHeaderValue($value);
119 - $normalized = \strtolower($header);
161 + $normalized = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::asciiToLower($header);
120 162 if (isset($this->headerNames[$normalized])) {
121 163 $header = $this->headerNames[$normalized];
122 164 $this->headers[$header] = \array_merge($this->headers[$header], $value);
123 165 } else {
@@ -130,16 +172,16 @@
130 172 * @param mixed $value
131 173 *
132 174 * @return string[]
133 175 */
134 - private function normalizeHeaderValue($value)
176 + private function normalizeHeaderValue($value) : array
135 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 + }
136 181 if (!\is_array($value)) {
137 182 return $this->trimAndValidateHeaderValues([$value]);
138 183 }
139 - if (\count($value) === 0) {
140 - throw new \InvalidArgumentException('Header value can not be an empty array.');
141 - }
142 184 return $this->trimAndValidateHeaderValues($value);
143 185 }
144 186 /**
145 187 * Trims whitespace from the header values.
@@ -152,16 +194,21 @@
152 194 * @param mixed[] $values Header values
153 195 *
154 196 * @return string[] Trimmed header values
155 197 *
156 - * @see https://tools.ietf.org/html/rfc7230#section-3.2.4
198 + * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4
157 199 */
158 - private function trimAndValidateHeaderValues(array $values)
200 + private function trimAndValidateHeaderValues(array $values) : array
159 201 {
160 202 return \array_map(function ($value) {
161 203 if (!\is_scalar($value) && null !== $value) {
162 204 throw new \InvalidArgumentException(\sprintf('Header value must be scalar or null but %s provided.', \is_object($value) ? \get_class($value) : \gettype($value)));
163 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 + }
164 211 $trimmed = \trim((string) $value, " \t");
165 212 $this->assertValue($trimmed);
166 213 return $trimmed;
167 214 }, \array_values($values));
@@ -166,33 +213,39 @@
166 213 return $trimmed;
167 214 }, \array_values($values));
168 215 }
169 216 /**
170 - * @see https://tools.ietf.org/html/rfc7230#section-3.2
217 + * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2
171 218 *
172 219 * @param mixed $header
173 - *
174 - * @return void
175 220 */
176 - private function assertHeader($header)
221 + private function assertHeader($header) : void
177 222 {
178 223 if (!\is_string($header)) {
179 224 throw new \InvalidArgumentException(\sprintf('Header name must be a string but %s provided.', \is_object($header) ? \get_class($header) : \gettype($header)));
180 225 }
181 - if ($header === '') {
182 - throw new \InvalidArgumentException('Header name can not be empty.');
226 + if (!\preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) {
227 + throw new \InvalidArgumentException(\sprintf('"%s" is not valid header name.', $header));
183 228 }
184 - if (!\preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/', $header)) {
185 - throw new \InvalidArgumentException(\sprintf('"%s" is not valid header name', $header));
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');
186 237 }
187 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 + }
188 245 /**
189 - * @param string $value
246 + * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2
190 247 *
191 - * @return void
192 - *
193 - * @see https://tools.ietf.org/html/rfc7230#section-3.2
194 - *
195 248 * field-value = *( field-content / obs-fold )
196 249 * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
197 250 * field-vchar = VCHAR / obs-text
198 251 * VCHAR = %x21-7E
@@ -198,9 +251,9 @@
198 251 * VCHAR = %x21-7E
199 252 * obs-text = %x80-FF
200 253 * obs-fold = CRLF 1*( SP / HTAB )
201 254 */
202 - private function assertValue($value)
255 + private function assertValue(string $value) : void
203 256 {
204 257 // The regular expression intentionally does not support the obs-fold production, because as
205 258 // per RFC 7230#3.2.4:
206 259 //
@@ -211,9 +264,9 @@
211 264 //
212 265 // Clients must not send a request with line folding and a server sending folded headers is
213 266 // likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting
214 267 // folding is not likely to break any legitimate use case.
215 - if (!\preg_match('/^[\\x20\\x09\\x21-\\x7E\\x80-\\xFF]*$/', $value)) {
216 - throw new \InvalidArgumentException(\sprintf('"%s" is not valid header value', $value));
268 + if (!\preg_match('/^[\\x20\\x09\\x21-\\x7E\\x80-\\xFF]*$/D', $value)) {
269 + throw new \InvalidArgumentException(\sprintf('"%s" is not valid header value.', $value));
217 270 }
218 271 }
219 272 }