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

MimePart::isMultiPart()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 6
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;
8
9
use ZBateson\MailMimeParser\IMessage;
10
use ZBateson\MailMimeParser\MailMimeParser;
11
use ZBateson\MailMimeParser\Header\HeaderConsts;
12
use ZBateson\MailMimeParser\Header\ParameterHeader;
13
14
/**
15
 * A mime email message part.
16
 *
17
 * A MIME part may contain any combination of headers, content and children.
18
 *
19
 * @author Zaahid Bateson
20
 */
21
class MimePart extends MultiPart implements IMimePart
22
{
23
    /**
24
     * @var PartHeaderContainer Container for this part's headers.
25
     */
26
    protected $headerContainer;
27
28
    public function __construct(
29
        IMimePart $parent = null,
30
        PartStreamContainer $streamContainer = null,
31
        PartHeaderContainer $headerContainer = null,
32
        PartChildrenContainer $partChildrenContainer = null
33
    ) {
34
        $setStream = false;
35
        $di = MailMimeParser::getDependencyContainer();
36
        if ($streamContainer === null || $headerContainer === null || $partChildrenContainer === null) {
37
            $headerContainer = $di['ZBateson\MailMimeParser\Message\PartHeaderContainer'];
38
            $streamContainer = $di['ZBateson\MailMimeParser\Message\PartStreamContainer'];
39
            $partChildrenContainer = $di['ZBateson\MailMimeParser\Message\PartChildrenContainer'];
40
            $setStream = true;
41
        }
42
        parent::__construct(
43
            $parent,
44
            $streamContainer,
45
            $partChildrenContainer
46
        );
47
        if ($setStream) {
48
            $streamFactory = $di['ZBateson\MailMimeParser\Stream\StreamFactory'];
49
            $streamContainer->setStream($streamFactory->newMessagePartStream($this));
50
        }
51
        $this->headerContainer = $headerContainer;
52
    }
53
54
    /**
55
     * Returns a filename for the part if one is defined, or null otherwise.
56
     *
57
     * Uses the 'filename' parameter of the Content-Disposition header if it
58
     * exists, or the 'name' parameter of the 'Content-Type' header if it
59
     * doesn't.
60
     *
61
     * @return string|null the file name of the part or null.
62
     */
63
    public function getFilename()
64
    {
65
        return $this->getHeaderParameter(
66
            HeaderConsts::CONTENT_DISPOSITION,
67
            'filename',
68
            $this->getHeaderParameter(
69
                HeaderConsts::CONTENT_TYPE,
70
                'name'
71
            )
72
        );
73
    }
74
75
    /**
76
     * Returns true.
77
     *
78
     * @return bool
79
     */
80
    public function isMime()
81
    {
82
        return true;
83
    }
84
85
    public function isMultiPart()
86
    {
87
        // casting to bool, preg_match returns 1 for true
88
        return (bool) (preg_match(
89
            '~multipart/.*~i',
90
            $this->getContentType()
91
        ));
92
    }
93
94
    /**
95
     * Returns true if this part has a defined 'charset' on its Content-Type
96
     * header.
97
     *
98
     * This may result in some false positives if charset is set on a part that
99
     * is not plain text which has been seen.  If a part is known to be binary,
100
     * it's better to use {@see IMessagePart::getBinaryContentStream()} to
101
     * avoid issues, or to call {@see IMessagePart::saveContent()} directly if
102
     * saving a part's content.
103
     *
104
     * @return bool
105
     */
106
    public function isTextPart()
107
    {
108
        return ($this->getCharset() !== null);
109
    }
110
111
    /**
112
     * Returns the mime type of the content, or $default if one is not set.
113
     *
114
     * Looks at the part's Content-Type header and returns its value if set, or
115
     * defaults to 'text/plain'.
116
     *
117
     * Note that the returned value is converted to lower case, and may not be
118
     * identical to calling {@see MimePart::getHeaderValue('Content-Type')} in
119
     * some cases.
120
     *
121
     * @param string $default Optional default value to specify a default other
122
     *        than text/plain if needed.
123
     * @return string the mime type
124
     */
125
    public function getContentType($default = 'text/plain')
126
    {
127
        return strtolower($this->getHeaderValue(HeaderConsts::CONTENT_TYPE, $default));
128
    }
129
130
    /**
131
     * Returns the charset of the content, or null if not applicable/defined.
132
     *
133
     * Looks for a 'charset' parameter under the 'Content-Type' header of this
134
     * part and returns it if set, defaulting to 'ISO-8859-1' if the
135
     * Content-Type header exists and is of type text/plain or text/html.
136
     *
137
     * Note that the returned value is also converted to upper case.
138
     *
139
     * @return string|null the charset
140
     */
141
    public function getCharset()
142
    {
143
        $charset = $this->getHeaderParameter(HeaderConsts::CONTENT_TYPE, 'charset');
144
        if ($charset === null || strcasecmp($charset, 'binary') === 0) {
145
            $contentType = $this->getContentType();
146
            if ($contentType === 'text/plain' || $contentType === 'text/html') {
147
                return 'ISO-8859-1';
148
            }
149
            return null;
150
        }
151
        return strtoupper($charset);
152
    }
153
154
    /**
155
     * Returns the content's disposition, or returns the value of $default if
156
     * not defined.
157
     *
158
     * Looks at the 'Content-Disposition' header, which should only contain
159
     * either 'inline' or 'attachment'.  If the header is not one of those
160
     * values, $default is returned, which defaults to 'inline' unless passed
161
     * something else.
162
     *
163
     * @param string $default Optional default value if not set or does not
164
     *        match 'inline' or 'attachment'.
165
     * @return string the content disposition
166
     */
167
    public function getContentDisposition($default = 'inline')
168
    {
169
        $value = strtolower($this->getHeaderValue(HeaderConsts::CONTENT_DISPOSITION));
0 ignored issues
show
Bug introduced by
It seems like $this->getHeaderValue(ZB...s::CONTENT_DISPOSITION) can also be of type null; however, parameter $string of strtolower() does only seem to accept string, 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

169
        $value = strtolower(/** @scrutinizer ignore-type */ $this->getHeaderValue(HeaderConsts::CONTENT_DISPOSITION));
Loading history...
170
        if ($value === null || !in_array($value, [ 'inline', 'attachment' ])) {
171
            return $default;
172
        }
173
        return $value;
174
    }
175
176
    /**
177
     * Returns the content transfer encoding used to encode the content on this
178
     * part, or the value of $default if not defined.
179
     *
180
     * Looks up and returns the value of the 'Content-Transfer-Encoding' header
181
     * if set, defaulting to '7bit' if an alternate $default param is not
182
     * passed.
183
     *
184
     * The returned value is always lowercase, and header values of 'x-uue',
185
     * 'uue' and 'uuencode' will return 'x-uuencode' instead.
186
     *
187
     * @param string $default Optional default value to return if the header
188
     *        isn't set.
189
     * @return string the content transfer encoding.
190
     */
191
    public function getContentTransferEncoding($default = '7bit')
192
    {
193
        static $translated = [
194
            'x-uue' => 'x-uuencode',
195
            'uue' => 'x-uuencode',
196
            'uuencode' => 'x-uuencode'
197
        ];
198
        $type = strtolower($this->getHeaderValue(HeaderConsts::CONTENT_TRANSFER_ENCODING, $default));
199
        if (isset($translated[$type])) {
200
            return $translated[$type];
201
        }
202
        return $type;
203
    }
204
205
    /**
206
     * Returns the Content ID of the part, or null if not defined.
207
     *
208
     * Looks up and returns the value of the 'Content-ID' header.
209
     *
210
     * @return string|null the content ID or null if not defined.
211
     */
212
    public function getContentId()
213
    {
214
        return $this->getHeaderValue(HeaderConsts::CONTENT_ID);
215
    }
216
217
    /**
218
     * Returns true if this part's parent is an IMessage, and is the same part
219
     * returned by {@see IMessage::getSignaturePart()}.
220
     *
221
     * @return bool
222
     */
223
    public function isSignaturePart()
224
    {
225
        if ($this->parent === null || !$this->parent instanceof IMessage) {
226
            return false;
227
        }
228
        return $this->parent->getSignaturePart() === $this;
229
    }
230
231
    public function getHeader($name, $offset = 0)
232
    {
233
        return $this->headerContainer->get($name, $offset);
234
    }
235
236
    public function getAllHeaders()
237
    {
238
        return $this->headerContainer->getHeaderObjects();
239
    }
240
241
    public function getAllHeadersByName($name)
242
    {
243
        return $this->headerContainer->getAll($name);
244
    }
245
246
    public function getRawHeaders()
247
    {
248
        return $this->headerContainer->getHeaders();
249
    }
250
251
    public function getRawHeaderIterator()
252
    {
253
        return $this->headerContainer->getIterator();
254
    }
255
256
    public function getHeaderValue($name, $defaultValue = null)
257
    {
258
        $header = $this->getHeader($name);
259
        if ($header !== null) {
260
            return $header->getValue();
261
        }
262
        return $defaultValue;
263
    }
264
265
    public function getHeaderParameter($header, $param, $defaultValue = null)
266
    {
267
        $obj = $this->getHeader($header);
268
        if ($obj && $obj instanceof ParameterHeader) {
269
            return $obj->getValueFor($param, $defaultValue);
270
        }
271
        return $defaultValue;
272
    }
273
274
    public function setRawHeader($name, $value, $offset = 0)
275
    {
276
        $this->headerContainer->set($name, $value, $offset);
277
        $this->notify();
278
    }
279
280
    public function addRawHeader($name, $value)
281
    {
282
        $this->headerContainer->add($name, $value);
283
        $this->notify();
284
    }
285
286
    public function removeHeader($name)
287
    {
288
        $this->headerContainer->removeAll($name);
289
        $this->notify();
290
    }
291
292
    public function removeSingleHeader($name, $offset = 0)
293
    {
294
        $this->headerContainer->remove($name, $offset);
295
        $this->notify();
296
    }
297
}
298