Swift_Mime_SimpleMimeEntity::getEncoder()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
crap 1
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 MIME entity, in a multipart message.
13
 *
14
 * @author Chris Corbyn
15
 */
16
class Swift_Mime_SimpleMimeEntity implements Swift_Mime_MimeEntity
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
     * A collection of Headers for this mime entity
20
     *
21
     * @var Swift_Mime_HeaderSet
22
     */
23
    private $_headers;
24
25
    /**
26
     * The body as a string, or a stream
27
     */
28
    private $_body;
29
30
    /**
31
     * The encoder that encodes the body into a streamable format
32
     *
33
     * @var Swift_Mime_ContentEncoder
34
     */
35
    private $_encoder;
36
37
    /**
38
     * Message ID generator
39
     *
40
     * @var Swift_IdGenerator
41
     */
42
    private $_idGenerator;
43
44
    /**
45
     * A mime boundary, if any is used
46
     */
47
    private $_boundary;
48
49
    /**
50
     * Mime types to be used based on the nesting level
51
     *
52
     * @var array
53
     */
54
    private $_compositeRanges = array(
55
        'multipart/mixed' => array(self::LEVEL_TOP, self::LEVEL_MIXED),
56
        'multipart/alternative' => array(self::LEVEL_MIXED, self::LEVEL_ALTERNATIVE),
57
        'multipart/related' => array(self::LEVEL_ALTERNATIVE, self::LEVEL_RELATED),
58
    );
59
60
    /**
61
     * A set of filter rules to define what level an entity should be nested at
62
     *
63
     * @var array
64
     */
65
    private $_compoundLevelFilters = array();
66
67
    /**
68
     * The nesting level of this entity
69
     *
70
     * @var int
71
     */
72
    private $_nestingLevel = self::LEVEL_ALTERNATIVE;
73
74
    /**
75
     * A KeyCache instance used during encoding and streaming
76
     *
77
     * @var Swift_KeyCache
78
     */
79
    private $_cache;
80
81
    /**
82
     * Direct descendants of this entity
83
     *
84
     * @var Swift_Mime_MimeEntity[]|array
85
     */
86
    private $_immediateChildren = array();
87
88
    /**
89
     * All descendants of this entity
90
     *
91
     * @var Swift_Mime_MimeEntity[]
92
     */
93
    private $_children = array();
94
95
    /**
96
     * The maximum line length of the body of this entity
97
     *
98
     * @var int
99
     */
100
    private $_maxLineLength = 78;
101
102
    /**
103
     * The order in which alternative mime types should appear
104
     *
105
     * @var array
106
     */
107
    private $_alternativePartOrder = array(
108
        'text/plain' => 1,
109
        'text/html' => 2,
110
        'multipart/related' => 3,
111
    );
112
113
    /**
114
     * The CID of this entity
115
     *
116
     * @var string
117
     */
118
    private $_id;
119
120
    /**
121
     * The key used for accessing the cache
122
     *
123
     * @var string
124
     */
125
    private $_cacheKey;
126
127
    /**
128
     * @var string
129
     */
130
    protected $_userContentType;
131
132
    /**
133
     * Create a new SimpleMimeEntity with $headers, $encoder and $cache.
134
     *
135
     * @param Swift_Mime_HeaderSet       $headers
136
     * @param Swift_Mime_ContentEncoder  $encoder
137
     * @param Swift_KeyCache             $cache
138
     * @param Swift_IdGenerator          $idGenerator
139
     */
140 538
    public function __construct(Swift_Mime_HeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_IdGenerator $idGenerator)
141
    {
142 538
        $this->_cacheKey = $this->_generateNewCacheKey();
143 538
        $this->_cache = $cache;
144 538
        $this->_headers = $headers;
145 538
        $this->_idGenerator = $idGenerator;
146 538
        $this->setEncoder($encoder);
147 538
        $this->_headers->defineOrdering(array('Content-Type', 'Content-Transfer-Encoding'));
148
149
        // This array specifies that, when the entire MIME document contains
150
        // $compoundLevel, then for each child within $level, if its Content-Type
151
        // is $contentType then it should be treated as if it's level is
152
        // $neededLevel instead.  I tried to write that unambiguously! :-\
153
        // Data Structure:
154
        // array (
155
        //   $compoundLevel => array(
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% 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...
156
        //     $level => array(
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% 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...
157
        //       $contentType => $neededLevel
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
158
        //     )
159
        //   )
160
        // )
161
162 538
        $this->_compoundLevelFilters = array(
163 538
            (self::LEVEL_ALTERNATIVE + self::LEVEL_RELATED) => array(
164 538
                self::LEVEL_ALTERNATIVE => array(
165 538
                    'text/plain' => self::LEVEL_ALTERNATIVE,
166 538
                    'text/html' => self::LEVEL_RELATED,
167 538
                ),
168 538
            ),
169
        );
170
171 538
        $this->_id = $this->_idGenerator->generateId();
172 538
    }
