Passed
Push — master ( ad3faa...5c4918 )
by Zaahid
03:33
created

Message::getTextPartCount()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of the ZBateson\MailMimeParser project.
4
 *
5
 * @license http://opensource.org/licenses/bsd-license.php BSD
6
 */
7
namespace ZBateson\MailMimeParser;
8
9
use GuzzleHttp\Psr7;
10
use Psr\Http\Message\StreamInterface;
11
use ZBateson\MailMimeParser\Message\Helper\MessageHelperService;
12
use ZBateson\MailMimeParser\Message\Part\MimePart;
13
use ZBateson\MailMimeParser\Message\Part\PartBuilder;
14
use ZBateson\MailMimeParser\Message\Part\PartStreamFilterManager;
15
use ZBateson\MailMimeParser\Message\PartFilter;
16
use ZBateson\MailMimeParser\Message\PartFilterFactory;
17
use ZBateson\MailMimeParser\Stream\StreamFactory;
18
19
/**
20
 * A parsed mime message with optional mime parts depending on its type.
21
 * 
22
 * A mime message may have any number of mime parts, and each part may have any
23
 * number of sub-parts, etc...
24
 *
25
 * @author Zaahid Bateson
26
 */
27
class Message extends MimePart
28
{
29
    /**
30
     * @var MessageHelperService helper class with various message manipulation
31
     *      routines.
32
     */
33
    protected $messageHelperService;
34
35
    /**
36
     * @param PartStreamFilterManager $partStreamFilterManager
37
     * @param StreamFactory $streamFactory
38
     * @param PartFilterFactory $partFilterFactory
39
     * @param PartBuilder $partBuilder
40
     * @param MessageHelperService $messageHelperService
41
     * @param StreamInterface $stream
42
     * @param StreamInterface $contentStream
43
     */
44 11
    public function __construct(
45
        PartStreamFilterManager $partStreamFilterManager,
46
        StreamFactory $streamFactory,
47
        PartFilterFactory $partFilterFactory,
48
        PartBuilder $partBuilder,
49
        MessageHelperService $messageHelperService,
50
        StreamInterface $stream = null,
51
        StreamInterface $contentStream = null
52
    ) {
53 11
        parent::__construct(
54 11
            $partStreamFilterManager,
55 11
            $streamFactory,
56 11
            $partFilterFactory,
57 11
            $partBuilder,
58 11
            $stream,
59 11
            $contentStream
60
        );
61 11
        $this->messageHelperService = $messageHelperService;
62 11
    }
63
64
    /**
65
     * Convenience method to parse a handle or string into a Message without
66
     * requiring including MailMimeParser, instantiating it, and calling parse.
67
     * 
68
     * @param resource|string $handleOrString the resource handle to the input
69
     *        stream of the mime message, or a string containing a mime message
70
     */
71
    public static function from($handleOrString)
72
    {
73
        $mmp = new MailMimeParser();
74
        return $mmp->parse($handleOrString);
75
    }
76
77
    /**
78
     * Returns the text/plain part at the given index (or null if not found.)
79
     * 
80
     * @param int $index
81
     * @return \ZBateson\MailMimeParser\Message\Part\MimePart
82
     */
83 1
    public function getTextPart($index = 0)
84
    {
85 1
        return $this->getPart(
86 1
            $index,
87 1
            $this->partFilterFactory->newFilterFromInlineContentType('text/plain')
88
        );
89
    }
90
    
91
    /**
92
     * Returns the number of text/plain parts in this message.
93
     * 
94
     * @return int
95
     */
96 1
    public function getTextPartCount()
97
    {
98 1
        return $this->getPartCount(
99 1
            $this->partFilterFactory->newFilterFromInlineContentType('text/plain')
100
        );
101
    }
102
    
103
    /**
104
     * Returns the text/html part at the given index (or null if not found.)
105
     * 
106
     * @param $index
107
     * @return \ZBateson\MailMimeParser\Message\Part\MimePart
108
     */
109 1
    public function getHtmlPart($index = 0)
110
    {
111 1
        return $this->getPart(
112 1
            $index,
113 1
            $this->partFilterFactory->newFilterFromInlineContentType('text/html')
114
        );
115
    }
116
    
117
    /**
118
     * Returns the number of text/html parts in this message.
119
     * 
120
     * @return int
121
     */
122 1
    public function getHtmlPartCount()
123
    {
124 1
        return $this->getPartCount(
125 1
            $this->partFilterFactory->newFilterFromInlineContentType('text/html')
126
        );
127
    }
128
129
    /**
130
     * Returns the attachment part at the given 0-based index, or null if none
131
     * is set.
132
     * 
133
     * @param int $index
134
     * @return ZBateson\MailMimeParser\Message\Part\MessagePart
0 ignored issues
show
Bug introduced by
The type ZBateson\MailMimeParser\...essage\Part\MessagePart was not found. Did you mean ZBateson\MailMimeParser\Message\Part\MessagePart? If so, make sure to prefix the type with \.
Loading history...
135
     */
136 1
    public function getAttachmentPart($index)
137
    {
138 1
        $attachments = $this->getAllAttachmentParts();
139 1
        if (!isset($attachments[$index])) {
140 1
            return null;
141
        }
142 1
        return $attachments[$index];
143
    }
144
145
    /**
146
     * Returns all attachment parts.
147
     * 
148
     * "Attachments" are any non-multipart, non-signature and any text or html
149
     * html part witha Content-Disposition set to  'attachment'.
150
     * 
151
     * @return MessagePart[]
152
     */
153 1
    public function getAllAttachmentParts()
154
    {
155 1
        $parts = $this->getAllParts(
156 1
            $this->partFilterFactory->newFilterFromArray([
157 1
                'multipart' => PartFilter::FILTER_EXCLUDE
158
            ])
159
        );
160 1
        return array_values(array_filter(
161 1
            $parts,
162 1
            function ($part) {
163
                return !(
164 1
                    $part->isTextPart()
165 1
                    && $part->getContentDisposition() === 'inline'
166
                );
167 1
            }
168
        ));
169
    }
170
171
    /**
172
     * Returns the number of attachments available.
173
     * 
174
     * @return int
175
     */
176 1
    public function getAttachmentCount()
177
    {
178 1
        return count($this->getAllAttachmentParts());
179
    }
180
181
    /**
182
     * Returns a Psr7 Stream for the 'inline' text/plain content at the passed
183
     * $index, or null if unavailable.
184
     * 
185
     * @param int $index
186
     * @param string $charset
187
     * @return StreamInterface
188
     */
189 1
    public function getTextStream($index = 0, $charset = MailMimeParser::DEFAULT_CHARSET)
190
    {
191 1
        $textPart = $this->getTextPart($index);
192 1
        if ($textPart !== null) {
193 1
            return $textPart->getContentStream($charset);
194
        }
195 1
        return null;
196
    }
197
198
    /**
199
     * Returns a resource handle for the 'inline' text/plain content at the
200
     * passed $index, or null if unavailable.
201
     *
202
     * @param int $index
203
     * @param string $charset
204
     * @return resource
205
     */
206 1
    public function getTextResourceHandle($index = 0, $charset = MailMimeParser::DEFAULT_CHARSET)
207
    {
208 1
        $textPart = $this->getTextPart($index);
209 1
        if ($textPart !== null) {
210 1
            return $textPart->getContentResourceHandle($charset);
211
        }
212 1
        return null;
213
    }
214
215
    /**
216
     * Returns the content of the inline text/plain part at the given index.
217
     * 
218
     * Reads the entire stream content into a string and returns it.  Returns
219
     * null if the message doesn't have an inline text part.
220
     * 
221
     * @param int $index
222
     * @param string $charset
223
     * @return string
224
     */
225 1
    public function getTextContent($index = 0, $charset = MailMimeParser::DEFAULT_CHARSET)
226
    {
227 1
        $part = $this->getTextPart($index);
228 1
        if ($part !== null) {
229 1
            return $part->getContent($charset);
230
        }
231 1
        return null;
232
    }
233
234
    /**
235
     * Returns a Psr7 Stream for the 'inline' text/html content at the passed
236
     * $index, or null if unavailable.
237
     * 
238
     * @param int $index
239
     * @param string $charset
240
     * @return resource
241
     */
242 1
    public function getHtmlStream($index = 0, $charset = MailMimeParser::DEFAULT_CHARSET)
243
    {
244 1
        $htmlPart = $this->getHtmlPart($index);
245 1
        if ($htmlPart !== null) {
246 1
            return $htmlPart->getContentStream($charset);
247
        }
248 1
        return null;
249
    }
250
251
    /**
252
     * Returns a resource handle for the 'inline' text/html content at the
253
     * passed $index, or null if unavailable.
254
     *
255
     * @param int $index
256
     * @param string $charset
257
     * @return resource
258
     */
259 1
    public function getHtmlResourceHandle($index = 0, $charset = MailMimeParser::DEFAULT_CHARSET)
260
    {
261 1
        $htmlPart = $this->getHtmlPart($index);
262 1
        if ($htmlPart !== null) {
263 1
            return $htmlPart->getContentResourceHandle($charset);
264
        }
265 1
        return null;
266
    }
267
268
    /**
269
     * Returns the content of the inline text/html part at the given index.
270
     * 
271
     * Reads the entire stream content into a string and returns it.  Returns
272
     * null if the message doesn't have an inline html part.
273
     * 
274
     * @param int $index
275
     * @param string $charset
276
     * @return string
277
     */
278 1
    public function getHtmlContent($index = 0, $charset = MailMimeParser::DEFAULT_CHARSET)
279
    {
280 1
        $part = $this->getHtmlPart($index);
281 1
        if ($part !== null) {
282 1
            return $part->getContent($charset);
283
        }
284 1
        return null;
285
    }
286
287
    /**
288
     * Returns true if either a Content-Type or Mime-Version header are defined
289
     * in this Message.
290
     * 
291
     * @return bool
292
     */
293 3
    public function isMime()
294
    {
295 3
        $contentType = $this->getHeaderValue('Content-Type');
296 3
        $mimeVersion = $this->getHeaderValue('Mime-Version');
297 3
        return ($contentType !== null || $mimeVersion !== null);
298
    }
299
300
    /**
301
     * Sets the text/plain part of the message to the passed $stringOrHandle,
302
     * either creating a new part if one doesn't exist for text/plain, or
303
     * assigning the value of $stringOrHandle to an existing text/plain part.
304
     *
305
     * The optional $charset parameter is the charset for saving to.
306
     * $stringOrHandle is expected to be in UTF-8 regardless of the target
307
     * charset.
308
     *
309
     * @param string|resource|StreamInterface $resource
310
     * @param string $charset
311
     */
312 1
    public function setTextPart($resource, $charset = 'UTF-8')
313
    {
314 1
        $this->messageHelperService
315 1
            ->getMultipartHelper()
316 1
            ->setContentPartForMimeType(
317 1
                $this, 'text/plain', $resource, $charset
318
            );
319 1
    }
320
321
    /**
322
     * Sets the text/html part of the message to the passed $stringOrHandle,
323
     * either creating a new part if one doesn't exist for text/html, or
324
     * assigning the value of $stringOrHandle to an existing text/html part.
325
     *
326
     * The optional $charset parameter is the charset for saving to.
327
     * $stringOrHandle is expected to be in UTF-8 regardless of the target
328
     * charset.
329
     *
330
     * @param string|resource|StreamInterface $resource
331
     * @param string $charset
332
     */
333 1
    public function setHtmlPart($resource, $charset = 'UTF-8')
334
    {
335 1
        $this->messageHelperService
336 1
            ->getMultipartHelper()
337 1
            ->setContentPartForMimeType(
338 1
                $this, 'text/html', $resource, $charset
339
            );
340 1
    }
341
342
    /**
343
     * Removes the text/plain part of the message at the passed index if one
344
     * exists.  Returns true on success.
345
     *
346
     * @return bool true on success
347
     */
348 1
    public function removeTextPart($index = 0)
349
    {
350 1
        return $this->messageHelperService
351 1
            ->getMultipartHelper()
352 1
            ->removePartByMimeType(
353 1
                $this, 'text/plain', $index
354
            );
355
    }
356
357
    /**
358
     * Removes all text/plain inline parts in this message, optionally keeping
359
     * other inline parts as attachments on the main message (defaults to
360
     * keeping them).
361
     *
362
     * @param bool $keepOtherPartsAsAttachments
363
     * @return bool true on success
364
     */
365 1
    public function removeAllTextParts($keepOtherPartsAsAttachments = true)
366
    {
367 1
        return $this->messageHelperService
368 1
            ->getMultipartHelper()
369 1
            ->removeAllContentPartsByMimeType(
370 1
                $this, 'text/plain', $keepOtherPartsAsAttachments
371
            );
372
    }
373
374
    /**
375
     * Removes the html part of the message if one exists.  Returns true on
376
     * success.
377
     *
378
     * @return bool true on success
379
     */
380 1
    public function removeHtmlPart($index = 0)
381
    {
382 1
        return $this->messageHelperService
383 1
            ->getMultipartHelper()
384 1
            ->removePartByMimeType(
385 1
                $this, 'text/html', $index
386
            );
387
    }
388
389
    /**
390
     * Removes all text/html inline parts in this message, optionally keeping
391
     * other inline parts as attachments on the main message (defaults to
392
     * keeping them).
393
     *
394
     * @param bool $keepOtherPartsAsAttachments
395
     * @return bool true on success
396
     */
397 1
    public function removeAllHtmlParts($keepOtherPartsAsAttachments = true)
398
    {
399 1
        return $this->messageHelperService
400 1
            ->getMultipartHelper()
401 1
            ->removeAllContentPartsByMimeType(
402 1
                $this, 'text/html', $keepOtherPartsAsAttachments
403
            );
404
    }
405
406
    /**
407
     * Adds an attachment part for the passed raw data string or handle and
408
     * given parameters.
409
     *
410
     * @param string|resource|StreamInterface $resource
411
     * @param string $mimeType
412
     * @param string $filename
413
     * @param string $disposition
414
     */
415 1
    public function addAttachmentPart($resource, $mimeType, $filename = null, $disposition = 'attachment')
416
    {
417 1
        $this->messageHelperService
418 1
            ->getMultipartHelper()
419 1
            ->createAndAddPartForAttachment($this, $resource, $mimeType, $disposition, $filename);
420 1
    }
421
422
    /**
423
     * Adds an attachment part using the passed file.
424
     *
425
     * Essentially creates a file stream and uses it.
426
     *
427
     * @param string $filePath
428
     * @param string $mimeType
429
     * @param string $filename
430
     * @param string $disposition
431
     */
432 1
    public function addAttachmentPartFromFile($filePath, $mimeType, $filename = null, $disposition = 'attachment')
433
    {
434 1
        $handle = Psr7\stream_for(fopen($filePath, 'r'));
0 ignored issues
show
Bug introduced by
The function stream_for was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

434
        $handle = /** @scrutinizer ignore-call */ Psr7\stream_for(fopen($filePath, 'r'));
Loading history...
435 1
        if ($filename === null) {
436 1
            $filename = basename($filePath);
437
        }
438 1
        $this->addAttachmentPart($handle, $mimeType, $filename, $disposition);
439 1
    }
440
441
    /**
442
     * Removes the attachment with the given index
443
     *
444
     * @param int $index
445
     */
446 1
    public function removeAttachmentPart($index)
447
    {
448 1
        $part = $this->getAttachmentPart($index);
449 1
        $this->removePart($part);
450 1
    }
451
452
    /**
453
     * Returns a stream that can be used to read the content part of a signed
454
     * message, which can be used to sign an email or verify a signature.
455
     *
456
     * The method simply returns the stream for the first child.  No
457
     * verification of whether the message is in fact a signed message is
458
     * performed.
459
     *
460
     * Note that unlike getSignedMessageAsString, getSignedMessageStream doesn't
461
     * replace new lines.
462
     *
463
     * @return StreamInterface or null if the message doesn't have any children
464
     */
465 1
    public function getSignedMessageStream()
466
    {
467
        return $this
468 1
            ->messageHelperService
469 1
            ->getPrivacyHelper()
470 1
            ->getSignedMessageStream($this);
471
    }
472
473
    /**
474
     * Returns a string containing the entire body of a signed message for
475
     * verification or calculating a signature.
476
     *
477
     * Non-CRLF new lines are replaced to always be CRLF.
478
     *
479
     * @return string or null if the message doesn't have any children
480
     */
481 1
    public function getSignedMessageAsString()
482
    {
483
        return $this
484 1
            ->messageHelperService
485 1
            ->getPrivacyHelper()
486 1
            ->getSignedMessageAsString($this);
487
    }
488
489
    /**
490
     * Returns the signature part of a multipart/signed message or null.
491
     *
492
     * The signature part is determined to always be the 2nd child of a
493
     * multipart/signed message, the first being the 'body'.
494
     *
495
     * Using the 'protocol' parameter of the Content-Type header is unreliable
496
     * in some instances (for instance a difference of x-pgp-signature versus
497
     * pgp-signature).
498
     *
499
     * @return MimePart
500
     */
501
    public function getSignaturePart()
502
    {
503
        return $this
504
            ->messageHelperService
505
            ->getPrivacyHelper()
506
            ->getSignaturePart($this);
507
    }
508
509
    /**
510
     * Turns the message into a multipart/signed message, moving the actual
511
     * message into a child part, sets the content-type of the main message to
512
     * multipart/signed and adds an empty signature part as well.
513
     *
514
     * After calling setAsMultipartSigned, call getSignedMessageAsString to
515
     * return a
516
     *
517
     * @param string $micalg The Message Integrity Check algorithm being used
518
     * @param string $protocol The mime-type of the signature body
519
     */
520 1
    public function setAsMultipartSigned($micalg, $protocol)
521
    {
522
        $this
523 1
            ->messageHelperService
524 1
            ->getPrivacyHelper()
525 1
            ->setMessageAsMultipartSigned($this, $micalg, $protocol);
526 1
    }
527
528
    /**
529
     * Sets the signature body of the message to the passed $body for a
530
     * multipart/signed message.
531
     *
532
     * @param string $body
533
     */
534 1
    public function setSignature($body)
535
    {
536 1
        $this->messageHelperService->getPrivacyHelper()
537 1
            ->setSignature($this, $body);
538 1
    }
539
}
540