Swift_Mime_Headers_AbstractHeader   C
last analyzed

Complexity

Total Complexity 63

Size/Duplication

Total Lines 511
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 96.65%

Importance

Changes 0
Metric Value
dl 0
loc 511
ccs 173
cts 179
cp 0.9665
rs 5.8893
c 0
b 0
f 0
wmc 63
lcom 1
cbo 3

27 Methods

Rating   Name   Duplication   Size   Complexity  
A getCharset() 0 4 1
A getLanguage() 0 4 1
A getEncoder() 0 4 1
A getFieldName() 0 4 1
A toString() 0 4 1
A __toString() 0 4 1
A setEncoder() 0 7 1
A __construct() 0 3 1
A getMaxLineLength() 0 4 1
A getCachedValue() 0 4 1
A setMaxLineLength() 0 12 3
A setFieldName() 0 4 1
A setCharset() 0 12 4
A setLanguage() 0 7 3
B createPhrase() 0 25 4
A escapeSpecials() 0 8 2
B encodeWords() 0 26 6
A tokenNeedsEncoding() 0 8 2
B getEncodableWordTokens() 0 24 5
B getTokenAsEncodedWord() 0 32 5
A generateTokenLines() 0 4 1
A setCachedValue() 0 4 1
A clearCachedValue() 0 4 1
A clearCachedValueIf() 0 6 2
A toTokens() 0 18 4
C _tokensToString() 0 36 7
A __clone() 0 6 2

How to fix   Complexity   

Complex Class

Complex classes like Swift_Mime_Headers_AbstractHeader 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_Headers_AbstractHeader, 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
 * An abstract base MIME Header.
13
 *
14
 * @author Chris Corbyn
15
 */
16
abstract class Swift_Mime_Headers_AbstractHeader implements Swift_Mime_Header
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
    const PHRASE_PATTERN = '(?:(?:(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]+(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?)|(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?"((?:(?:[ \t]*(?:\r\n))?[ \t])?(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])))*(?:(?:[ \t]*(?:\r\n))?[ \t])?"(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?))+?)';
19
20
    /**
21
     * The name of this Header.
22
     *
23
     * @var string
24
     */
25
    private $_name;
26
27
    /**
28
     * The Encoder used to encode this Header.
29
     *
30
     * @var Swift_Mime_HeaderEncoder
31
     */
32
    private $_encoder;
33
34
    /**
35
     * The maximum length of a line in the header.
36
     *
37
     * @var int
38
     */
39
    private $_lineLength = 78;
40
41
    /**
42
     * The language used in this Header.
43
     *
44
     * @var string|null
45
     */
46
    private $_lang;
47
48
    /**
49
     * The character set of the text in this Header.
50
     *
51
     * @var string
52
     */
53
    private $_charset = 'utf-8';
54
55
    /**
56
     * The value of this Header, cached.
57
     *
58
     * @var string|null
59
     */
60
    private $_cachedValue;
61
62
    /**
63
     * Creates a new Header.
64
     */
65 294
    public function __construct()
66
    {
67 294
    }
68
69
    /**
70
     * Set the character set used in this Header.
71
     *
72
     * @param string $charset
73
     */
74 169
    public function setCharset($charset)
75
    {
76 169
        if ($charset && $charset !== $this->_charset) {
77 55
            $this->clearCachedValue();
78
79 55
            $this->_charset = $charset;
80
81 55
            if ($this->_encoder) {
82 55
                $this->_encoder->charsetChanged($charset);
83 55
            }
84 55
        }
85 169
    }
86
87
    /**
88
     * Get the character set used in this Header.
89
     *
90
     * @return string
91
     */
92 115
    public function getCharset()
93
    {
94 115
        return $this->_charset;
95
    }
96
97
    /**
98
     * Set the language used in this Header.
99
     *
100
     * For example, for US English, 'en-us'.
101
     * This can be unspecified.
102
     *
103
     * @param string $lang
104
     */
105 4
    public function setLanguage($lang)
106
    {
107 4
        if ($lang && $this->_lang !== $lang) {
108 4
            $this->clearCachedValue();
109 4
            $this->_lang = (string)$lang;
110 4
        }
111 4
    }
112
113
    /**
114
     * Get the language used in this Header.
115
     *
116
     * @return string
117
     */
118 7
    public function getLanguage()
119
    {
120 7
        return $this->_lang;
121
    }
