Passed
Push — 1.0.0 ( a1adee...bca153 )
by Zaahid
03:20
created

MessagePart::getFilename()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
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\Part;
8
9
use ZBateson\MailMimeParser\MailMimeParser;
10
11
/**
12
 * Represents a single part of a message.
13
 *
14
 * A MessagePart object may have any number of child parts, or may be a child
15
 * itself with its own parent or parents.
16
 *
17
 * The content of the part can be read from its PartStream resource handle,
18
 * accessible via MimePart::getContentResourceHanlde.
19
 *
20
 * @author Zaahid Bateson
21
 */
22
abstract class MessagePart
23
{
24
    /**
25
     * @var \ZBateson\MailMimeParser\Message\Part\MimePart parent part
26
     */
27
    protected $parent;
28
29
    /**
30
     * @var resource a resource handle containing this part's headers, content
31
     *      and children
32
     */
33
    protected $handle;
34
    
35
    /**
36
     * @var string url for opening a content handle with partStreamFilterManager
37
     */
38
    protected $contentUrl;
39
    
40
    /**
41
     * @var PartStreamFilterManager manages attached filters to $contentHandle
42
     */
43
    protected $partStreamFilterManager;
44
    
45
    /**
46
     * @var string a unique ID representing the message this part belongs to.
47
     */
48
    protected $messageObjectId;
49
    
50
    /**
51
     * @var string can be used to set an override for content's charset in cases
52
     *      where a user wants to set a default other than ISO-8859-1.
53
     */
54
    protected $charsetOverride;
55
56
    /**
57
     * Sets up class dependencies.
58
     * 
59
     * @param string $messageObjectId
60
     * @param PartBuilder $partBuilder
61
     * @param PartStreamFilterManager $partStreamFilterManager
62
     */
63 6
    public function __construct(
64
        $messageObjectId,
65
        PartBuilder $partBuilder,
66
        PartStreamFilterManager $partStreamFilterManager
67
    ) {
68 6
        $this->messageObjectId = $messageObjectId;
69 6
        $partUrl = $partBuilder->getStreamPartUrl($messageObjectId);
70 6
        $this->contentUrl = $partBuilder->getStreamContentUrl($messageObjectId);
71 6
        $partStreamFilterManager->setContentUrl($this->contentUrl);
72 6
        $this->partStreamFilterManager = $partStreamFilterManager;
73 6
        if ($partUrl !== null) {
74 2
            $this->handle = fopen($partUrl, 'r');
75 2
        }
76 6
    }
77
78
    /**
79
     * Closes the attached resource handles.
80
     */
81 6
    public function __destruct()
82
    {
83
        // stream_filter_append may be cleaned up by PHP, but for large files
84
        // and many emails may be more efficient to fully clean up
85 6
        $this->partStreamFilterManager->setContentUrl(null);
86 6
        if (is_resource($this->handle)) {
87 2
            fclose($this->handle);
88 2
        }
89 6
    }
90
    
91
    /**
92
     * Returns the unique object ID registered with the PartStreamRegistry
93
     * service object for the message this part belongs to.
94
     * 
95
     * @return string
96
     * @see \ZBateson\MailMimeParser\SimpleDi::registerStreamExtensions
97
     * @see \ZBateson\MailMimeParser\Stream\PartStream::stream_open
98
     */
99 1
    public function getMessageObjectId()
100
    {
101 1
        return $this->messageObjectId;
102
    }
103
104
    /**
105
     * Returns true if there's a content stream associated with the part.
106
     *
107
     * @return boolean
108
     */
109 5
    public function hasContent()
110
    {
111 5
        if ($this->contentUrl !== null) {
112 3
            return true;
113
        }
114 2
        return false;
115
    }
116
117
    /**
118
     * Returns true if this part's mime type is text/plain, text/html or has a
119
     * text/* and has a defined 'charset' attribute.
120
     * 
121
     * @return bool
122
     */
123
    public abstract function isTextPart();
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
124
    
125
    /**
126
     * Returns the mime type of the content.
127
     * 
128
     * @return string
129
     */
130
    public abstract function getContentType();
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
131
    
132
    /**
133
     * Returns the charset of the content, or null if not applicable/defined.
134
     * 
135
     * @return string
136
     */
137
    public abstract function getCharset();
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
138
    
139
    /**
140
     * Returns the content's disposition.
141
     * 
142
     * @return string
143
     */
144
    public abstract function getContentDisposition();
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
145
    
146
    /**
147
     * Returns the content-transfer-encoding used for this part.
148
     * 
149
     * @return string
150
     */
151
    public abstract function getContentTransferEncoding();
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
152
    
153
    /**
154
     * Returns a filename for the part if one is defined, or null otherwise.
155
     * 
156
     * @return string
157
     */
158
    public function getFilename()
159
    {
160
        return null;
161
    }
162
    
163
    /**
164
     * Returns true if the current part is a mime part.
165
     * 
166
     * @return bool
167
     */
168
    public abstract function isMime();
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
169
    
170
    /**
171
     * Returns a resource stream handle allowing a user to read the original
172
     * stream (including headers and child parts) that was used to create the
173
     * current part.
174
     * 
175
     * Note that 'rewind()' is called on the resource prior to returning it,
176
     * which may affect other read operations if multiple calls to 'getHandle'
177
     * are used.
178
     * 
179
     * The resource stream is handled by MessagePart and is closed by the
180
     * destructor.
181
     * 
182
     * @return resource the resource handle or null if not set
183
     */
184 3
    public function getHandle()
185
    {
186 3
        if (is_resource($this->handle)) {
187 2
            rewind($this->handle);
188 2
        }
189 3
        return $this->handle;
190
    }
191
192
    /**
193
     * Overrides the default character set used for reading content from content
194
     * streams in cases where a user knows the source charset is not what is
195
     * specified.
196
     * 
197
     * If set, the returned value from MessagePart::getCharset is ignored.
198
     * 
199
     * Note that setting an override on a Message and calling getTextStream,
200
     * getTextContent, getHtmlStream or getHtmlContent will not be applied to
201
     * those sub-parts, unless the text/html part is the Message itself.
202
     * Instead, Message:getTextPart() should be called, and setCharsetOverride
203
     * called on the returned MessagePart.
204
     * 
205
     * @param string $charsetOverride
206
     * @param boolean $onlyIfNoCharset if true, $charsetOverride is used only if
207
     *        getCharset returns null.
208
     */
209 1
    public function setCharsetOverride($charsetOverride, $onlyIfNoCharset = false)
210
    {
211 1
        if (!$onlyIfNoCharset || $this->getCharset() === null) {
212 1
            $this->charsetOverride = $charsetOverride;
213 1
        }
214 1
    }
215
216
    /**
217
     * Returns the resource stream handle for the part's content or null if not
218
     * set.  rewind() is called on the stream before returning it.
219
     *
220
     * The resource is automatically closed by MimePart's destructor and should
221
     * not be closed otherwise.
222
     *
223
     * The returned resource handle is a stream with decoding filters appended
224
     * to it.  The attached filters are determined by looking at the part's
225
     * Content-Transfer-Encoding and Content-Type headers unless a charset
226
     * override is set.  The following transfer encodings are supported:
227
     *
228
     * - quoted-printable
229
     * - base64
230
     * - x-uuencode
231
     *
232
     * In addition a ZBateson\MailMimeParser\Stream\CharsetStreamFilter is
233
     * attached for text parts to convert from the content's charset to the
234
     * target charset passed in as an argument (defaults to UTF-8).
235
     *
236
     * @param string $charset
237
     * @return resource
238
     */
239 6
    public function getContentResourceHandle($charset = MailMimeParser::DEFAULT_CHARSET)
240
    {
241 6
        if ($this->contentUrl !== null) {
242 4
            $tr = $this->getContentTransferEncoding();
243 4
            $ch = ($this->charsetOverride !== null) ? $this->charsetOverride : $this->getCharset();
244 4
            return $this->partStreamFilterManager->getContentHandle(
245 4
                $tr,
246 4
                $ch,
247
                $charset
248 4
            );
249
        }
250 2
        return null;
251
    }
252
253
    /**
254
     * Shortcut to reading stream content and assigning it to a string.  Returns
255
     * null if the part doesn't have a content stream.
256
     * 
257
     * The returned string is encoded to the passed $charset character encoding,
258
     * defaulting to UTF-8.
259
     *
260
     * @return string
261
     */
262 2
    public function getContent($charset = MailMimeParser::DEFAULT_CHARSET)
263
    {
264 2
        if ($this->hasContent()) {
265 1
            $handle = $this->getContentResourceHandle($charset);
266 1
            $pos = ftell($handle);
267 1
            rewind($handle);
268 1
            $text = stream_get_contents($handle);
269 1
            fseek($handle, $pos);
270 1
            return $text;
271
        }
272 1
        return null;
273
    }
274
275
    /**
276
     * Returns this part's parent.
277
     *
278
     * @return \ZBateson\MailMimeParser\Message\Part\MimePart
279
     */
280 1
    public function getParent()
281
    {
282 1
        return $this->parent;
283
    }
284
}
285