Mercurial > hg > isophonics-drupal-site
comparison vendor/symfony/http-foundation/ResponseHeaderBag.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 1fec387a4317 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
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 * ResponseHeaderBag is a container for Response HTTP headers. | |
16 * | |
17 * @author Fabien Potencier <fabien@symfony.com> | |
18 */ | |
19 class ResponseHeaderBag extends HeaderBag | |
20 { | |
21 const COOKIES_FLAT = 'flat'; | |
22 const COOKIES_ARRAY = 'array'; | |
23 | |
24 const DISPOSITION_ATTACHMENT = 'attachment'; | |
25 const DISPOSITION_INLINE = 'inline'; | |
26 | |
27 /** | |
28 * @var array | |
29 */ | |
30 protected $computedCacheControl = array(); | |
31 | |
32 /** | |
33 * @var array | |
34 */ | |
35 protected $cookies = array(); | |
36 | |
37 /** | |
38 * @var array | |
39 */ | |
40 protected $headerNames = array(); | |
41 | |
42 /** | |
43 * Constructor. | |
44 * | |
45 * @param array $headers An array of HTTP headers | |
46 */ | |
47 public function __construct(array $headers = array()) | |
48 { | |
49 parent::__construct($headers); | |
50 | |
51 if (!isset($this->headers['cache-control'])) { | |
52 $this->set('Cache-Control', ''); | |
53 } | |
54 } | |
55 | |
56 /** | |
57 * {@inheritdoc} | |
58 */ | |
59 public function __toString() | |
60 { | |
61 $cookies = ''; | |
62 foreach ($this->getCookies() as $cookie) { | |
63 $cookies .= 'Set-Cookie: '.$cookie."\r\n"; | |
64 } | |
65 | |
66 ksort($this->headerNames); | |
67 | |
68 return parent::__toString().$cookies; | |
69 } | |
70 | |
71 /** | |
72 * Returns the headers, with original capitalizations. | |
73 * | |
74 * @return array An array of headers | |
75 */ | |
76 public function allPreserveCase() | |
77 { | |
78 return array_combine($this->headerNames, $this->headers); | |
79 } | |
80 | |
81 /** | |
82 * {@inheritdoc} | |
83 */ | |
84 public function replace(array $headers = array()) | |
85 { | |
86 $this->headerNames = array(); | |
87 | |
88 parent::replace($headers); | |
89 | |
90 if (!isset($this->headers['cache-control'])) { | |
91 $this->set('Cache-Control', ''); | |
92 } | |
93 } | |
94 | |
95 /** | |
96 * {@inheritdoc} | |
97 */ | |
98 public function set($key, $values, $replace = true) | |
99 { | |
100 parent::set($key, $values, $replace); | |
101 | |
102 $uniqueKey = str_replace('_', '-', strtolower($key)); | |
103 $this->headerNames[$uniqueKey] = $key; | |
104 | |
105 // ensure the cache-control header has sensible defaults | |
106 if (in_array($uniqueKey, array('cache-control', 'etag', 'last-modified', 'expires'))) { | |
107 $computed = $this->computeCacheControlValue(); | |
108 $this->headers['cache-control'] = array($computed); | |
109 $this->headerNames['cache-control'] = 'Cache-Control'; | |
110 $this->computedCacheControl = $this->parseCacheControl($computed); | |
111 } | |
112 } | |
113 | |
114 /** | |
115 * {@inheritdoc} | |
116 */ | |
117 public function remove($key) | |
118 { | |
119 parent::remove($key); | |
120 | |
121 $uniqueKey = str_replace('_', '-', strtolower($key)); | |
122 unset($this->headerNames[$uniqueKey]); | |
123 | |
124 if ('cache-control' === $uniqueKey) { | |
125 $this->computedCacheControl = array(); | |
126 } | |
127 } | |
128 | |
129 /** | |
130 * {@inheritdoc} | |
131 */ | |
132 public function hasCacheControlDirective($key) | |
133 { | |
134 return array_key_exists($key, $this->computedCacheControl); | |
135 } | |
136 | |
137 /** | |
138 * {@inheritdoc} | |
139 */ | |
140 public function getCacheControlDirective($key) | |
141 { | |
142 return array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null; | |
143 } | |
144 | |
145 /** | |
146 * Sets a cookie. | |
147 * | |
148 * @param Cookie $cookie | |
149 */ | |
150 public function setCookie(Cookie $cookie) | |
151 { | |
152 $this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie; | |
153 } | |
154 | |
155 /** | |
156 * Removes a cookie from the array, but does not unset it in the browser. | |
157 * | |
158 * @param string $name | |
159 * @param string $path | |
160 * @param string $domain | |
161 */ | |
162 public function removeCookie($name, $path = '/', $domain = null) | |
163 { | |
164 if (null === $path) { | |
165 $path = '/'; | |
166 } | |
167 | |
168 unset($this->cookies[$domain][$path][$name]); | |
169 | |
170 if (empty($this->cookies[$domain][$path])) { | |
171 unset($this->cookies[$domain][$path]); | |
172 | |
173 if (empty($this->cookies[$domain])) { | |
174 unset($this->cookies[$domain]); | |
175 } | |
176 } | |
177 } | |
178 | |
179 /** | |
180 * Returns an array with all cookies. | |
181 * | |
182 * @param string $format | |
183 * | |
184 * @return array | |
185 * | |
186 * @throws \InvalidArgumentException When the $format is invalid | |
187 */ | |
188 public function getCookies($format = self::COOKIES_FLAT) | |
189 { | |
190 if (!in_array($format, array(self::COOKIES_FLAT, self::COOKIES_ARRAY))) { | |
191 throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', array(self::COOKIES_FLAT, self::COOKIES_ARRAY)))); | |
192 } | |
193 | |
194 if (self::COOKIES_ARRAY === $format) { | |
195 return $this->cookies; | |
196 } | |
197 | |
198 $flattenedCookies = array(); | |
199 foreach ($this->cookies as $path) { | |
200 foreach ($path as $cookies) { | |
201 foreach ($cookies as $cookie) { | |
202 $flattenedCookies[] = $cookie; | |
203 } | |
204 } | |
205 } | |
206 | |
207 return $flattenedCookies; | |
208 } | |
209 | |
210 /** | |
211 * Clears a cookie in the browser. | |
212 * | |
213 * @param string $name | |
214 * @param string $path | |
215 * @param string $domain | |
216 * @param bool $secure | |
217 * @param bool $httpOnly | |
218 */ | |
219 public function clearCookie($name, $path = '/', $domain = null, $secure = false, $httpOnly = true) | |
220 { | |
221 $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly)); | |
222 } | |
223 | |
224 /** | |
225 * Generates a HTTP Content-Disposition field-value. | |
226 * | |
227 * @param string $disposition One of "inline" or "attachment" | |
228 * @param string $filename A unicode string | |
229 * @param string $filenameFallback A string containing only ASCII characters that | |
230 * is semantically equivalent to $filename. If the filename is already ASCII, | |
231 * it can be omitted, or just copied from $filename | |
232 * | |
233 * @return string A string suitable for use as a Content-Disposition field-value | |
234 * | |
235 * @throws \InvalidArgumentException | |
236 * | |
237 * @see RFC 6266 | |
238 */ | |
239 public function makeDisposition($disposition, $filename, $filenameFallback = '') | |
240 { | |
241 if (!in_array($disposition, array(self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE))) { | |
242 throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE)); | |
243 } | |
244 | |
245 if ('' == $filenameFallback) { | |
246 $filenameFallback = $filename; | |
247 } | |
248 | |
249 // filenameFallback is not ASCII. | |
250 if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) { | |
251 throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.'); | |
252 } | |
253 | |
254 // percent characters aren't safe in fallback. | |
255 if (false !== strpos($filenameFallback, '%')) { | |
256 throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.'); | |
257 } | |
258 | |
259 // path separators aren't allowed in either. | |
260 if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) { | |
261 throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.'); | |
262 } | |
263 | |
264 $output = sprintf('%s; filename="%s"', $disposition, str_replace('"', '\\"', $filenameFallback)); | |
265 | |
266 if ($filename !== $filenameFallback) { | |
267 $output .= sprintf("; filename*=utf-8''%s", rawurlencode($filename)); | |
268 } | |
269 | |
270 return $output; | |
271 } | |
272 | |
273 /** | |
274 * Returns the calculated value of the cache-control header. | |
275 * | |
276 * This considers several other headers and calculates or modifies the | |
277 * cache-control header to a sensible, conservative value. | |
278 * | |
279 * @return string | |
280 */ | |
281 protected function computeCacheControlValue() | |
282 { | |
283 if (!$this->cacheControl && !$this->has('ETag') && !$this->has('Last-Modified') && !$this->has('Expires')) { | |
284 return 'no-cache, private'; | |
285 } | |
286 | |
287 if (!$this->cacheControl) { | |
288 // conservative by default | |
289 return 'private, must-revalidate'; | |
290 } | |
291 | |
292 $header = $this->getCacheControlHeader(); | |
293 if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) { | |
294 return $header; | |
295 } | |
296 | |
297 // public if s-maxage is defined, private otherwise | |
298 if (!isset($this->cacheControl['s-maxage'])) { | |
299 return $header.', private'; | |
300 } | |
301 | |
302 return $header; | |
303 } | |
304 } |