Test Failed
Push — 2.0 ( 3431b8...9e8731 )
by Zaahid
03:11
created

GenericHelper::isMimeContentField()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 4
rs 10
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\Message\Helper;
8
9
use ZBateson\MailMimeParser\MailMimeParser;
10
use ZBateson\MailMimeParser\IMessage;
11
use ZBateson\MailMimeParser\Header\IHeader;
12
use ZBateson\MailMimeParser\Header\HeaderConsts;
13
use ZBateson\MailMimeParser\Message\IMimePart;
14
15
/**
16
 * Provides common Message helper routines for Message manipulation.
17
 *
18
 * @author Zaahid Bateson
19
 */
20
class GenericHelper extends AbstractHelper
21
{
22
    /**
23
     * @var string[] non mime content fields that are not related to the content
24
     *      of a part.
25
     */
26
    private static $nonMimeContentFields = [ 'contentreturn', 'contentidentifier' ];
27
28
    /**
29
     * Returns true if the passed header's name is a Content-* header other than
30
     * one defined in the static $nonMimeContentFields
31
     *
32
     * @param IHeader $header
33
     * @param string $exceptions
34
     */
35
    private function isMimeContentField(IHeader $header, array $exceptions = [])
36
    {
37
        return (stripos($header->getName(), 'Content') === 0
38
            && !in_array(strtolower(str_replace('-', '', $header->getName())), array_merge(static::$nonMimeContentFields, $exceptions)));
0 ignored issues
show
Bug introduced by
Since $nonMimeContentFields is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $nonMimeContentFields to at least protected.
Loading history...
39
    }
40
41
    /**
42
     * Copies the passed $header from $from, to $to or sets the header to
43
     * $default if it doesn't exist in $from.
44
     *
45
     * @param IMimePart $from
46
     * @param IMimePart $to
47
     * @param string $header
48
     * @param string $default
49
     */
50
    public function copyHeader(IMimePart $from, IMimePart $to, $header, $default = null)
51
    {
52
        $fromHeader = $from->getHeader($header);
53
        $set = ($fromHeader !== null) ? $fromHeader->getRawValue() : $default;
54
        if ($set !== null) {
55
            $to->setRawHeader($header, $set);
56
        }
57
    }
58
59
    /**
60
     * Removes Content-* headers from the passed part, then detaches its content
61
     * stream.
62
     *
63
     * An exception is made for the obsolete Content-Return header, which isn't
64
     * isn't a MIME content field and so isn't removed.
65
     * 
66
     * @param IMimePart $part
67
     */
68
    public function removeContentHeadersAndContent(IMimePart $part)
69
    {
70
        foreach ($part->getAllHeaders() as $header) {
71
            if ($this->isMimeContentField($header)) {
72
                $part->removeHeader($header->getName());
73
            }
74
        }
75
        $part->detachContentStream();
76
    }
77
78
    /**
79
     * Copies Content-* headers from the $from header into the $to header. If
80
     * the Content-Type header isn't defined in $from, defaults to text/plain
81
     * with utf-8 and quoted-printable as its Content-Transfer-Encoding.
82
     *
83
     * An exception is made for the obsolete Content-Return header, which isn't
84
     * isn't a MIME content field and so isn't copied.
85
     *
86
     * @param IMimePart $from
87
     * @param IMimePart $to
88
     * @param bool $move
89
     */
90
    public function copyContentHeadersAndContent(IMimePart $from, IMimePart $to, $move = false)
91
    {
92
        $this->copyHeader($from, $to, HeaderConsts::CONTENT_TYPE, 'text/plain; charset=utf-8');
93
        if ($from->getHeader(HeaderConsts::CONTENT_TYPE) === null) {
94
            $this->copyHeader($from, $to, HeaderConsts::CONTENT_TRANSFER_ENCODING, 'quoted-printable');
95
        } else {
96
            $this->copyHeader($from, $to, HeaderConsts::CONTENT_TRANSFER_ENCODING);
97
        }
98
        foreach ($from->getAllHeaders() as $header) {
99
            if ($this->isMimeContentField($header, [ 'contenttype', 'contenttransferencoding' ])) {
100
                $this->copyHeader($from, $to, $header->getName());
101
            }
102
        }
103
        if ($from->hasContent()) {
104
            $to->attachContentStream($from->getContentStream(), MailMimeParser::DEFAULT_CHARSET);
0 ignored issues
show
Bug introduced by
It seems like $from->getContentStream() can also be of type null; however, parameter $stream of ZBateson\MailMimeParser\...::attachContentStream() does only seem to accept Psr\Http\Message\StreamInterface, maybe add an additional type check? ( Ignorable by Annotation )

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

104
            $to->attachContentStream(/** @scrutinizer ignore-type */ $from->getContentStream(), MailMimeParser::DEFAULT_CHARSET);
Loading history...
105
        }
106
        if ($move) {
107
            $this->removeContentHeadersAndContent($from);
108
        }
109
    }
110
111
    /**
112
     * Creates a new content part from the passed part, allowing the part to be
113
     * used for something else (e.g. changing a non-mime message to a multipart
114
     * mime message).
115
     *
116
     * @param IMimePart $part
117
     * @return MimePart the newly-created MimePart
0 ignored issues
show
Bug introduced by
The type ZBateson\MailMimeParser\Message\Helper\MimePart was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
118
    */
119
    public function createNewContentPartFrom(IMimePart $part)
120
    {
121
        $mime = $this->mimePartFactory->newInstance();
122
        $this->copyContentHeadersAndContent($part, $mime, true);
123
        return $mime;
124
    }
125
126
    /**
127
     * Copies type headers (Content-Type, Content-Disposition,
128
     * Content-Transfer-Encoding) from the $from MimePart to $to.  Attaches the
129
     * content resource handle of $from to $to, and loops over child parts,
130
     * removing them from $from and adding them to $to.
131
     *
132
     * @param IMimePart $from
133
     * @param IMimePart $to
134
     */
135
    public function movePartContentAndChildren(IMimePart $from, IMimePart $to)
136
    {
137
        $this->copyContentHeadersAndContent($from, $to, true);
138
        if ($from->getChildCount() > 0) {
139
            foreach ($from->getChildIterator() as $child) {
140
                $from->removePart($child);
141
                $to->addChild($child);
142
            }
143
        }
144
    }
145
146
    /**
147
     * Replaces the $part IMimePart with $replacement.
148
     *
149
     * Essentially removes $part from its parent, and adds $replacement in its
150
     * same position.  If $part is the IMessage, then $part can't be removed and
151
     * replaced, and instead $replacement's type headers are copied to $message,
152
     * and any children below $replacement are added directly below $message.
153
     *
154
     * @param IMessage $message
155
     * @param IMimePart $part
156
     * @param IMimePart $replacement
157
     */
158
    public function replacePart(IMessage $message, IMimePart $part, IMimePart $replacement)
159
    {
160
        $position = $message->removePart($replacement);
161
        if ($part === $message) {
0 ignored issues
show
introduced by
The condition $part === $message is always false.
Loading history...
162
            $this->movePartContentAndChildren($replacement, $message);
163
            return;
164
        }
165
        $parent = $part->getParent();
166
        $parent->addChild($replacement, $position);
167
        $parent->removePart($part);
168
    }
169
}
170