173
174
    /**
175
     * Generate a new Content-ID or Message-ID for this MIME entity.
176
     *
177
     * @return string
178
     */
179 16
    public function generateId()
180
    {
181 16
        $this->setId($this->_idGenerator->generateId());
182
183 16
        return $this->_id;
184
    }
185
186
    /**
187
     * Get the {@link Swift_Mime_HeaderSet} for this entity.
188
     *
189
     * @return Swift_Mime_HeaderSet
190
     */
191 399
    public function getHeaders()
192
    {
193 399
        return $this->_headers;
194
    }
195
196
    /**
197
     * Get the nesting level of this entity.
198
     *
199
     * @see LEVEL_TOP, LEVEL_MIXED, LEVEL_RELATED, LEVEL_ALTERNATIVE
200
     *
201
     * @return int
202
     */
203 24
    public function getNestingLevel()
204
    {
205 24
        return $this->_nestingLevel;
206
    }
207
208
    /**
209
     * Get the Content-type of this entity.
210
     *
211
     * @return string
212
     */
213 63
    public function getContentType()
214
    {
215 63
        return $this->_getHeaderFieldModel('Content-Type');
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->_getHeaderFieldModel('Content-Type'); of type null|string[]|string adds the type string[] to the return on line 215 which is incompatible with the return type declared by the interface Swift_Mime_MimeEntity::getContentType of type string|null.
Loading history...
216
    }
217
218
    /**
219
     * Set the Content-type of this entity.
220
     *
221
     * @param string $type
222
     *
223
     * @return $this
224
     */
225 492
    public function setContentType($type)
226
    {
227 492
        $this->_setContentTypeInHeaders($type);
228
        // Keep track of the value so that if the content-type changes automatically
229
        // due to added child entities, it can be restored if they are later removed
230 492
        $this->_userContentType = $type;
231
232 492
        return $this;
233
    }
234
235
    /**
236
     * Get the CID of this entity.
237
     *
238
     * The CID will only be present in headers if a Content-ID header is present.
239
     *
240
     * @return string
241
     */
242 345
    public function getId()
243
    {
244 345
        $tmp = (array)$this->_getHeaderFieldModel($this->_getIdField());
245
246 345
        return $this->_headers->has($this->_getIdField()) ? current($tmp) : $this->_id;
247
    }
248
249
    /**
250
     * Set the CID of this entity.
251
     *
252
     * @param string $id
253
     *
254
     * @return $this
255
     */
256 348
    public function setId($id)
257
    {
258 348
        if (!$this->_setHeaderFieldModel($this->_getIdField(), $id)) {
259 341
            $this->_headers->addIdHeader($this->_getIdField(), $id);
260 341
        }
261 348
        $this->_id = $id;
262
263 348
        return $this;
264
    }
265
266
    /**
267
     * Get the description of this entity.
268
     *
269
     * This value comes from the Content-Description header if set.
270
     *
271
     * @return string
272
     */
273 5
    public function getDescription()
274
    {
275 5
        return $this->_getHeaderFieldModel('Content-Description');
276
    }
277
278
    /**
279
     * Set the description of this entity.
280
     *
281
     * This method sets a value in the Content-ID header.
282
     *
283
     * @param string $description
284
     *
285
     * @return $this
286
     */
287 15
    public function setDescription($description)
288
    {
289 15
        if (!$this->_setHeaderFieldModel('Content-Description', $description)) {
290 10
            $this->_headers->addTextHeader('Content-Description', $description);
291 10
        }
292
293 15
        return $this;
294
    }
295
296
    /**
297
     * Get the maximum line length of the body of this entity.
298
     *
299
     * @return int
300
     */
