Subversion Repositories php-qbpwcf

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 liveuser 1
<?php
2
 
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <fabien@symfony.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
 
12
namespace Symfony\Component\HttpFoundation;
13
 
14
/**
15
 * HeaderBag is a container for HTTP headers.
16
 *
17
 * @author Fabien Potencier <fabien@symfony.com>
18
 */
19
class HeaderBag implements \IteratorAggregate, \Countable
20
{
21
    protected const UPPER = '_ABCDEFGHIJKLMNOPQRSTUVWXYZ';
22
    protected const LOWER = '-abcdefghijklmnopqrstuvwxyz';
23
 
24
    protected $headers = [];
25
    protected $cacheControl = [];
26
 
27
    public function __construct(array $headers = [])
28
    {
29
        foreach ($headers as $key => $values) {
30
            $this->set($key, $values);
31
        }
32
    }
33
 
34
    /**
35
     * Returns the headers as a string.
36
     *
37
     * @return string The headers
38
     */
39
    public function __toString()
40
    {
41
        if (!$headers = $this->all()) {
42
            return '';
43
        }
44
 
45
        ksort($headers);
46
        $max = max(array_map('strlen', array_keys($headers))) + 1;
47
        $content = '';
48
        foreach ($headers as $name => $values) {
49
            $name = ucwords($name, '-');
50
            foreach ($values as $value) {
51
                $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value);
52
            }
53
        }
54
 
55
        return $content;
56
    }
57
 
58
    /**
59
     * Returns the headers.
60
     *
61
     * @param string|null $key The name of the headers to return or null to get them all
62
     *
63
     * @return array An array of headers
64
     */
65
    public function all(string $key = null)
66
    {
67
        if (null !== $key) {
68
            return $this->headers[strtr($key, self::UPPER, self::LOWER)] ?? [];
69
        }
70
 
71
        return $this->headers;
72
    }
73
 
74
    /**
75
     * Returns the parameter keys.
76
     *
77
     * @return array An array of parameter keys
78
     */
79
    public function keys()
80
    {
81
        return array_keys($this->all());
82
    }
83
 
84
    /**
85
     * Replaces the current HTTP headers by a new set.
86
     */
87
    public function replace(array $headers = [])
88
    {
89
        $this->headers = [];
90
        $this->add($headers);
91
    }
92
 
93
    /**
94
     * Adds new headers the current HTTP headers set.
95
     */
96
    public function add(array $headers)
97
    {
98
        foreach ($headers as $key => $values) {
99
            $this->set($key, $values);
100
        }
101
    }
102
 
103
    /**
104
     * Returns a header value by name.
105
     *
106
     * @return string|null The first header value or default value
107
     */
108
    public function get(string $key, string $default = null)
109
    {
110
        $headers = $this->all($key);
111
 
112
        if (!$headers) {
113
            return $default;
114
        }
115
 
116
        if (null === $headers[0]) {
117
            return null;
118
        }
119
 
120
        return (string) $headers[0];
121
    }
122
 
123
    /**
124
     * Sets a header by name.
125
     *
126
     * @param string|string[] $values  The value or an array of values
127
     * @param bool            $replace Whether to replace the actual value or not (true by default)
128
     */
129
    public function set(string $key, $values, bool $replace = true)
130
    {
131
        $key = strtr($key, self::UPPER, self::LOWER);
132
 
133
        if (\is_array($values)) {
134
            $values = array_values($values);
135
 
136
            if (true === $replace || !isset($this->headers[$key])) {
137
                $this->headers[$key] = $values;
138
            } else {
139
                $this->headers[$key] = array_merge($this->headers[$key], $values);
140
            }
141
        } else {
142
            if (true === $replace || !isset($this->headers[$key])) {
143
                $this->headers[$key] = [$values];
144
            } else {
145
                $this->headers[$key][] = $values;
146
            }
147
        }
148
 
149
        if ('cache-control' === $key) {
150
            $this->cacheControl = $this->parseCacheControl(implode(', ', $this->headers[$key]));
151
        }
152
    }
