Projekt

Obecné

Profil

Stáhnout (8.46 KB) Statistiky
| Větev: | Revize:
1 cb15593b Cajova-Houba
<?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 $headers = array();
22
    protected $cacheControl = array();
23
24
    /**
25
     * Constructor.
26
     *
27
     * @param array $headers An array of HTTP headers
28
     */
29
    public function __construct(array $headers = array())
30
    {
31
        foreach ($headers as $key => $values) {
32
            $this->set($key, $values);
33
        }
34
    }
35
36
    /**
37
     * Returns the headers as a string.
38
     *
39
     * @return string The headers
40
     */
41
    public function __toString()
42
    {
43
        if (!$this->headers) {
44
            return '';
45
        }
46
47
        $max = max(array_map('strlen', array_keys($this->headers))) + 1;
48
        $content = '';
49
        ksort($this->headers);
50
        foreach ($this->headers as $name => $values) {
51
            $name = implode('-', array_map('ucfirst', explode('-', $name)));
52
            foreach ($values as $value) {
53
                $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value);
54
            }
55
        }
56
57
        return $content;
58
    }
59
60
    /**
61
     * Returns the headers.
62
     *
63
     * @return array An array of headers
64
     */
65
    public function all()
66
    {
67
        return $this->headers;
68
    }
69
70
    /**
71
     * Returns the parameter keys.
72
     *
73
     * @return array An array of parameter keys
74
     */
75
    public function keys()
76
    {
77
        return array_keys($this->headers);
78
    }
79
80
    /**
81
     * Replaces the current HTTP headers by a new set.
82
     *
83
     * @param array $headers An array of HTTP headers
84
     */
85
    public function replace(array $headers = array())
86
    {
87
        $this->headers = array();
88
        $this->add($headers);
89
    }
90
91
    /**
92
     * Adds new headers the current HTTP headers set.
93
     *
94
     * @param array $headers An array of HTTP headers
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
     * @param string $key     The header name
107
     * @param mixed  $default The default value
108
     * @param bool   $first   Whether to return the first value or all header values
109
     *
110
     * @return string|array The first header value if $first is true, an array of values otherwise
111
     */
112
    public function get($key, $default = null, $first = true)
113
    {
114
        $key = str_replace('_', '-', strtolower($key));
115
116
        if (!array_key_exists($key, $this->headers)) {
117
            if (null === $default) {
118
                return $first ? null : array();
119
            }
120
121
            return $first ? $default : array($default);
122
        }
123
124
        if ($first) {
125
            return count($this->headers[$key]) ? $this->headers[$key][0] : $default;
126
        }
127
128
        return $this->headers[$key];
129
    }
130
131
    /**
132
     * Sets a header by name.
133
     *
134
     * @param string       $key     The key
135
     * @param string|array $values  The value or an array of values
136
     * @param bool         $replace Whether to replace the actual value or not (true by default)
137
     */
138
    public function set($key, $values, $replace = true)
139
    {
140
        $key = str_replace('_', '-', strtolower($key));
141
142
        $values = array_values((array) $values);
143
144
        if (true === $replace || !isset($this->headers[$key])) {
145
            $this->headers[$key] = $values;
146
        } else {
147
            $this->headers[$key] = array_merge($this->headers[$key], $values);
148
        }
149
150
        if ('cache-control' === $key) {
151
            $this->cacheControl = $this->parseCacheControl($values[0]);
152
        }
153
    }
154
155
    /**
156
     * Returns true if the HTTP header is defined.
157
     *
158
     * @param string $key The HTTP header
159
     *
160
     * @return bool true if the parameter exists, false otherwise
161
     */
162
    public function has($key)
163
    {
164
        return array_key_exists(str_replace('_', '-', strtolower($key)), $this->headers);
165
    }
166
167
    /**
168
     * Returns true if the given HTTP header contains the given value.
169
     *
170
     * @param string $key   The HTTP header name
171
     * @param string $value The HTTP value
172
     *
173
     * @return bool true if the value is contained in the header, false otherwise
174
     */
175
    public function contains($key, $value)
176
    {
177
        return in_array($value, $this->get($key, null, false));
178
    }