301 126
    public function getMaxLineLength()
302
    {
303 126
        return $this->_maxLineLength;
304
    }
305
306
    /**
307
     * Set the maximum line length of lines in this body.
308
     *
309
     * Though not enforced by the library, lines should not exceed 1000 chars.
310
     *
311
     * @param int $length
312
     *
313
     * @return $this
314
     */
315 34
    public function setMaxLineLength($length)
316
    {
317 34
        $this->_maxLineLength = $length;
318
319 34
        return $this;
320
    }
321
322
    /**
323
     * Get all children added to this entity.
324
     *
325
     * @return Swift_Mime_MimeEntity[]
326
     */
327 185
    public function getChildren()
328
    {
329 185
        return $this->_children;
330
    }
331
332
    /**
333
     * Set all children of this entity.
334
     *
335
     * @param Swift_Mime_MimeEntity[] $children
336
     * @param int                     $compoundLevel For internal use only
337
     *
338
     * @return $this
339
     */
340 132
    public function setChildren(array $children, $compoundLevel = null)
341
    {
342
        // TODO: Try to refactor this logic
343
344 132
        $compoundLevel = isset($compoundLevel) ? $compoundLevel : $this->_getCompoundLevel($children);
345 132
        $immediateChildren = array();
346 132
        $grandchildren = array();
347 132
        $newContentType = $this->_userContentType;
348
349 132
        foreach ($children as $child) {
350 118
            $level = $this->_getNeededChildLevel($child, $compoundLevel);
351 118
            if (empty($immediateChildren)) {
352
                // first iteration
353 118
                $immediateChildren = array($child);
354 118
            } else {
355 71
                $nextLevel = $this->_getNeededChildLevel($immediateChildren[0], $compoundLevel);
356 71
                if ($nextLevel === $level) {
357 52
                    $immediateChildren[] = $child;
358 71
                } elseif ($level < $nextLevel) {
359
                    // re-assign immediateChildren to grandchildren
360 16
                    $grandchildren = array_merge($grandchildren, $immediateChildren);
361
                    // set new children
362 16
                    $immediateChildren = array($child);
363 16
                } else {
364 15
                    $grandchildren[] = $child;
365
                }
366
            }
367 132
        }
368
369 132
        if ($immediateChildren) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $immediateChildren of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
370 118
            $lowestLevel = $this->_getNeededChildLevel($immediateChildren[0], $compoundLevel);
371
372
            // Determine which composite media type is needed to accommodate the immediate children.
373 118
            foreach ($this->_compositeRanges as $mediaType => $range) {
374 118
                if ($lowestLevel > $range[0] && $lowestLevel <= $range[1]) {
375 92
                    $newContentType = $mediaType;
376
377 92
                    break;
378
                }
379 118
            }
380
381
            // Put any grandchildren in a sub-part.
382 118
            if (!empty($grandchildren)) {
383 24
                $subentity = $this->_createChild();
384 24
                $subentity->_setNestingLevel($lowestLevel);
385 24
                $subentity->setChildren($grandchildren, $compoundLevel);
386 24
                array_unshift($immediateChildren, $subentity);
387 24
            }
388 118
        }
389
390 132
        $this->_immediateChildren = $immediateChildren;
391 132
        $this->_children = $children;
392 132
        $this->_setContentTypeInHeaders($newContentType);
393 132
        $this->_fixHeaders();
394 132
        $this->_sortChildren();
395
396 132
        return $this;
397
    }
398
399
    /**
400
     * Get the body of this entity as a string.
401
     *
402
     * @return string
403
     */
404 138
    public function getBody()
405
    {
406 138
        return $this->_body instanceof Swift_OutputByteStream ? $this->_readStream($this->_body) : $this->_body;
407
    }
408
409
    /**
410
     * Set the body of this entity, either as a string, or as an instance of
411
     * {@link Swift_OutputByteStream}.
412
     *
413
     * @param mixed       $body
414
     * @param string|null $contentType optional
415
     *
416
     * @return $this
417
     */
418 254
    public function setBody($body, $contentType = null)
419
    {
420 254
        if ($body !== $this->_body) {
421 170
            $this->_clearCache();
422 170
        }
423
424 254
        $this->_body = $body;
425
426 254
        if ($contentType) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $contentType 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...
427 17
            $this->setContentType($contentType);
428 17
        }
