Headers::getHeader()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace GinoPane\NanoRest\Supplemental;
4
5
/**
6
 * Class Headers
7
 *
8
 * Simple container object to store request and response headers
9
 */
10
class Headers
11
{
12
    /**
13
     * Array of stored headers
14
     *
15
     * @var array
16
     */
17
    private $headers = [];
18
19
    /**
20
     * Headers constructor
21
     *
22
     * @param array $headers
23
     */
24
    public function __construct(array $headers = [])
25
    {
26
        $this->setHeaders($headers);
27
    }
28
29
    /**
30
     * Set individual header
31
     *
32
     * @param string $header
33
     * @param string $content
34
     *
35
     * @return Headers
36
     */
37
    public function setHeader(string $header, string $content): Headers
38
    {
39
        $this->headers[self::processKey($header)] = $content;
40
41
        return $this;
42
    }
43
44
    /**
45
     * Set headers array. Old headers will be removed
46
     *
47
     * @param array $headers Array of header -> data pairs
48
     *
49
     * @return Headers
50
     */
51
    public function setHeaders(array $headers = []): Headers
52
    {
53
        $this->headers = array();
54
55
        foreach ($headers as $header => $data) {
56
            $this->setHeader((string)$header, (string)$data);
57
        }
58
59
        return $this;
60
    }
61
62
    /**
63
     * Merge headers array. Old headers will be preserved or replaced
64
     *
65
     * @param array $headers Array of header -> data pairs
66
     *
67
     * @return Headers
68
     */
69
    public function mergeHeaders(array $headers = []): Headers
70
    {
71
        foreach ($headers as $header => $data) {
72
            $this->setHeader((string)$header, (string)$data);
73
        }
74
75
        return $this;
76
    }
77
78
    /**
79
     * Set headers from headers string
80
     *
81
     * @param string $headers
82
     *
83
     * @return Headers
84
     */
85
    public function setHeadersFromString(string $headers): Headers
86
    {
87
        return $this->setHeaders($this::parseHeaders($headers));
88
    }
89
90
    /**
91
     * Get header value by name
92
     *
93
     * @param string $key
94
     *
95
     * @return null|string
96
     */
97
    public function getHeader(string $key): ?string
98
    {
99
        $key = self::processKey($key);
100
101
        return isset($this->headers[$key]) ? $this->headers[$key] : null;
102
    }
103
104
    /**
105
     * Get all set headers
106
     *
107
     * @return array
108
     */
109
    public function getHeaders(): array
110
    {
111
        return $this->headers;
112
    }
113
114
    /**
115
     * Returns an array of "name: value" pair for request
116
     *
117
     * @return array
118
     */
119
    public function getHeadersForRequest(): array
120
    {
121
        $headers = $this->headers;
122
123
        array_walk($headers, function (&$value, $name) {
124
            $value = "$name: $value";
125
        });
126
127
        return $headers;
128
    }
129
130
    /**
131
     * Returns true if headers exists, false otherwise
132
     *
133
     * @param string $header
134
     *
135
     * @return bool
136
     */
137
    public function headerExists(string $header): bool
138
    {
139
        return array_key_exists(self::processKey($header), $this->getHeaders());
140
    }
141
142
    /**
143
     * Parse headers string into associative array. Only named headers returned
144
     *
145
     * Duplicated headers are parsed into comma-separated string:
146
     * @link https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
147
     * @link https://stackoverflow.com/questions/4371328/are-duplicate-http-response-headers-acceptable
148
     * @link https://stackoverflow.com/questions/6368574/how-to-get-the-functionality-of-http-parse-headers-without-pecl
149
     *
150
     * @param string $headers
151
     *
152
     * @return array
153
     */
154
    public static function parseHeaders(string $headers): array
155
    {
156
        $parsedHeaders = array();
157
158
        foreach (explode("\n", $headers) as $header) {
159
            @list($headerTitle, $headerValue) = explode(':', $header, 2);
160
161
            if (!isset($headerValue)) {
162
                continue;
163
            }
164
165
            $headerTitle = self::processKey(trim($headerTitle));
166
            $headerValue = trim($headerValue);
167
168
            if (!isset($parsedHeaders[$headerTitle])) {
169
                $parsedHeaders[$headerTitle] = $headerValue;
170
            } else {
171
                $parsedHeaders[$headerTitle] .= ", $headerValue";
172
            }
173
        }
174
175
        return $parsedHeaders;
176
    }
177
178
    /**
179
     * Helper method to statically create Headers object from headers string
180
     *
181
     * @param string $headers
182
     *
183
     * @return Headers
184
     */
185
    public static function createFromString(string $headers): Headers
186
    {
187
        return new self(Headers::parseHeaders($headers));
188
    }
189
190
    /**
191
     * Just returns processed (lower-cased) version of the $key
192
     *
193
     * @param string $key
194
     * @return string
195
     */
196
    private static function processKey(string $key): string
197
    {
198
        return strtolower($key);
199
    }
200
}
201