179
180
    /**
181
     * Removes a header.
182
     *
183
     * @param string $key The HTTP header name
184
     */
185
    public function remove($key)
186
    {
187
        $key = str_replace('_', '-', strtolower($key));
188
189
        unset($this->headers[$key]);
190
191
        if ('cache-control' === $key) {
192
            $this->cacheControl = array();
193
        }
194
    }
195
196
    /**
197
     * Returns the HTTP header value converted to a date.
198
     *
199
     * @param string    $key     The parameter key
200
     * @param \DateTime $default The default value
201
     *
202
     * @return null|\DateTime The parsed DateTime or the default value if the header does not exist
203
     *
204
     * @throws \RuntimeException When the HTTP header is not parseable
205
     */
206
    public function getDate($key, \DateTime $default = null)
207
    {
208
        if (null === $value = $this->get($key)) {
209
            return $default;
210
        }
211
212
        if (false === $date = \DateTime::createFromFormat(DATE_RFC2822, $value)) {
213
            throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value));
214
        }
215
216
        return $date;
217
    }
218
219
    /**
220
     * Adds a custom Cache-Control directive.
221
     *
222
     * @param string $key   The Cache-Control directive name
223
     * @param mixed  $value The Cache-Control directive value
224
     */
225
    public function addCacheControlDirective($key, $value = true)
226
    {
227
        $this->cacheControl[$key] = $value;
228
229
        $this->set('Cache-Control', $this->getCacheControlHeader());
230
    }
231
232
    /**
233
     * Returns true if the Cache-Control directive is defined.
234
     *
235
     * @param string $key The Cache-Control directive
236
     *
237
     * @return bool true if the directive exists, false otherwise
238
     */
239
    public function hasCacheControlDirective($key)
240
    {
241
        return array_key_exists($key, $this->cacheControl);
242
    }
243
244
    /**
245
     * Returns a Cache-Control directive value by name.
246
     *
247
     * @param string $key The directive name
248
     *
249
     * @return mixed|null The directive value if defined, null otherwise
250
     */
251
    public function getCacheControlDirective($key)
252
    {
253
        return array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null;
254
    }
255
256
    /**
257
     * Removes a Cache-Control directive.
258
     *
259
     * @param string $key The Cache-Control directive
260
     */
261
    public function removeCacheControlDirective($key)
262
    {
263
        unset($this->cacheControl[$key]);
264
265
        $this->set('Cache-Control', $this->getCacheControlHeader());
266
    }
267
268
    /**
269
     * Returns an iterator for headers.
270
     *
271
     * @return \ArrayIterator An \ArrayIterator instance
272
     */
273
    public function getIterator()
274
    {
275
        return new \ArrayIterator($this->headers);
276
    }
277
278
    /**
279
     * Returns the number of headers.
280
     *
281
     * @return int The number of headers
282
     */
283
    public function count()
284
    {
285
        return count($this->headers);
286
    }
287
288
    protected function getCacheControlHeader()
289
    {
290
        $parts = array();
291
        ksort($this->cacheControl);
292
        foreach ($this->cacheControl as $key => $value) {
293
            if (true === $value) {
294
                $parts[] = $key;
295
            } else {
296
                if (preg_match('#[^a-zA-Z0-9._-]#', $value)) {
297
                    $value = '"'.$value.'"';
298
                }
299
300
                $parts[] = "$key=$value";
301
            }
302
        }
303
304
        return implode(', ', $parts);
305
    }
306
307
    /**
308
     * Parses a Cache-Control HTTP header.
309
     *
310
     * @param string $header The value of the Cache-Control HTTP header
311
     *
312
     * @return array An array representing the attribute values
313
     */
314
    protected function parseCacheControl($header)
315
    {
316
        $cacheControl = array();
317
        preg_match_all('#([a-zA-Z][a-zA-Z_-]*)\s*(?:=(?:"([^"]*)"|([^ \t",;]*)))?#', $header, $matches, PREG_SET_ORDER);
318
        foreach ($matches as $match) {
319
            $cacheControl[strtolower($match[1])] = isset($match[3]) ? $match[3] : (isset($match[2]) ? $match[2] : true);
320
        }
321
322
        return $cacheControl;
323
    }
324
}