429
430 254
        return $this;
431
    }
432
433
    /**
434
     * Get the encoder used for the body of this entity.
435
     *
436
     * @return Swift_Mime_ContentEncoder
437
     */
438 30
    public function getEncoder()
439
    {
440 30
        return $this->_encoder;
441
    }
442
443
    /**
444
     * Set the encoder used for the body of this entity.
445
     *
446
     * @param Swift_Mime_ContentEncoder $encoder
447
     *
448
     * @return $this
449
     */
450 538
    public function setEncoder(Swift_Mime_ContentEncoder $encoder)
451
    {
452 538
        if ($encoder !== $this->_encoder) {
453 538
            $this->_clearCache();
454 538
        }
455
456 538
        $this->_encoder = $encoder;
457 538
        $this->_setEncoding($encoder->getName());
458 538
        $this->_notifyEncoderChanged($encoder);
459
460 538
        return $this;
461
    }
462
463
    /**
464
     * Get the boundary used to separate children in this entity.
465
     *
466
     * @return string
467
     */
468 133
    public function getBoundary()
469
    {
470 133
        if (!isset($this->_boundary)) {
471 112
            $this->_boundary = '_=_swift_v5_' . time() . '_' . md5(getmypid() . mt_rand() . uniqid('', true)) . '_=_';
472 112
        }
473
474 133
        return $this->_boundary;
475
    }
476
477
    /**
478
     * Set the boundary used to separate children in this entity.
479
     *
480
     * @param string $boundary
481
     *
482
     * @throws Swift_RfcComplianceException
483
     *
484
     * @return $this
485
     */
486 34
    public function setBoundary($boundary)
487
    {
488 34
        $this->_assertValidBoundary($boundary);
489 34
        $this->_boundary = $boundary;
490
491 34
        return $this;
492
    }
493
494
    /**
495
     * Receive notification that the charset of this entity, or a parent entity
496
     * has changed.
497
     *
498
     * @param string|null $charset
499
     */
500 114
    public function charsetChanged($charset)
501
    {
502 114
        $this->_notifyCharsetChanged($charset);
503 114
    }
504
505
    /**
506
     * Receive notification that the encoder of this entity or a parent entity
507
     * has changed.
508
     *
509
     * @param Swift_Mime_ContentEncoder $encoder
510
     */
511 6
    public function encoderChanged(Swift_Mime_ContentEncoder $encoder)
512
    {
513 6
        $this->_notifyEncoderChanged($encoder);
514 6
    }
515
516
    /**
517
     * Get this entire entity as a string.
518
     *
519
     * @return string
520
     */
521 224
    public function toString()
522
    {
523 224
        $string = $this->_headers->toString();
524 224
        $string .= $this->_bodyToString();
525
526 224
        return $string;
527
    }
528
529
    /**
530
     * Get this entire entity as a string.
531
     *
532
     * @return string
533
     */
534 224
    protected function _bodyToString()
535
    {
536 224
        $string = '';
537
538
        if (
539 224
            isset($this->_body)
540 224
            &&
541
            empty($this->_immediateChildren)
542 224
        ) {
543 107
            if ($this->_cache->hasKey($this->_cacheKey, 'body')) {
544 7
                $body = $this->_cache->getString($this->_cacheKey, 'body');
545 7
            } else {
546 102
                $body = "\r\n" . $this->_encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength());
547 102
                $this->_cache->setString($this->_cacheKey, 'body', $body, Swift_KeyCache::MODE_WRITE);
548
            }
549 107
            $string .= $body;
550 107
        }
551
552 224
        if (!empty($this->_immediateChildren)) {
553 53
            foreach ($this->_immediateChildren as $child) {
554 53
                $string .= "\r\n\r\n--" . $this->getBoundary() . "\r\n";
555 53
                $string .= $child->toString();
556 53
            }
557 53
            $string .= "\r\n\r\n--" . $this->getBoundary() . "--\r\n";
558 53
        }
559
560 224
        return $string;
561
    }
562
563
    /**
564
     * Returns a string representation of this object.
565
     *
566
     * @see toString()
567
     *
568
     * @return string
569
     */
570
    public function __toString()
571
    {
572
        return $this->toString();
573
    }
