Completed
Push — master ( 891643...c9f30c )
by Asmir
14:46 queued 12:49
created

MimeParser::extractPart()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 18
Code Lines 11

Duplication

Lines 6
Ratio 33.33 %

Code Coverage

Tests 13
CRAP Score 5

Importance

Changes 0
Metric Value
dl 6
loc 18
ccs 13
cts 13
cp 1
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 11
nc 5
nop 3
crap 5
1
<?php
2
3
namespace Goetas\Mail\ToSwiftMailParser;
4
5
use Goetas\Mail\ToSwiftMailParser\Mime\ContentDecoder;
6
use Goetas\Mail\ToSwiftMailParser\Mime\HeaderDecoder;
7
8
class MimeParser
9
{
10
    protected $removeHeaders = array("Received", "From", "X-Original-To", "MIME-Version", "Received-SPF", "Delivered-To");
11
    protected $allowedHeaders = array("return-path", "subject");
12
    private $cache;
13
    private $grammar;
14
    private $contentDecoder;
15
    private $headerDecoder;
16
17 5
    public function __construct(array $allowedHeaders = array(), array $removeHeaders = array())
18
    {
19 5
        $this->cache = \Swift_DependencyContainer::getInstance()->lookup('cache');
20 5
        $this->grammar = \Swift_DependencyContainer::getInstance()->lookup('mime.grammar');
21 5
        $this->contentDecoder = new ContentDecoder ();
22 5
        $this->headerDecoder = new HeaderDecoder ();
23
24 5
        $this->allowedHeaders = array_merge($this->allowedHeaders, $allowedHeaders);
25 5
        $this->removeHeaders = array_merge($this->removeHeaders, $removeHeaders);
26 5
    }
27
28 1
    public function parseString($string, $fillHeaders = false, \Swift_Mime_MimeEntity $message = null)
29
    {
30 1
        $fp = fopen("php://memory", "wb");
31 1
        fwrite($fp, $string);
32 1
        rewind($fp);
33 1
        $message = $this->parseStream($fp, $fillHeaders, $message);
0 ignored issues
show
Documentation introduced by
$fp is of type resource, but the function expects a object<Goetas\Mail\ToSwiftMailParser\stream>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
34 1
        fclose($fp);
35 1
        return $message;
36
    }
37
38
    /**
39
     *
40
     * @param stream $stream
41
     * @param boolean $fillHeaders (default to false)
42
     * @param \Swift_Mime_MimeEntity $message (default to null)
43
     * @return Swift_Mime_MimeEntity|\Swift_Message
44
     */
45 5
    public function parseStream($stream, $fillHeaders = false, \Swift_Mime_MimeEntity $message = null)
46
    {
47 5
        $partHeaders = $this->extractHeaders($stream);
48
49 5
        $filteredHeaders = $this->filterHeaders($partHeaders);
50
51 5
        $parts = $this->parseParts($stream, $partHeaders);
52
53 5
        if (!$message) {
54 5
            $message = new \Swift_Message ();
55 5
        }
56
57 5
        $headers = $this->createHeadersSet($filteredHeaders);
58
59 5
        foreach ($headers->getAll() as $name => $header) {
60 5
            if ($fillHeaders || in_array(strtolower($header->getFieldName()), $this->allowedHeaders)) {
61 5
                $message->getHeaders()->set($header);
62 5
            }
63 5
        }
64 5
        $this->createMessage($parts, $message);
65
66 5
        return $message;
67
    }
68
69 5
    protected function extractHeaders($stream)
70
    {
71 5
        $headers = array();
72 5
        $hName = null;
73 5
        while (!feof($stream)) {
74 5
            $row = fgets($stream);
75 5
            if ($row == "\r\n" || $row == "\n" || $row == "\r") {
76 5
                break;
77
            }
78 5
            if (preg_match('/^([a-z0-9\-]+)\s*:(.*)/i', $row, $mch)) {
79 5
                $hName = strtolower($mch [1]);
80 5
                if (!in_array($hName, array("content-type", "content-transfer-encoding"))) {
81 5
                    $hName = $mch [1];
82 5
                }
83 5
                $row = $mch [2];
84 5
            }
85 5
            if (empty($hName)) {
86
                continue;
87
            }
88 5
            $headers [$hName] [] = trim($row);
89 5
        }
90 5
        foreach ($headers as $header => $values) {
91 5
            $headers [$header] = $this->headerDecoder->decode(trim(implode(" ", $values)));
92 5
        }
93 5
        return $headers;
94
    }
95
96 5
    private function filterHeaders(array $headers)
97
    {
98 5
        foreach ($headers as $header => $values) {
99 5
            if (in_array(strtolower($header), $this->removeHeaders) && !in_array(strtolower($header), $this->allowedHeaders)) {
100
                unset ($headers [$header]);
101
            }
102 5
        }
103 5
        return $headers;
104
    }
105
106 5
    protected function parseParts($stream, $partHeaders)
107
    {
108 5
        $parts = array();
109 5
        $contentType = $this->extractValueHeader($this->getContentType($partHeaders));
110
111 5
        if (stripos($contentType, 'multipart/') !== false) {
112 3
            $headerParts = $this->extractHeaderParts($this->getContentType($partHeaders));
113 3
            $boundary = $headerParts ["boundary"];
114 3
        } else {
115 2
            $boundary = null;
116
        }
117
118
        try {
119
            // body
120 5
            $this->extractPart($stream, $boundary, $this->getTransferEncoding($partHeaders));
121 5
        } catch (Exception\EndOfPartReachedException $e) {
122
            $parts = array(
123 5
                "type" => $contentType,
124 5
                "headers" => $partHeaders,
125 5
                "body" => $e->getData(),
126 5
                "boundary" => $boundary,
127 5
                "parts" => array()
128 5
            );
129
        }
130
131 5
        if ($boundary) {
132 3
            while (!feof($stream)) {
133
                try {
134 3
                    $partHeaders = $this->extractHeaders($stream);
135 3
                    $childContentType = $this->extractValueHeader($this->getContentType($partHeaders));
136
137 3
                    if (stripos($childContentType, 'multipart/') !== false) {
138
                        $parts ["parts"] [] = $this->parseParts($stream, $partHeaders);
139
                        try {
140
                            $this->extractPart($stream, $boundary, $this->getTransferEncoding($partHeaders));
141
                        } catch (Exception\EndOfPartReachedException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
142
                        }
143
                    } else {
144 3
                        $this->extractPart($stream, $boundary, $this->getTransferEncoding($partHeaders));
145
                    }
146 3
                } catch (Exception\EndOfPartReachedException $e) {
147 3
                    $parts ["parts"] [] = array(
148 3
                        "type" => $childContentType,
0 ignored issues
show
Bug introduced by
The variable $childContentType does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
149 3
                        "parent-type" => $contentType,
150 3
                        "headers" => $partHeaders,
151 3
                        "body" => $e->getData(),
152 3
                        "parts" => array()
153 3
                    );
154
155 3
                    if ($e instanceof Exception\EndOfMultiPartReachedException) {
156 3
                        break;
157
                    }
158
                }
159 3
            }
160 3
        }
161 5
        return $parts;
162
    }
163
164 5
    private function extractValueHeader($header)
165
    {
166 5
        $pos = stripos($header, ';');
167 5
        if ($pos !== false) {
168 3
            return substr($header, 0, $pos);
169
        } else {
170 5
            return $header;
171
        }
172
    }
173
174 5
    private function getContentType(array $partHeaders)
175
    {
176 5
        if (array_key_exists('content-type', $partHeaders)) {
177 5
            return $partHeaders['content-type'];
178
        }
179
180
        return '';
181
    }
182
183 5
    private function extractHeaderParts($header)
184
    {
185 5
        if (stripos($header, ';') !== false) {
186
187 3
            $parts = explode(";", $header);
188 3
            array_shift($parts);
189 3
            $p = array();
190 3
            foreach ($parts as $pv) {
191 3
                if (!trim($pv)) {
192 3
                    continue;
193
                }
194 3
                list ($k, $v) = explode("=", trim($pv), 2);
195 3
                $p [$k] = trim($v, '"');
196 3
            }
197 3
            return $p;
198
        } else {
199 5
            return array();
200
        }
201
    }
202 5
    protected function extractPart($stream, $boundary, $encoding)
203
    {
204 5
        $rows = array();
205 5
        while (!feof($stream)) {
206 5
            $row = fgets($stream);
207
208 5
            if ($boundary !== null) {
209 3 View Code Duplication
                if (strpos($row, "--$boundary--") === 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
210 3
                    throw new Exception\EndOfMultiPartReachedException ($this->contentDecoder->decode(implode("", $rows), $encoding));
211
                }
212 3 View Code Duplication
                if (strpos($row, "--$boundary") === 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
213 3
                    throw new Exception\EndOfPartReachedException ($this->contentDecoder->decode(implode("", $rows), $encoding));
214
                }
215 3
            }
216 5
            $rows [] = $row;
217 5
        }
218 2
        throw new Exception\EndOfMultiPartReachedException ($this->contentDecoder->decode(implode("", $rows), $encoding));
219
    }
220
221 5
    private function getTransferEncoding(array $partHeaders)
222
    {
223 5
        if (array_key_exists('content-transfer-encoding', $partHeaders)) {
224 1
            return $partHeaders ['content-transfer-encoding'];
225
        }
226
227 4
        return '';
228
    }
229
230
    /**
231
     *
232
     * @param array $headersRaw
233
     * @return \Swift_Mime_HeaderSet
234
     */
235 5
    protected function createHeadersSet(array $headersRaw)
236
    {
237 5
        $headers = \Swift_DependencyContainer::getInstance()->lookup('mime.headerset');
238
239 5
        foreach ($headersRaw as $name => $value) {
240 5
            switch (strtolower($name)) {
241 5
                case "content-type":
242 5
                    $parts = $this->extractHeaderParts($value);
243 5
                    unset ($parts ["boundary"]);
244 5
                    $headers->addParameterizedHeader($name, $this->extractValueHeader($value), $parts);
245 5
                    break;
246 5
                case "return-path" :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
247 1
                    if (preg_match_all('/([a-z][a-z0-9_\-\.]*@[a-z0-9\.\-]*\.[a-z]{2,5})/i', $value, $mch)) {
248 1
                        foreach ($mch [0] as $k => $mails) {
249 1
                            $headers->addPathHeader($name, $mch [1] [$k]);
250 1
                        }
251 1
                    }
252 1
                    break;
253 5
                case "date":
254 1
                    $headers->addDateHeader($name, strtotime($value));
255 1
                    break;
256 5
                case "to":
257 5
                case "from":
258 5
                case "bcc" :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
259 5
                case "reply-to":
260 5
                case "cc":
261 5
                    $adresses = array();
262 5
                    if (preg_match_all('/(.*?)<([a-z][a-z0-9_\-\.]*@[a-z0-9\.\-]*\.[a-z]{2,5})>\s*[;,]*/i', $value, $mch)) {
263 5
                        foreach ($mch [0] as $k => $mail) {
264 5
                            if (!$mch [1] [$k]) {
265
                                $adresses [$mch [2] [$k]] = trim($mch [2] [$k]);
266
                            } else {
267 5
                                $adresses [$mch [2] [$k]] = trim($mch [1] [$k]);
268
                            }
269 5
                        }
270 5
                    } elseif (preg_match_all('/([a-z][a-z0-9_\-\.]*@[a-z0-9\.\-]*\.[a-z]{2,5})/i', $value, $mch)) {
271
                        foreach ($mch [0] as $k => $mails) {
272
                            $adresses [$mch [1] [$k]] = trim($mch [1] [$k]);
273
                        }
274
                    }
275 5
                    $headers->addMailboxHeader($name, $adresses);
276 5
                    break;
277 5
                default:
278 5
                    $headers->addTextHeader($name, $value);
279 5
                    break;
280 5
            }
281 5
        }
282 5
        return $headers;
283
    }
284
285 5
    protected function createMessage(array $message, \Swift_Mime_MimeEntity $entity)
286
    {
287 5
        if (stripos($message ["type"], 'multipart/') !== false) {
288
289 3
            if (strpos($message ["type"], '/alternative')) {
290
                $nestingLevel = \Swift_Mime_MimeEntity::LEVEL_ALTERNATIVE;
291 3
            } elseif (strpos($message ["type"], '/related')) {
292
                $nestingLevel = \Swift_Mime_MimeEntity::LEVEL_RELATED;
293 3
            } elseif (strpos($message ["type"], '/mixed')) {
294 3
                $nestingLevel = \Swift_Mime_MimeEntity::LEVEL_MIXED;
295 3
            }
296
297 3
            $childrens = array();
298 3
            foreach ($message ["parts"] as $part) {
299
300 3
                $headers = $this->createHeadersSet($part ["headers"]);
301 3
                $encoder = $this->getEncoder($this->getTransferEncoding($part ["headers"]));
302
303 3
                if (stripos($part ["type"], 'multipart/') !== false) {
304
                    $newEntity = new \Swift_Mime_MimePart ($headers, $encoder, $this->cache, $this->grammar);
305
                } else {
306 3
                    $newEntity = new \Swift_Mime_SimpleMimeEntity ($headers, $encoder, $this->cache, $this->grammar);
307
                }
308
309 3
                $this->createMessage($part, $newEntity);
310
311 3
                $ref = new \ReflectionObject ($newEntity);
312 3
                $m = $ref->getMethod('_setNestingLevel');
313 3
                $m->setAccessible(true);
314 3
                $m->invoke($newEntity, $nestingLevel);
0 ignored issues
show
Bug introduced by
The variable $nestingLevel does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
315
316 3
                $childrens [] = $newEntity;
317 3
            }
318
319 3
            $entity->setContentType($part ["type"]);
0 ignored issues
show
Bug introduced by
The variable $part seems to be defined by a foreach iteration on line 298. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
Bug introduced by
It seems like you code against a concrete implementation and not the interface Swift_Mime_MimeEntity as the method setContentType() does only exist in the following implementations of said interface: Swift_Attachment, Swift_EmbeddedFile, Swift_Image, Swift_Message, Swift_MimePart, Swift_Mime_Attachment, Swift_Mime_EmbeddedFile, Swift_Mime_MimePart, Swift_Mime_SimpleMessage, Swift_Mime_SimpleMimeEntity, Swift_SignedMessage.

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...
320 3
            $entity->setChildren($childrens);
321 3
        } else {
322 5
            $entity->setBody($message ["body"], $message ["type"]);
323
        }
324 5
    }
325
326
    /**
327
     *
328
     * @param string $type
329
     * @return \Swift_Mime_ContentEncoder
330
     */
331 3
    protected function getEncoder($type)
332
    {
333
        switch ($type) {
334 3
            case "base64" :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
335
                return \Swift_DependencyContainer::getInstance()->lookup('mime.base64contentencoder');
336
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
337 3
            case "8bit" :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
338
                return \Swift_DependencyContainer::getInstance()->lookup('mime.8bitcontentencoder');
339
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
340 3
            case "7bit" :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
341
                return \Swift_DependencyContainer::getInstance()->lookup('mime.7bitcontentencoder');
342
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
343 3
            default :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a DEFAULT statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in the default statement.

switch ($expr) {
    default : //wrong
        doSomething();
        break;
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
344 3
                return \Swift_DependencyContainer::getInstance()->lookup('mime.qpcontentencoder');
345
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
346 3
        }
347
    }
348
349
    /**
350
     *
351
     * @param string $path
352
     *            The file containg a MIME message
353
     * @return \Swift_Message
354
     */
355 1
    public function parseFile($path, $fillHeaders = false, \Swift_Mime_MimeEntity $message = null)
356
    {
357 1
        $fp = fopen($path, "rb");
358 1
        $message = $this->parseStream($fp, $fillHeaders, $message);
0 ignored issues
show
Documentation introduced by
$fp is of type resource, but the function expects a object<Goetas\Mail\ToSwiftMailParser\stream>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
359 1
        fclose($fp);
360 1
        return $message;
361
    }
362
}
363