Completed
Push — 5.x ( 831ff0...27843f )
by Lars
15:22 queued 08:41
created

Swift_Mime_SimpleHeaderSet   C

Complexity

Total Complexity 58

Size/Duplication

Total Lines 444
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 94.52%
Metric Value
wmc 58
lcom 1
cbo 3
dl 0
loc 444
ccs 138
cts 146
cp 0.9452
rs 6.3006

27 Methods

Rating   Name   Duplication   Size   Complexity  
A setCharset() 0 6 1
A __construct() 0 7 2
A addMailboxHeader() 0 4 1
A addDateHeader() 0 4 1
A addTextHeader() 0 4 1
A addParameterizedHeader() 0 4 1
A addIdHeader() 0 4 1
A addPathHeader() 0 4 1
A set() 0 4 1
A get() 0 8 2
A removeAll() 0 5 1
A newInstance() 0 4 1
A defineOrdering() 0 4 1
A setAlwaysDisplayed() 0 4 1
A charsetChanged() 0 4 1
A __toString() 0 4 1
A _canSort() 0 4 1
B _sortHeaders() 0 20 9
A _isDisplayed() 0 8 2
A has() 0 14 3
A getAll() 0 18 4
A remove() 0 11 3
B toString() 0 18 6
A _storeHeader() 0 12 3
A _notifyHeadersOfCharset() 0 9 3
A __clone() 0 12 4
A listAll() 0 9 2

How to fix   Complexity   

Complex Class

Complex classes like Swift_Mime_SimpleHeaderSet often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Swift_Mime_SimpleHeaderSet, and based on these observations, apply Extract Interface, too.

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
 * A collection of MIME headers.
13
 *
14
 * @author Chris Corbyn
15
 */
16
class Swift_Mime_SimpleHeaderSet implements Swift_Mime_HeaderSet
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

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