574
575
    /**
576
     * Write this entire entity to a {@see Swift_InputByteStream}.
577
     *
578
     * @param Swift_InputByteStream
579
     */
580 37
    public function toByteStream(Swift_InputByteStream $is)
581
    {
582 37
        $is->write($this->_headers->toString());
583 37
        $is->commit();
584
585 37
        $this->_bodyToByteStream($is);
586 37
    }
587
588
    /**
589
     * Write this entire entity to a {@link Swift_InputByteStream}.
590
     *
591
     * @param Swift_InputByteStream
592
     */
593 37
    protected function _bodyToByteStream(Swift_InputByteStream $is)
594
    {
595 37
        if (empty($this->_immediateChildren)) {
596 37
            if (isset($this->_body)) {
597 27
                if ($this->_cache->hasKey($this->_cacheKey, 'body')) {
598 8
                    $this->_cache->exportToByteStream($this->_cacheKey, 'body', $is);
599 8
                } else {
600 22
                    $cacheIs = $this->_cache->getInputByteStream($this->_cacheKey, 'body');
601 22
                    if ($cacheIs) {
602 17
                        $is->bind($cacheIs);
603 17
                    }
604
605 22
                    $is->write("\r\n");
606
607 22
                    if ($this->_body instanceof Swift_OutputByteStream) {
608 14
                        $this->_body->setReadPointer(0);
609
610 14
                        $this->_encoder->encodeByteStream($this->_body, $is, 0, $this->getMaxLineLength());
611 14
                    } else {
612 22
                        $is->write($this->_encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength()));
613
                    }
614
615 22
                    if ($cacheIs) {
616 17
                        $is->unbind($cacheIs);
617 17
                    }
618
                }
619 27
            }
620 37
        }
621
622 37
        if (!empty($this->_immediateChildren)) {
623 9
            foreach ($this->_immediateChildren as $child) {
624 9
                $is->write("\r\n\r\n--" . $this->getBoundary() . "\r\n");
625 9
                $child->toByteStream($is);
626 9
            }
627 9
            $is->write("\r\n\r\n--" . $this->getBoundary() . "--\r\n");
628 9
        }
629 37
    }
630
631
    /**
632
     * Get the name of the header that provides the ID of this entity.
633
     */
634 110
    protected function _getIdField()
635
    {
636 110
        return 'Content-ID';
637
    }
638
639
    /**
640
     * Get the model data (usually an array or a string) for $field.
641
     *
642
     * @param string $field
643
     *
644
     * @return null|string[]|string
645
     */
646 355
    protected function _getHeaderFieldModel($field)
647
    {
648 355
        if ($this->_headers->has($field)) {
649 188
            return $this->_headers->get($field)->getFieldBodyModel();
650
        }
651
652 338
        return null;
653
    }
654
655
    /**
656
     * Set the model data for $field.
657
     *
658
     * @param string $field
659
     * @param $model
660
     *
661
     * @return bool
662
     */
663 538
    protected function _setHeaderFieldModel($field, $model)
664
    {
665 538
        if ($this->_headers->has($field)) {
666 282
            $this->_headers->get($field)->setFieldBodyModel($model);
667
668 282
            return true;
669
        }
670
671 537
        return false;
672
    }
673
674
    /**
675
     * Get the parameter value of $parameter on $field header.
676
     * @param string $field
677
     * @param string $parameter
678
     *
679
     * @return string|false
680
     */
681 120
    protected function _getHeaderParameter($field, $parameter)
682
    {
683 120
        if ($this->_headers->has($field)) {
684 92
            return $this->_headers->get($field)->getParameter($parameter);
0 ignored issues
show
Bug introduced by
The method getParameter does only exist in Swift_Mime_ParameterizedHeader, but not in Swift_Mime_Headers_MailboxHeader.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
685
        }
686
687 28
        return false;
688
    }
689
690
    /**
691
     * Set the parameter value of $parameter on $field header.
692
     * @param string $field
693
     * @param string $parameter
694
     * @param mixed  $value
695
     *
696
     * @return bool
697
     */
698 279
    protected function _setHeaderParameter($field, $parameter, $value)
699
    {
700 279
        if ($this->_headers->has($field)) {
701 225
            $this->_headers->get($field)->setParameter($parameter, $value);
0 ignored issues
show
Bug introduced by
The method setParameter does only exist in Swift_Mime_ParameterizedHeader, but not in Swift_Mime_Headers_MailboxHeader.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
702
703 225
            return true;
704
        }
705
706 60
        return false;
707
    }