122
123
    /**
124
     * Set the encoder used for encoding the header.
125
     *
126
     * @param Swift_Mime_HeaderEncoder $encoder
127
     */
128 254
    public function setEncoder(Swift_Mime_HeaderEncoder $encoder)
129
    {
130 254
        $this->_encoder = $encoder;
131 254
        $this->_encoder->charsetChanged($this->_charset);
132
133 254
        $this->setCachedValue(null);
134 254
    }
135
136
    /**
137
     * Get the encoder used for encoding this Header.
138
     *
139
     * @return Swift_Mime_HeaderEncoder
140
     */
141 109
    public function getEncoder()
142
    {
143 109
        return $this->_encoder;
144
    }
145
146
    /**
147
     * Get the name of this header (e.g. charset).
148
     *
149
     * @return string
150
     */
151 194
    public function getFieldName()
152
    {
153 194
        return $this->_name;
154
    }
155
156
    /**
157
     * Set the maximum length of lines in the header (excluding EOL).
158
     *
159
     * @param int $lineLength
160
     *
161
     * @return bool
162
     */
163 61
    public function setMaxLineLength($lineLength)
164
    {
165 61
        if ($lineLength && $this->_lineLength !== $lineLength) {
166 57
            $this->clearCachedValue();
167
168 57
            $this->_lineLength = (int)$lineLength;
169
170 57
            return true;
171
        }
172
173 11
        return false;
174
    }
175
176
    /**
177
     * Get the maximum permitted length of lines in this Header.
178
     *
179
     * @return int
180
     */
181 118
    public function getMaxLineLength()
182
    {
183 118
        return $this->_lineLength;
184
    }
185
186
    /**
187
     * Get this Header rendered as a RFC 2822 compliant string.
188
     *
189
     * @return string
190
     */
191 193
    public function toString()
192
    {
193 193
        return $this->_tokensToString($this->toTokens());
194
    }
195
196
    /**
197
     * Returns a string representation of this object.
198
     *
199
     * @return string
200
     *
201
     * @see toString()
202
     */
203
    public function __toString()
204
    {
205
        return $this->toString();
206
    }
207
208
    /**
209
     * Set the name of this Header field.
210
     *
211
     * @param string $name
212
     */
213 294
    protected function setFieldName($name)
214
    {
215 294
        $this->_name = $name;
216 294
    }
217
218
    /**
219
     * Produces a compliant, formatted RFC 2822 'phrase' based on the string given.
220
     *
221
     * @param Swift_Mime_Header        $header
222
     * @param string                   $string  as displayed
223
     * @param string                   $charset of the text
224
     * @param Swift_Mime_HeaderEncoder $encoder
225
     * @param bool                     $shorten the first line to make remove for header name
226
     *
227
     * @return string
228
     */
229 109
    protected function createPhrase(Swift_Mime_Header $header, $string, $charset, Swift_Mime_HeaderEncoder $encoder = null, $shorten = false)
0 ignored issues
show
Unused Code introduced by
The parameter $charset is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $encoder is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
230
    {
231
        // Treat token as exactly what was given
232 109
        $phraseStr = $string;
233
        // If it's not valid
234 109
        if (!preg_match('/^' . self::PHRASE_PATTERN . '$/D', $phraseStr)) {
235
            // .. but it is just ascii text, try escaping some characters
236
            // and make it a quoted-string
237 12
            if (preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $phraseStr)) {
238 3
                $phraseStr = $this->escapeSpecials($phraseStr, array('"'));
239 3
                $phraseStr = '"' . $phraseStr . '"';
240 3
            } else {
241
                // ... otherwise it needs encoding
242
                // Determine space remaining on line if first line
243 10
                if ($shorten) {
244 10
                    $usedLength = strlen($header->getFieldName() . ': ');
245 10
                } else {
246
                    $usedLength = 0;
247
                }
248 10
                $phraseStr = $this->encodeWords($header, $string, $usedLength);
249
            }
250 12
        }
251
252 109
        return $phraseStr;
253
    }
254
255
    /**
256
     * Escape special characters in a string (convert to quoted-pairs).
257
     *
258
     * @param string   $token
259
     * @param string[] $include additional chars to escape
260
     *
261
     * @return string
262
     */
263 3
    protected function escapeSpecials($token, array $include = array())
264
    {
265 3
        foreach (array_merge(array('\\'), $include) as $char) {
266 3
            $token = str_replace($char, '\\' . $char, $token);
267 3
        }
268
269 3
        return $token;
270
    }