153
 
154
    /**
155
     * Returns true if the HTTP header is defined.
156
     *
157
     * @return bool true if the parameter exists, false otherwise
158
     */
159
    public function has(string $key)
160
    {
161
        return \array_key_exists(strtr($key, self::UPPER, self::LOWER), $this->all());
162
    }
163
 
164
    /**
165
     * Returns true if the given HTTP header contains the given value.
166
     *
167
     * @return bool true if the value is contained in the header, false otherwise
168
     */
169
    public function contains(string $key, string $value)
170
    {
171
        return \in_array($value, $this->all($key));
172
    }
173
 
174
    /**
175
     * Removes a header.
176
     */
177
    public function remove(string $key)
178
    {
179
        $key = strtr($key, self::UPPER, self::LOWER);
180
 
181
        unset($this->headers[$key]);
182
 
183
        if ('cache-control' === $key) {
184
            $this->cacheControl = [];
185
        }
186
    }
187
 
188
    /**
189
     * Returns the HTTP header value converted to a date.
190
     *
191
     * @return \DateTimeInterface|null The parsed DateTime or the default value if the header does not exist
192
     *
193
     * @throws \RuntimeException When the HTTP header is not parseable
194
     */
195
    public function getDate(string $key, \DateTime $default = null)
196
    {
197
        if (null === $value = $this->get($key)) {
198
            return $default;
199
        }
200
 
201
        if (false === $date = \DateTime::createFromFormat(\DATE_RFC2822, $value)) {
202
            throw new \RuntimeException(sprintf('The "%s" HTTP header is not parseable (%s).', $key, $value));
203
        }
204
 
205
        return $date;
206
    }
207
 
208
    /**
209
     * Adds a custom Cache-Control directive.
210
     *
211
     * @param mixed $value The Cache-Control directive value
212
     */
213
    public function addCacheControlDirective(string $key, $value = true)
214
    {
215
        $this->cacheControl[$key] = $value;
216
 
217
        $this->set('Cache-Control', $this->getCacheControlHeader());
218
    }
219
 
220
    /**
221
     * Returns true if the Cache-Control directive is defined.
222
     *
223
     * @return bool true if the directive exists, false otherwise
224
     */
225
    public function hasCacheControlDirective(string $key)
226
    {
227
        return \array_key_exists($key, $this->cacheControl);
228
    }
229
 
230
    /**
231
     * Returns a Cache-Control directive value by name.
232
     *
233
     * @return mixed|null The directive value if defined, null otherwise
234
     */
235
    public function getCacheControlDirective(string $key)
236
    {
237
        return \array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null;
238
    }
239
 
240
    /**
241
     * Removes a Cache-Control directive.
242
     */
243
    public function removeCacheControlDirective(string $key)
244
    {
245
        unset($this->cacheControl[$key]);
246
 
247
        $this->set('Cache-Control', $this->getCacheControlHeader());
248
    }
249
 
250
    /**
251
     * Returns an iterator for headers.
252
     *
253
     * @return \ArrayIterator An \ArrayIterator instance
254
     */
255
    public function getIterator()
256
    {
257
        return new \ArrayIterator($this->headers);
258
    }
259
 
260
    /**
261
     * Returns the number of headers.
262
     *
263
     * @return int The number of headers
264
     */
265
    public function count()
266
    {
267
        return \count($this->headers);
268
    }
269
 
270
    protected function getCacheControlHeader()
271
    {
272
        ksort($this->cacheControl);
273
 
274
        return HeaderUtils::toString($this->cacheControl, ',');
275
    }
276
 
277
    /**
278
     * Parses a Cache-Control HTTP header.
279
     *
280
     * @return array An array representing the attribute values
281
     */
282
    protected function parseCacheControl(string $header)
283
    {
284
        $parts = HeaderUtils::split($header, ',=');
285
 
286
        return HeaderUtils::combine($parts);
287
    }
288
}