708
709
    /**
710
     * Re-evaluate what content type and encoding should be used on this entity.
711
     */
712 132
    protected function _fixHeaders()
713
    {
714 132
        if (count($this->_immediateChildren)) {
715 118
            $this->_setHeaderParameter('Content-Type', 'boundary', $this->getBoundary());
716 118
            $this->_headers->remove('Content-Transfer-Encoding');
717 118
        } else {
718 25
            $this->_setHeaderParameter('Content-Type', 'boundary', null);
719 25
            $this->_setEncoding($this->_encoder->getName());
720
        }
721 132
    }
722
723
    /**
724
     * Get the KeyCache used in this entity.
725
     *
726
     * @return Swift_KeyCache
727
     */
728 19
    protected function _getCache()
729
    {
730 19
        return $this->_cache;
731
    }
732
733
    /**
734
     * @return Swift_IdGenerator
735
     */
736 19
    protected function _getIdGenerator()
737
    {
738 19
        return $this->_idGenerator;
739
    }
740
741
    /**
742
     * Empty the KeyCache for this entity.
743
     */
744 538
    protected function _clearCache()
745
    {
746 538
        $this->_cache->clearKey($this->_cacheKey, 'body');
747 538
    }
748
749
    /**
750
     * generate a new cache-key
751
     *
752
     * @return string
753
     */
754 538
    private function _generateNewCacheKey()
755
    {
756 538
        return md5(getmypid() . '.' . time() . '.' . uniqid(mt_rand(), true));
757
    }
758
759
    /**
760
     * read stream
761
     *
762
     * @param Swift_OutputByteStream $os
763
     *
764
     * @return string
765
     */
766 14
    private function _readStream(Swift_OutputByteStream $os)
767
    {
768 14
        $string = '';
769 14
        while (false !== $bytes = $os->read(8192)) {
770 14
            $string .= $bytes;
771 14
        }
772
773 14
        $os->setReadPointer(0);
774
775 14
        return $string;
776
    }
777
778
    /**
779
     * @param string $encoding
780
     */
781 538
    private function _setEncoding($encoding)
782
    {
783 538
        if (!$this->_setHeaderFieldModel('Content-Transfer-Encoding', $encoding)) {
784 533
            $this->_headers->addTextHeader('Content-Transfer-Encoding', $encoding);
785 533
        }
786 538
    }
787
788
    /**
789
     * @param string $boundary
790
     *
791
     * @throws Swift_RfcComplianceException
792
     */
793 34
    private function _assertValidBoundary($boundary)
794
    {
795 34
        if (!preg_match('/^[a-z0-9\'\(\)\+_\-,\.\/:=\?\ ]{0,69}[a-z0-9\'\(\)\+_\-,\.\/:=\?]$/Di', $boundary)) {
796
            throw new Swift_RfcComplianceException('Mime boundary set is not RFC 2046 compliant.');
797
        }
798 34
    }
799
800
    /**
801
     * @param string $type
802
     */
803 504
    private function _setContentTypeInHeaders($type)
804
    {
805 504
        if (!$this->_setHeaderFieldModel('Content-Type', $type)) {
806 443
            $this->_headers->addParameterizedHeader('Content-Type', $type);
807 443
        }
808 504
    }
809
810
    /**
811
     * @param int $level
812
     */
813 24
    private function _setNestingLevel($level)
814
    {
815 24
        $this->_nestingLevel = $level;
816 24
    }
817
818
    /**
819
     * @param Swift_Mime_MimeEntity[] $children
820
     *
821
     * @return int
822
     */
823 132
    private function _getCompoundLevel($children)
824
    {
825 132
        $level = 0;
826 132
        foreach ($children as $child) {
827 118
            $level |= $child->getNestingLevel();
828 132
        }
829
830 132
        return $level;
831
    }
832
833
    /**
834
     * @param Swift_Mime_MimeEntity $child
835
     * @param integer $compoundLevel
836
     *
837
     * @return int
838
     */
839 118
    private function _getNeededChildLevel($child, $compoundLevel)
