|
1 <?php |
|
2 |
|
3 /* |
|
4 * This file is part of SwiftMailer. |
|
5 * (c) 2004-2009 Chris Corbyn |
|
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 |
|
12 /** |
|
13 * A collection of MIME headers. |
|
14 * |
|
15 * @package Swift |
|
16 * @subpackage Mime |
|
17 * |
|
18 * @author Chris Corbyn |
|
19 */ |
|
20 class Swift_Mime_SimpleHeaderSet implements Swift_Mime_HeaderSet |
|
21 { |
|
22 |
|
23 /** HeaderFactory */ |
|
24 private $_factory; |
|
25 |
|
26 /** Collection of set Headers */ |
|
27 private $_headers = array(); |
|
28 |
|
29 /** Field ordering details */ |
|
30 private $_order = array(); |
|
31 |
|
32 /** List of fields which are required to be displayed */ |
|
33 private $_required = array(); |
|
34 |
|
35 /** The charset used by Headers */ |
|
36 private $_charset; |
|
37 |
|
38 /** |
|
39 * Create a new SimpleHeaderSet with the given $factory. |
|
40 * |
|
41 * @param Swift_Mime_HeaderFactory $factory |
|
42 * @param string $charset |
|
43 */ |
|
44 public function __construct(Swift_Mime_HeaderFactory $factory, |
|
45 $charset = null) |
|
46 { |
|
47 $this->_factory = $factory; |
|
48 if (isset($charset)) |
|
49 { |
|
50 $this->setCharset($charset); |
|
51 } |
|
52 } |
|
53 |
|
54 /** |
|
55 * Set the charset used by these headers. |
|
56 * |
|
57 * @param string $charset |
|
58 */ |
|
59 public function setCharset($charset) |
|
60 { |
|
61 $this->_charset = $charset; |
|
62 $this->_factory->charsetChanged($charset); |
|
63 $this->_notifyHeadersOfCharset($charset); |
|
64 } |
|
65 |
|
66 /** |
|
67 * Add a new Mailbox Header with a list of $addresses. |
|
68 * |
|
69 * @param string $name |
|
70 * @param array|string $addresses |
|
71 */ |
|
72 public function addMailboxHeader($name, $addresses = null) |
|
73 { |
|
74 $this->_storeHeader($name, |
|
75 $this->_factory->createMailboxHeader($name, $addresses)); |
|
76 } |
|
77 |
|
78 /** |
|
79 * Add a new Date header using $timestamp (UNIX time). |
|
80 * |
|
81 * @param string $name |
|
82 * @param int $timestamp |
|
83 */ |
|
84 public function addDateHeader($name, $timestamp = null) |
|
85 { |
|
86 $this->_storeHeader($name, |
|
87 $this->_factory->createDateHeader($name, $timestamp)); |
|
88 } |
|
89 |
|
90 /** |
|
91 * Add a new basic text header with $name and $value. |
|
92 * |
|
93 * @param string $name |
|
94 * @param string $value |
|
95 */ |
|
96 public function addTextHeader($name, $value = null) |
|
97 { |
|
98 $this->_storeHeader($name, |
|
99 $this->_factory->createTextHeader($name, $value)); |
|
100 } |
|
101 |
|
102 /** |
|
103 * Add a new ParameterizedHeader with $name, $value and $params. |
|
104 * |
|
105 * @param string $name |
|
106 * @param string $value |
|
107 * @param array $params |
|
108 */ |
|
109 public function addParameterizedHeader($name, $value = null, |
|
110 $params = array()) |
|
111 { |
|
112 $this->_storeHeader($name, |
|
113 $this->_factory->createParameterizedHeader($name, $value, |
|
114 $params)); |
|
115 } |
|
116 |
|
117 /** |
|
118 * Add a new ID header for Message-ID or Content-ID. |
|
119 * |
|
120 * @param string $name |
|
121 * @param string|array $ids |
|
122 */ |
|
123 public function addIdHeader($name, $ids = null) |
|
124 { |
|
125 $this->_storeHeader($name, $this->_factory->createIdHeader($name, $ids)); |
|
126 } |
|
127 |
|
128 /** |
|
129 * Add a new Path header with an address (path) in it. |
|
130 * |
|
131 * @param string $name |
|
132 * @param string $path |
|
133 */ |
|
134 public function addPathHeader($name, $path = null) |
|
135 { |
|
136 $this->_storeHeader($name, $this->_factory->createPathHeader($name, $path)); |
|
137 } |
|
138 |
|
139 /** |
|
140 * Returns true if at least one header with the given $name exists. |
|
141 * |
|
142 * If multiple headers match, the actual one may be specified by $index. |
|
143 * |
|
144 * @param string $name |
|
145 * @param int $index |
|
146 * |
|
147 * @return boolean |
|
148 */ |
|
149 public function has($name, $index = 0) |
|
150 { |
|
151 $lowerName = strtolower($name); |
|
152 return array_key_exists($lowerName, $this->_headers) |
|
153 && array_key_exists($index, $this->_headers[$lowerName]); |
|
154 } |
|
155 |
|
156 /** |
|
157 * Set a header in the HeaderSet. |
|
158 * |
|
159 * The header may be a previously fetched header via {@link get()} or it may |
|
160 * be one that has been created separately. |
|
161 * |
|
162 * If $index is specified, the header will be inserted into the set at this |
|
163 * offset. |
|
164 * |
|
165 * @param Swift_Mime_Header $header |
|
166 * @param int $index |
|
167 */ |
|
168 public function set(Swift_Mime_Header $header, $index = 0) |
|
169 { |
|
170 $this->_storeHeader($header->getFieldName(), $header, $index); |
|
171 } |
|
172 |
|
173 /** |
|
174 * Get the header with the given $name. |
|
175 * |
|
176 * If multiple headers match, the actual one may be specified by $index. |
|
177 * Returns NULL if none present. |
|
178 * |
|
179 * @param string $name |
|
180 * @param int $index |
|
181 * |
|
182 * @return Swift_Mime_Header |
|
183 */ |
|
184 public function get($name, $index = 0) |
|
185 { |
|
186 if ($this->has($name, $index)) |
|
187 { |
|
188 $lowerName = strtolower($name); |
|
189 return $this->_headers[$lowerName][$index]; |
|
190 } |
|
191 } |
|
192 |
|
193 /** |
|
194 * Get all headers with the given $name. |
|
195 * |
|
196 * @param string $name |
|
197 * |
|
198 * @return array |
|
199 */ |
|
200 public function getAll($name = null) |
|
201 { |
|
202 if (!isset($name)) |
|
203 { |
|
204 $headers = array(); |
|
205 foreach ($this->_headers as $collection) |
|
206 { |
|
207 $headers = array_merge($headers, $collection); |
|
208 } |
|
209 return $headers; |
|
210 } |
|
211 |
|
212 $lowerName = strtolower($name); |
|
213 if (!array_key_exists($lowerName, $this->_headers)) |
|
214 { |
|
215 return array(); |
|
216 } |
|
217 return $this->_headers[$lowerName]; |
|
218 } |
|
219 |
|
220 /** |
|
221 * Remove the header with the given $name if it's set. |
|
222 * |
|
223 * If multiple headers match, the actual one may be specified by $index. |
|
224 * |
|
225 * @param string $name |
|
226 * @param int $index |
|
227 */ |
|
228 public function remove($name, $index = 0) |
|
229 { |
|
230 $lowerName = strtolower($name); |
|
231 unset($this->_headers[$lowerName][$index]); |
|
232 } |
|
233 |
|
234 /** |
|
235 * Remove all headers with the given $name. |
|
236 * |
|
237 * @param string $name |
|
238 */ |
|
239 public function removeAll($name) |
|
240 { |
|
241 $lowerName = strtolower($name); |
|
242 unset($this->_headers[$lowerName]); |
|
243 } |
|
244 |
|
245 /** |
|
246 * Create a new instance of this HeaderSet. |
|
247 * |
|
248 * @return Swift_Mime_HeaderSet |
|
249 */ |
|
250 public function newInstance() |
|
251 { |
|
252 return new self($this->_factory); |
|
253 } |
|
254 |
|
255 /** |
|
256 * Define a list of Header names as an array in the correct order. |
|
257 * |
|
258 * These Headers will be output in the given order where present. |
|
259 * |
|
260 * @param array $sequence |
|
261 */ |
|
262 public function defineOrdering(array $sequence) |
|
263 { |
|
264 $this->_order = array_flip(array_map('strtolower', $sequence)); |
|
265 } |
|
266 |
|
267 /** |
|
268 * Set a list of header names which must always be displayed when set. |
|
269 * |
|
270 * Usually headers without a field value won't be output unless set here. |
|
271 * |
|
272 * @param array $names |
|
273 */ |
|
274 public function setAlwaysDisplayed(array $names) |
|
275 { |
|
276 $this->_required = array_flip(array_map('strtolower', $names)); |
|
277 } |
|
278 |
|
279 /** |
|
280 * Notify this observer that the entity's charset has changed. |
|
281 * |
|
282 * @param string $charset |
|
283 */ |
|
284 public function charsetChanged($charset) |
|
285 { |
|
286 $this->setCharset($charset); |
|
287 } |
|
288 |
|
289 /** |
|
290 * Returns a string with a representation of all headers. |
|
291 * |
|
292 * @return string |
|
293 */ |
|
294 public function toString() |
|
295 { |
|
296 $string = ''; |
|
297 $headers = $this->_headers; |
|
298 if ($this->_canSort()) |
|
299 { |
|
300 uksort($headers, array($this, '_sortHeaders')); |
|
301 } |
|
302 foreach ($headers as $collection) |
|
303 { |
|
304 foreach ($collection as $header) |
|
305 { |
|
306 if ($this->_isDisplayed($header) || $header->getFieldBody() != '') |
|
307 { |
|
308 $string .= $header->toString(); |
|
309 } |
|
310 } |
|
311 } |
|
312 return $string; |
|
313 } |
|
314 |
|
315 /** |
|
316 * Returns a string representation of this object. |
|
317 * |
|
318 * @return string |
|
319 * |
|
320 * @see toString() |
|
321 */ |
|
322 public function __toString() |
|
323 { |
|
324 return $this->toString(); |
|
325 } |
|
326 |
|
327 // -- Private methods |
|
328 |
|
329 /** Save a Header to the internal collection */ |
|
330 private function _storeHeader($name, Swift_Mime_Header $header, $offset = null) |
|
331 { |
|
332 if (!isset($this->_headers[strtolower($name)])) |
|
333 { |
|
334 $this->_headers[strtolower($name)] = array(); |
|
335 } |
|
336 if (!isset($offset)) |
|
337 { |
|
338 $this->_headers[strtolower($name)][] = $header; |
|
339 } |
|
340 else |
|
341 { |
|
342 $this->_headers[strtolower($name)][$offset] = $header; |
|
343 } |
|
344 } |
|
345 |
|
346 /** Test if the headers can be sorted */ |
|
347 private function _canSort() |
|
348 { |
|
349 return count($this->_order) > 0; |
|
350 } |
|
351 |
|
352 /** uksort() algorithm for Header ordering */ |
|
353 private function _sortHeaders($a, $b) |
|
354 { |
|
355 $lowerA = strtolower($a); |
|
356 $lowerB = strtolower($b); |
|
357 $aPos = array_key_exists($lowerA, $this->_order) |
|
358 ? $this->_order[$lowerA] |
|
359 : -1; |
|
360 $bPos = array_key_exists($lowerB, $this->_order) |
|
361 ? $this->_order[$lowerB] |
|
362 : -1; |
|
363 |
|
364 if ($aPos == -1) |
|
365 { |
|
366 return 1; |
|
367 } |
|
368 elseif ($bPos == -1) |
|
369 { |
|
370 return -1; |
|
371 } |
|
372 |
|
373 return ($aPos < $bPos) ? -1 : 1; |
|
374 } |
|
375 |
|
376 /** Test if the given Header is always displayed */ |
|
377 private function _isDisplayed(Swift_Mime_Header $header) |
|
378 { |
|
379 return array_key_exists(strtolower($header->getFieldName()), $this->_required); |
|
380 } |
|
381 |
|
382 /** Notify all Headers of the new charset */ |
|
383 private function _notifyHeadersOfCharset($charset) |
|
384 { |
|
385 foreach ($this->_headers as $headerGroup) |
|
386 { |
|
387 foreach ($headerGroup as $header) |
|
388 { |
|
389 $header->setCharset($charset); |
|
390 } |
|
391 } |
|
392 } |
|
393 |
|
394 } |