Test Failed
Branch 1.0.0 (84f469)
by Zaahid
05:36
created

MessagePart::getContentResourceHandle()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 20
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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