krz/vox-populi

A Tumblr web client.

clone: git clone https://gitbay.org/krz/vox-populi.git

main: vendor/guzzlehttp/psr7/src/MessageTrait.php · raw

  1<?php
  2namespace GuzzleHttp\Psr7;
  3
  4use Psr\Http\Message\StreamInterface;
  5
  6/**
  7 * Trait implementing functionality common to requests and responses.
  8 */
  9trait MessageTrait
 10{
 11    /** @var array Map of all registered headers, as original name => array of values */
 12    private $headers = [];
 13
 14    /** @var array Map of lowercase header name => original name at registration */
 15    private $headerNames  = [];
 16
 17    /** @var string */
 18    private $protocol = '1.1';
 19
 20    /** @var StreamInterface */
 21    private $stream;
 22
 23    public function getProtocolVersion()
 24    {
 25        return $this->protocol;
 26    }
 27
 28    public function withProtocolVersion($version)
 29    {
 30        if ($this->protocol === $version) {
 31            return $this;
 32        }
 33
 34        $new = clone $this;
 35        $new->protocol = $version;
 36        return $new;
 37    }
 38
 39    public function getHeaders()
 40    {
 41        return $this->headers;
 42    }
 43
 44    public function hasHeader($header)
 45    {
 46        return isset($this->headerNames[strtolower($header)]);
 47    }
 48
 49    public function getHeader($header)
 50    {
 51        $header = strtolower($header);
 52
 53        if (!isset($this->headerNames[$header])) {
 54            return [];
 55        }
 56
 57        $header = $this->headerNames[$header];
 58
 59        return $this->headers[$header];
 60    }
 61
 62    public function getHeaderLine($header)
 63    {
 64        return implode(', ', $this->getHeader($header));
 65    }
 66
 67    public function withHeader($header, $value)
 68    {
 69        $this->assertHeader($header);
 70        $value = $this->normalizeHeaderValue($value);
 71        $normalized = strtolower($header);
 72
 73        $new = clone $this;
 74        if (isset($new->headerNames[$normalized])) {
 75            unset($new->headers[$new->headerNames[$normalized]]);
 76        }
 77        $new->headerNames[$normalized] = $header;
 78        $new->headers[$header] = $value;
 79
 80        return $new;
 81    }
 82
 83    public function withAddedHeader($header, $value)
 84    {
 85        $this->assertHeader($header);
 86        $value = $this->normalizeHeaderValue($value);
 87        $normalized = strtolower($header);
 88
 89        $new = clone $this;
 90        if (isset($new->headerNames[$normalized])) {
 91            $header = $this->headerNames[$normalized];
 92            $new->headers[$header] = array_merge($this->headers[$header], $value);
 93        } else {
 94            $new->headerNames[$normalized] = $header;
 95            $new->headers[$header] = $value;
 96        }
 97
 98        return $new;
 99    }
100
101    public function withoutHeader($header)
102    {
103        $normalized = strtolower($header);
104
105        if (!isset($this->headerNames[$normalized])) {
106            return $this;
107        }
108
109        $header = $this->headerNames[$normalized];
110
111        $new = clone $this;
112        unset($new->headers[$header], $new->headerNames[$normalized]);
113
114        return $new;
115    }
116
117    public function getBody()
118    {
119        if (!$this->stream) {
120            $this->stream = stream_for('');
121        }
122
123        return $this->stream;
124    }
125
126    public function withBody(StreamInterface $body)
127    {
128        if ($body === $this->stream) {
129            return $this;
130        }
131
132        $new = clone $this;
133        $new->stream = $body;
134        return $new;
135    }
136
137    private function setHeaders(array $headers)
138    {
139        $this->headerNames = $this->headers = [];
140        foreach ($headers as $header => $value) {
141            if (is_int($header)) {
142                // Numeric array keys are converted to int by PHP but having a header name '123' is not forbidden by the spec
143                // and also allowed in withHeader(). So we need to cast it to string again for the following assertion to pass.
144                $header = (string) $header;
145            }
146            $this->assertHeader($header);
147            $value = $this->normalizeHeaderValue($value);
148            $normalized = strtolower($header);
149            if (isset($this->headerNames[$normalized])) {
150                $header = $this->headerNames[$normalized];
151                $this->headers[$header] = array_merge($this->headers[$header], $value);
152            } else {
153                $this->headerNames[$normalized] = $header;
154                $this->headers[$header] = $value;
155            }
156        }
157    }
158
159    private function normalizeHeaderValue($value)
160    {
161        if (!is_array($value)) {
162            return $this->trimHeaderValues([$value]);
163        }
164
165        if (count($value) === 0) {
166            throw new \InvalidArgumentException('Header value can not be an empty array.');
167        }
168
169        return $this->trimHeaderValues($value);
170    }
171
172    /**
173     * Trims whitespace from the header values.
174     *
175     * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field.
176     *
177     * header-field = field-name ":" OWS field-value OWS
178     * OWS          = *( SP / HTAB )
179     *
180     * @param string[] $values Header values
181     *
182     * @return string[] Trimmed header values
183     *
184     * @see https://tools.ietf.org/html/rfc7230#section-3.2.4
185     */
186    private function trimHeaderValues(array $values)
187    {
188        return array_map(function ($value) {
189            if (!is_scalar($value) && null !== $value) {
190                throw new \InvalidArgumentException(sprintf(
191                    'Header value must be scalar or null but %s provided.',
192                    is_object($value) ? get_class($value) : gettype($value)
193                ));
194            }
195
196            return trim((string) $value, " \t");
197        }, $values);
198    }
199
200    private function assertHeader($header)
201    {
202        if (!is_string($header)) {
203            throw new \InvalidArgumentException(sprintf(
204                'Header name must be a string but %s provided.',
205                is_object($header) ? get_class($header) : gettype($header)
206            ));
207        }
208
209        if ($header === '') {
210            throw new \InvalidArgumentException('Header name can not be empty.');
211        }
212    }
213}