Completed
Push — master ( 2e8a37...e129ff )
by Tobias
04:00
created

MessageTrait::getBody()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Nyholm\Psr7;
6
7
use Nyholm\Psr7\Factory\StreamFactory;
8
use 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
 */
16
trait MessageTrait
17
{
18
    /** @var array Map of all registered headers, as original name => array of values */
19
    private $headers = [];
20
21
    /** @var array Map of lowercase header name => original name at registration */
22
    private $headerNames = [];
23
24
    /** @var string */
25
    private $protocol = '1.1';
26
27
    /** @var StreamInterface */
28
    private $stream;
29
30 5
    public function getProtocolVersion()
31
    {
32 5
        return $this->protocol;
33
    }
34
35 4
    public function withProtocolVersion($version)
36
    {
37 4
        if ($this->protocol === $version) {
38 1
            return $this;
39
        }
40
41 3
        $new = clone $this;
42 3
        $new->protocol = $version;
43
44 3
        return $new;
45
    }
46
47 16
    public function getHeaders(): array
48
    {
49 16
        return $this->headers;
50
    }
51
52 50
    public function hasHeader($header): bool
53
    {
54 50
        return isset($this->headerNames[strtolower($header)]);
55
    }
56
57 25
    public function getHeader($header): array
58
    {
59 25
        $header = strtolower($header);
60
61 25
        if (!isset($this->headerNames[$header])) {
62 5
            return [];
63
        }
64
65 24
        $header = $this->headerNames[$header];
66
67 24
        return $this->headers[$header];
68
    }
69
70 23
    public function getHeaderLine($header): string
71
    {
72 23
        return implode(', ', $this->getHeader($header));
73
    }
74
75 6
    public function withHeader($header, $value): self
76
    {
77 6
        if (!is_array($value)) {
78 5
            $value = [$value];
79
        }
80
81 6
        $value = $this->trimHeaderValues($value);
82 6
        $normalized = strtolower($header);
83
84 6
        $new = clone $this;
85 6
        if (isset($new->headerNames[$normalized])) {
86 1
            unset($new->headers[$new->headerNames[$normalized]]);
87
        }
88 6
        $new->headerNames[$normalized] = $header;
89 6
        $new->headers[$header] = $value;
90
91 6
        return $new;
92
    }
93
94 20
    public function withAddedHeader($header, $value): self
95
    {
96 20
        if (!is_array($value)) {
97 17
            $value = [$value];
98
        } else {
99 5
            $value = array_values($value);
100
        }
101
102 20
        $value = $this->trimHeaderValues($value);
103 20
        $normalized = strtolower($header);
104
105 20
        $new = clone $this;
106 20
        if (isset($new->headerNames[$normalized])) {
107 14
            $header = $this->headerNames[$normalized];
108 14
            $new->headers[$header] = array_merge($this->headers[$header], $value);
109
        } else {
110 18
            $new->headerNames[$normalized] = $header;
111 18
            $new->headers[$header] = $value;
112
        }
113
114 20
        return $new;
115
    }
116
117 5
    public function withoutHeader($header): self
118
    {
119 5
        $normalized = strtolower($header);
120
121 5
        if (!isset($this->headerNames[$normalized])) {
122 2
            return $this;
123
        }
124
125 3
        $header = $this->headerNames[$normalized];
126
127 3
        $new = clone $this;
128 3
        unset($new->headers[$header], $new->headerNames[$normalized]);
129
130 3
        return $new;
131
    }
132
133 9
    public function getBody(): StreamInterface
134
    {
135 9
        if (!$this->stream) {
136 3
            $this->stream = (new StreamFactory())->createStream('');
137
        }
138
139 9
        return $this->stream;
140
    }
141
142 4
    public function withBody(StreamInterface $body): self
143
    {
144 4
        if ($body === $this->stream) {
145 1
            return $this;
146
        }
147
148 3
        $new = clone $this;
149 3
        $new->stream = $body;
150
151 3
        return $new;
152
    }
153
154 91
    private function setHeaders(array $headers)
155
    {
156 91
        $this->headerNames = $this->headers = [];
157 91
        foreach ($headers as $header => $value) {
158 11
            if (!is_array($value)) {
159 10
                $value = [$value];
160
            }
161
162 11
            $value = $this->trimHeaderValues($value);
163 11
            $normalized = strtolower($header);
164 11
            if (isset($this->headerNames[$normalized])) {
165
                $header = $this->headerNames[$normalized];
166
                $this->headers[$header] = array_merge($this->headers[$header], $value);
167
            } else {
168 11
                $this->headerNames[$normalized] = $header;
169 11
                $this->headers[$header] = $value;
170
            }
171
        }
172 91
    }
173
174
    /**
175
     * Trims whitespace from the header values.
176
     *
177
     * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field.
178
     *
179
     * header-field = field-name ":" OWS field-value OWS
180
     * OWS          = *( SP / HTAB )
181
     *
182
     * @param string[] $values Header values
183
     *
184
     * @return string[] Trimmed header values
185
     *
186
     * @see https://tools.ietf.org/html/rfc7230#section-3.2.4
187
     */
188
    private function trimHeaderValues(array $values): array
189
    {
190 29
        return array_map(function ($value) {
191 29
            return trim($value, " \t");
192 29
        }, $values);
193
    }
194
}
195