271
272
    /**
273
     * Encode needed word tokens within a string of input.
274
     *
275
     * @param Swift_Mime_Header|Swift_Mime_Headers_AbstractHeader $header
276
     * @param string            $input
277
     * @param int               $usedLength optional
278
     *
279
     * @return string
280
     */
281 197
    protected function encodeWords(Swift_Mime_Header $header, $input, $usedLength = -1)
282
    {
283 197
        $value = '';
284 197
        $tokens = $this->getEncodableWordTokens($input);
285 197
        foreach ($tokens as $token) {
286
            // See RFC 2822, Sect 2.2 (really 2.2 ??)
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
287 197
            if ($this->tokenNeedsEncoding($token)) {
288
                // Don't encode starting WSP
289 57
                $firstChar = substr($token, 0, 1);
290
                switch ($firstChar) {
291 57
                    case ' ':
292 57
                    case "\t":
293 46
                        $value .= $firstChar;
294 46
                        $token = substr($token, 1);
295 46
                }
296 57
                if (-1 == $usedLength) {
297 48
                    $usedLength = strlen($header->getFieldName().': ') + strlen($value);
298 48
                }
299 57
                $value .= $this->getTokenAsEncodedWord($token, $usedLength);
300 57
                $header->setMaxLineLength(76); // Forcefully override
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Swift_Mime_Header as the method setMaxLineLength() does only exist in the following implementations of said interface: Swift_Mime_Headers_AbstractHeader, Swift_Mime_Headers_DateHeader, Swift_Mime_Headers_IdentificationHeader, Swift_Mime_Headers_MailboxHeader, Swift_Mime_Headers_ParameterizedHeader, Swift_Mime_Headers_PathHeader, Swift_Mime_Headers_UnstructuredHeader.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
301 57
            } else {
302 186
                $value .= $token;
303
            }
304 197
        }
305 197
        return $value;
306
    }
307
308
    /**
309
     * Test if a token needs to be encoded or not.
310
     *
311
     * @param string $token
312
     *
313
     * @return integer
314
     */
315 197
    protected function tokenNeedsEncoding($token)
316
    {
317 197
        if (preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token)) {
318 56
            return 1;
319
        } else {
320 186
            return 0;
321
        }
322
    }
323
324
    /**
325
     * Splits a string into tokens in blocks of words which can be encoded quickly.
326
     *
327
     * @param string $string
328
     *
329
     * @return string[]
330
     */
331 197
    protected function getEncodableWordTokens($string)
332
    {
333 197
        $tokens = array();
334
335 197
        $encodedToken = '';
336
        // Split at all whitespace boundaries
337 197
        foreach (preg_split('~(?=[\t ])~', $string) as $token) {
338 197
            if ($this->tokenNeedsEncoding($token)) {
339 57
                $encodedToken .= $token;
340 57
            } else {
341 186
                if ($encodedToken !== '') {
342 43
                    $tokens[] = $encodedToken;
343 43
                    $encodedToken = '';
344 43
                }
345 186
                $tokens[] = $token;
346
            }
347 197
        }
348
349 197
        if ($encodedToken !== '') {
350 21
            $tokens[] = $encodedToken;
351 21
        }
352
353 197
        return $tokens;
354
    }
355
356
    /**
357
     * Get a token as an encoded word for safe insertion into headers.
358
     *
359
     * @param string $token           token to encode
360
     * @param int    $firstLineOffset optional
361
     *
362
     * @return string
363
     */
364 58
    protected function getTokenAsEncodedWord($token, $firstLineOffset = 0)
365
    {
366
        // Adjust $firstLineOffset to account for space needed for syntax.
367
368 58
        $charsetDecl = $this->_charset;
369
370 58
        if ($this->_lang) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->_lang of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
371 2
            $charsetDecl .= '*' . $this->_lang;
372 2
        }
373
374 58
        $encodingWrapperLength = strlen('=?' . $charsetDecl . '?' . $this->_encoder->getName() . '??=');
375
376 58
        if ($firstLineOffset >= 75) {
377
            // Does this logic need to be here?
378
            $firstLineOffset = 0;
379
        }
380
381
        /** @noinspection PhpMethodParametersCountMismatchInspection */
382 58
        $encodedTextLines = explode(
383 58
            "\r\n",
384 58
            $this->_encoder->encodeString($token, $firstLineOffset, 75 - $encodingWrapperLength, $this->_charset)
0 ignored issues
show
Unused Code introduced by
The call to Swift_Mime_HeaderEncoder::encodeString() has too many arguments starting with $this->_charset.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
385 58
        );
