HeaderBag::fromServer()   B
last analyzed

Complexity

Conditions 6
Paths 8

Size

Total Lines 29
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 8.439
c 0
b 0
f 0
cc 6
eloc 17
nc 8
nop 1
1
<?php
2
/*
3
 * This file is part of the Borobudur-Http package.
4
 *
5
 * (c) Hexacodelabs <http://hexacodelabs.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Borobudur\Http;
12
13
use Borobudur\Http\Exception\InvalidArgumentException;
14
use Borobudur\Http\Header\GenericHeader;
15
use Borobudur\Http\Header\HeaderInterface;
16
17
/**
18
 * @author      Iqbal Maulana <[email protected]>
19
 * @created     7/28/15
20
 */
21
class HeaderBag extends AbstractParameterBag
22
{
23
    /**
24
     * @var HeaderInterface[]
25
     */
26
    protected $parameters = array();
27
28
    /**
29
     * @var bool
30
     */
31
    private $sorted = false;
32
33
    /**
34
     * Build HeaderBag from Server variables ($_SERVER).
35
     *
36
     * @param array $headers
37
     *
38
     * @return HeaderBag
39
     */
40
    public static function fromServer(array $headers)
41
    {
42
        $headerBag = new HeaderBag();
43
        foreach ($headers as $name => $values) {
44
            foreach ((array) $values as $value) {
45
                $parts = explode('-', str_replace('_', '-', strtolower($name)));
46
                $name = implode('-', array_map('ucfirst', $parts));
47
                $namespace = 'Borobudur\Http\Header';
48
                
49
                if (0 === strpos($name, 'Accept')) {
50
                    $namespace = sprintf('%s\Accept', $namespace);
51
                } elseif (0 === strpos($name, 'Content')) {
52
                    $namespace = sprintf('%s\Content', $namespace);
53
                }
54
    
55
                $class = sprintf('%s\%sHeader', $namespace, str_replace('-', '', $name));
56
                if (class_exists($class)) {
57
                    /**
58
                     * @var HeaderInterface $class
59
                     */
60
                    $headerBag->set($class::fromString(sprintf('%s: %s', $name, $value)), true);
61
                } else {
62
                    $headerBag->set(new GenericHeader($name, $value), true);
63
                }
64
            }
65
        }
66
67
        return $headerBag;
68
    }
69
70
    /**
71
     * Add sets of header.
72
     *
73
     * @param HeaderInterface[] $headers
74
     * @param bool              $replace
75
     *
76
     * @return $this
77
     *
78
     * @throws InvalidArgumentException
79
     */
80
    public function add(array $headers, $replace = false)
81
    {
82
        foreach ($headers as $header) {
83
            if (is_array($header)) {
84
                $this->add($header);
85
                continue;
86
            }
87
            
88
            if (false === $header instanceof HeaderInterface) {
89
                throw new InvalidArgumentException(sprintf(
90
                    'Header should implement "%s".',
91
                    'Borobudur\Http\Header\HeaderInterface'
92
                ));
93
            }
94
95
            $this->set($header, $replace);
96
        }
97
98
        return $this;
99
    }
100
101
    /**
102
     * Set header.
103
     *
104
     * @param HeaderInterface $header
105
     * @param bool            $replace
106
     *
107
     * @return $this
108
     */
109
    public function set(HeaderInterface $header, $replace = false)
110
    {
111
        $headerName = strtolower($header->getFieldName());
112
113
        if (false === $this->has($headerName) || true === $replace) {
114
            $this->parameters[$headerName] = array();
115
        }
116
117
        $this->parameters[$headerName][] = $header;
118
        $this->sorted = false;
119
120
        return $this;
121
    }
122
123
    /**
124
     * Check if header exist by header name.
125
     *
126
     * @param string $headerName
127
     *
128
     * @return bool
129
     */
130
    public function has($headerName)
131
    {
132
        return array_key_exists(strtolower($headerName), $this->parameters);
133
    }
134
135
    /**
136
     * Get first header by header name or return default value if not exist.
137
     *
138
     * @param string $headerName
139
     * @param mixed  $default
140
     *
141
     * @return HeaderInterface|null
142
     */
143
    public function first($headerName, $default = null)
144
    {
145
        if (null !== $headers = $this->get($headerName)) {
146
            return $headers[0];
147
        }
148
149
        return $default;
150
    }
151
152
    /**
153
     * Get headers by name or return default value if not exist.
154
     *
155
     * @param string $headerName
156
     * @param mixed  $default
157
     *
158
     * @return HeaderInterface[]|mixed
159
     */
160
    public function get($headerName, $default = null)
161
    {
162
        return parent::get(strtolower($headerName), $default);
163
    }
164
165
    /**
166
     * Get all headers.
167
     *
168
     * @return array
169
     */
170
    public function all()
171
    {
172
        $this->sort();
173
174
        return array_values($this->parameters);
175
    }
176
177
    /**
178
     * Get all header names.
179
     *
180
     * @return array
181
     */
182
    public function keys()
183
    {
184
        $this->sort();
185
        $keys = array();
186
187
        foreach ($this->parameters as $header) {
188
            $header = $header[0];
189
190
            if ($header instanceof HeaderInterface) {
191
                $keys[] = $header->getFieldName();
192
            }
193
        }
194
195
        return $keys;
196
    }
197
198
    /**
199
     * Remove header by header name.
200
     *
201
     * @param string $headerName
202
     *
203
     * @return $this
204
     */
205
    public function remove($headerName)
206
    {
207
        return parent::remove(strtolower($headerName));
208
    }
209
210
    /**
211
     * Cast HeaderBag to string representation.
212
     *
213
     * @return string
214
     */
215
    public function __toString()
216
    {
217
        $this->sort();
218
219
        return implode("\r\n", array_map(function (array $item) {
220
            return implode("\r\n", array_map(function (HeaderInterface $header) {
221
                return (string) $header;
222
            }, $item));
223
        }, $this->parameters));
224
    }
225
226
    /**
227
     * Sort headers by name.
228
     */
229
    private function sort()
230
    {
231
        if (false === $this->sorted) {
232
            ksort($this->parameters);
233
            $this->sorted = true;
234
        }
235
    }
236
}
237