840
    {
841 118
        $filter = array();
842 118
        foreach ($this->_compoundLevelFilters as $bitmask => $rules) {
843 118
            if (($compoundLevel & $bitmask) === $bitmask) {
844 15
                $filter = $rules + $filter;
845 15
            }
846 118
        }
847
848 118
        $realLevel = $child->getNestingLevel();
849 118
        $lowercaseType = Swift::strtolowerWithStaticCache((string)$child->getContentType());
850
851 118
        if (isset($filter[$realLevel], $filter[$realLevel][$lowercaseType])) {
852 10
            return (int)$filter[$realLevel][$lowercaseType];
853
        }
854
855 118
        return (int)$realLevel;
856
    }
857
858
    /**
859
     * @return $this
860
     */
861 24
    private function _createChild()
862
    {
863 24
        return new self($this->_headers->newInstance(), $this->_encoder, $this->_cache, $this->_idGenerator);
864
    }
865
866
    /**
867
     * @param Swift_Mime_ContentEncoder $encoder
868
     */
869 538
    private function _notifyEncoderChanged(Swift_Mime_ContentEncoder $encoder)
870
    {
871 538
        foreach ($this->_immediateChildren as $child) {
872 11
            $child->encoderChanged($encoder);
873 538
        }
874 538
    }
875
876
    /**
877
     * @param string $charset
878
     */
879 114
    private function _notifyCharsetChanged($charset)
880
    {
881 114
        $this->_encoder->charsetChanged($charset);
882 114
        $this->_headers->charsetChanged($charset);
883 114
        foreach ($this->_immediateChildren as $child) {
884 7
            $child->charsetChanged($charset);
885 114
        }
886 114
    }
887
888 132
    private function _sortChildren()
889
    {
890 132
        $shouldSort = false;
891 132
        foreach ($this->_immediateChildren as $child) {
892
            // NOTE: This include alternative parts moved into a related part
893 118
            if ($child->getNestingLevel() === self::LEVEL_ALTERNATIVE) {
894 66
                $shouldSort = true;
895 66
                break;
896
            }
897 132
        }
898
899
        // Sort in order of preference, if there is one
900 132
        if ($shouldSort) {
901
            // Group the messages by order of preference
902 66
            $sorted = array();
903 66
            foreach ($this->_immediateChildren as $child) {
904 66
                $type = $child->getContentType();
905 66
                $level = array_key_exists($type, $this->_alternativePartOrder) ?
906 66
                    $this->_alternativePartOrder[$type] :
907 66
                    max($this->_alternativePartOrder) + 1;
908
909 66
                if (empty($sorted[$level])) {
910 66
                    $sorted[$level] = array();
911 66
                }
912
913 66
                $sorted[$level][] = $child;
914 66
            }
915
916 66
            ksort($sorted);
917
918 66
            $this->_immediateChildren = array_reduce($sorted, 'array_merge', array());
0 ignored issues
show
Documentation Bug introduced by
It seems like array_reduce($sorted, 'array_merge', array()) of type * is incompatible with the declared type array of property $_immediateChildren.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
919 66
        }
920 132
    }
921
922
    /**
923
     * Empties it's own contents from the cache.
924
     */
925 536
    public function __destruct()
926
    {
927 536
        if ($this->_cache instanceof Swift_KeyCache) {
928 536
            $this->_cache->clearAll($this->_cacheKey);
929 536
        }
930 536
    }
931
932
    /**
933
     * Make a deep copy of object.
934
     */
935 5
    public function __clone()
936
    {
937 5
        $this->_headers = clone $this->_headers;
938 5
        $this->_encoder = clone $this->_encoder;
939
940
        // TODO? do we need this ? -> https://github.com/bmurashin/swiftmailer/commit/ef5c5134e6e02afc2e8ff3287bfa74be1b33dcaf
941
        //$this->_cacheKey = $this->_generateNewCacheKey();
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% 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...
942
        //$this->generateId();
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% 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...
943
944 5
        $children = array();
945 5
        foreach ($this->_children as $pos => $child) {
946 2
            if ($child instanceof Swift_Mime_Attachment || $child instanceof Swift_Mime_EmbeddedFile) {
947 1
                $children[$pos] = $child;
948 1
            } else {
949 1
                $children[$pos] = clone $child;
950
            }
951 5
        }
952 5
        $this->setChildren($children);
953 5
    }
954
}
955