386
387 58
        if (Swift::strtolowerWithStaticCache($this->_charset) !== 'iso-2022-jp') {
388
            // special encoding for iso-2022-jp using mb_encode_mimeheader
389 58
            foreach ($encodedTextLines as $lineNum => $line) {
390 58
                $encodedTextLines[$lineNum] = '=?' . $charsetDecl . '?' . $this->_encoder->getName() . '?' . $line . '?=';
391 58
            }
392 58
        }
393
394 58
        return implode("\r\n ", $encodedTextLines);
395
    }
396
397
    /**
398
     * Generates tokens from the given string which include CRLF as individual tokens.
399
     *
400
     * @param string $token
401
     *
402
     * @return string[]
403
     */
404 193
    protected function generateTokenLines($token)
405
    {
406 193
        return preg_split('~(\r\n)~', $token, -1, PREG_SPLIT_DELIM_CAPTURE);
407
    }
408
409
    /**
410
     * Set a value into the cache.
411
     *
412
     * @param string $value
413
     */
414 283
    protected function setCachedValue($value)
415
    {
416 283
        $this->_cachedValue = $value;
417 283
    }
418
419
    /**
420
     * Get the value in the cache.
421
     *
422
     * @return string
423
     */
424 212
    protected function getCachedValue()
425
    {
426 212
        return $this->_cachedValue;
427
    }
428
429 242
    private function clearCachedValue()
430
    {
431 242
        $this->setCachedValue(null);
432 242
    }
433
434
    /**
435
     * Clear the cached value if $condition is met.
436
     *
437
     * @param bool $condition
438
     */
439 233
    protected function clearCachedValueIf($condition)
440
    {
441 233
        if (true === $condition) {
442 233
            $this->clearCachedValue();
443 233
        }
444 233
    }
445
446
    /**
447
     * Generate a list of all tokens in the final header.
448
     *
449
     * @param string $string The string to tokenize
450
     *
451
     * @return array An array of tokens as strings
452
     */
453 193
    protected function toTokens($string = null)
454
    {
455 193
        if (null === $string) {
456 188
            $string = $this->getFieldBody();
457 188
        }
458
459 193
        $tokens = array();
460
461
        // Generate atoms; split at all invisible boundaries followed by WSP
462 193
        foreach (preg_split('~(?=[ \t])~', $string) as $token) {
463 193
            $newTokens = $this->generateTokenLines($token);
464 193
            foreach ($newTokens as $newToken) {
465 193
                $tokens[] = $newToken;
466 193
            }
467 193
        }
468
469 193
        return $tokens;
470
    }
471
472
    /**
473
     * Takes an array of tokens which appear in the header and turns them into
474
     * an RFC 2822 compliant string, adding FWSP where needed.
475
     *
476
     * @param string[] $tokens
477
     *
478
     * @return string
479
     */
480 193
    private function _tokensToString(array $tokens)
481
    {
482 193
        $lineCount = 0;
483 193
        $headerLines = array();
484 193
        $headerLines[] = $this->_name . ': ';
485 193
        $currentLine = &$headerLines[$lineCount++];
486
487
        // Build all tokens back into compliant header
488 193
        foreach ($tokens as $i => $token) {
489
            // Line longer than specified maximum or token was just a new line
490
            if (
491 193
                ("\r\n" === $token)
492
                ||
493
                (
494 193
                    strlen($currentLine) > 0
495 193
                    &&
496
                    (
497
                        $i > 0
498 193
                        &&
499 175
                        strlen($currentLine . $token) > $this->_lineLength
500 175
                    )
501 193
                )
502 193
            ) {
503 52
                $headerLines[] = '';
504 52
                $currentLine = &$headerLines[$lineCount++];
505 52
            }
506
507
            // Append token to the line
508 193
            if ("\r\n" !== $token) {
509 193
                $currentLine .= $token;
510 193
            }
511 193
        }
512
513
        // Implode with FWS (RFC 2822, 2.2.3)
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
514 193
        return implode("\r\n", $headerLines) . "\r\n";
515
    }
516
517
    /**
518
     * Make a deep copy of object
519
     */
520 5
    public function __clone()
521
    {
522 5
        if ($this->_encoder !== null) {
523 5
            $this->_encoder = clone $this->_encoder;
524 5
        }
525 5
    }
526
}
527