Passed
Push — master ( 24955d...c95513 )
by Zaahid
06:27 queued 13s
created

MimePart::__construct()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 7.4572

Importance

Changes 0
Metric Value
eloc 15
c 0
b 0
f 0
dl 0
loc 24
ccs 7
cts 13
cp 0.5385
rs 9.4555
cc 5
nc 4
nop 4
crap 7.4572
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 138
    public function __construct(
29
        IMimePart $parent = null,
30
        PartStreamContainer $streamContainer = null,
31
        PartHeaderContainer $headerContainer = null,
32
        PartChildrenContainer $partChildrenContainer = null
33
    ) {
34 138
        $setStream = false;
35 138
        $di = MailMimeParser::getDependencyContainer();
36 138
        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 138
        parent::__construct(
43
            $parent,
44
            $streamContainer,
45
            $partChildrenContainer
46
        );
47 138
        if ($setStream) {
48
            $streamFactory = $di['ZBateson\MailMimeParser\Stream\StreamFactory'];
49
            $streamContainer->setStream($streamFactory->newMessagePartStream($this));
50
        }
51 138
        $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 56
    public function getFilename()
64
    {
65 56
        return $this->getHeaderParameter(
66
            HeaderConsts::CONTENT_DISPOSITION,
67
            'filename',
68 56
            $this->getHeaderParameter(
69
                HeaderConsts::CONTENT_TYPE,
70
                'name'
71
            )
72
        );
73
    }
74
75
    /**
76
     * Returns true.
77
     *
78
     * @return bool
79
     */
80 2
    public function isMime()
81
    {
82 2
        return true;
83
    }
84
85 57
    public function isMultiPart()
86
    {
87
        // casting to bool, preg_match returns 1 for true
88 57
        return (bool) (preg_match(
89
            '~multipart/.*~i',
90 57
            $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 48
    public function isTextPart()
107
    {
108 48
        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 108
    public function getContentType($default = 'text/plain')
126
    {
127 108
        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 104
    public function getCharset()
142
    {
143 104
        $charset = $this->getHeaderParameter(HeaderConsts::CONTENT_TYPE, 'charset');
144 104
        if ($charset === null || strcasecmp($charset, 'binary') === 0) {
145 76
            $contentType = $this->getContentType();
146 76
            if ($contentType === 'text/plain' || $contentType === 'text/html') {
147 11
                return 'ISO-8859-1';
148
            }
149 68
            return null;
150
        }
151 84
        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 97
    public function getContentDisposition($default = 'inline')
168
    {
169 97
        $value = $this->getHeaderValue(HeaderConsts::CONTENT_DISPOSITION);
170 97
        if ($value === null || !in_array($value, [ 'inline', 'attachment' ])) {
171 95
            return $default;
172
        }
173 55
        return strtolower($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 103
    public function getContentTransferEncoding($default = '7bit')
192
    {
193
        static $translated = [
194
            'x-uue' => 'x-uuencode',
195
            'uue' => 'x-uuencode',
196
            'uuencode' => 'x-uuencode'
197
        ];
198 103
        $type = strtolower($this->getHeaderValue(HeaderConsts::CONTENT_TRANSFER_ENCODING, $default));
199 103
        if (isset($translated[$type])) {
200 2
            return $translated[$type];
201
        }
202 103
        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 3
    public function getContentId()
213
    {
214 3
        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 57
    public function isSignaturePart()
224
    {
225 57
        if ($this->parent === null || !$this->parent instanceof IMessage) {
226 20
            return false;
227
        }
228 52
        return $this->parent->getSignaturePart() === $this;
229
    }
230
231 118
    public function getHeader($name, $offset = 0)
232
    {
233 118
        return $this->headerContainer->get($name, $offset);
234
    }
235
236 19
    public function getAllHeaders()
237
    {
238 19
        return $this->headerContainer->getHeaderObjects();
239
    }
240
241 1
    public function getAllHeadersByName($name)
242
    {
243 1
        return $this->headerContainer->getAll($name);
244
    }
245
246 1
    public function getRawHeaders()
247
    {
248 1
        return $this->headerContainer->getHeaders();
249
    }
250
251 93
    public function getRawHeaderIterator()
252
    {
253 93
        return $this->headerContainer->getIterator();
254
    }
255
256 115
    public function getHeaderValue($name, $defaultValue = null)
257
    {
258 115
        $header = $this->getHeader($name);
259 115
        if ($header !== null) {
260 114
            return $header->getValue();
261
        }
262 105
        return $defaultValue;
263
    }
264
265 107
    public function getHeaderParameter($header, $param, $defaultValue = null)
266
    {
267 107
        $obj = $this->getHeader($header);
268 107
        if ($obj && $obj instanceof ParameterHeader) {
269 103
            return $obj->getValueFor($param, $defaultValue);
270
        }
271 13
        return $defaultValue;
272
    }
273
274 22
    public function setRawHeader($name, $value, $offset = 0)
275
    {
276 22
        $this->headerContainer->set($name, $value, $offset);
277 22
        $this->notify();
278
    }
279
280 1
    public function addRawHeader($name, $value)
281
    {
282 1
        $this->headerContainer->add($name, $value);
283 1
        $this->notify();
284
    }
285
286 18
    public function removeHeader($name)
287
    {
288 18
        $this->headerContainer->removeAll($name);
289 18
        $this->notify();
290
    }
291
292 1
    public function removeSingleHeader($name, $offset = 0)
293
    {
294 1
        $this->headerContainer->remove($name, $offset);
295 1
        $this->notify();
296
    }
297
}
298