Completed
Push — master ( 487db1...396d03 )
by Zaahid
02:25
created

PartStreamRegistry::increaseHandleRefCount()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
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\Stream;
8
9
use ZBateson\MailMimeParser\MimePart;
10
use ZBateson\MailMimeParser\Message;
11
12
/**
13
 * Factory class for PartStream objects and registration class for Message
14
 * handles.
15
 * 
16
 * PartStreamRegistry is used for \ZBateson\MailMimeParser\MessageParser to
17
 * register Message stream handles for opening with PartStreams, and to open
18
 * file handles for specific mime parts of a message.  The PartStreamRegistry
19
 * maintains a list of opened resources, closing them either when unregistering
20
 * a Message or on destruction.
21
 *
22
 * @author Zaahid Bateson
23
 */
24
class PartStreamRegistry
25
{
26
    /**
27
     * @var array Array of handles, with message IDs as keys.
28
     */
29
    private $registeredHandles;
30
31
    /**
32
     * @var int[] number of registered part stream handles with message IDs as
33
     * keys
34
     */
35
    private $numRefCountsForHandles;
36
37
    /**
38
     * Registers an ID for the passed resource handle.
39
     * 
40
     * @param string $id
41
     * @param resource $handle
42
     */
43
    public function register($id, $handle)
44
    {
45
        if (!isset($this->registeredHandles[$id])) {
46
            $this->registeredHandles[$id] = $handle;
47
            $this->numRefCountsForHandles[$id] = 0;
48
        }
49
    }
50
51
    /**
52
     * Unregisters the given message ID and closes the associated resource
53
     * handle.
54
     * 
55
     * @param string $id
56
     */
57
    protected function unregister($id)
58
    {
59
        fclose($this->registeredHandles[$id]);
60
        unset($this->registeredHandles[$id], $this->registeredPartStreamHandles[$id]);
61
    }
62
    
63
    /**
64
     * Increases the reference count for streams using the resource handle
65
     * associated with the message id.
66
     * 
67
     * @param int $messageId
68
     */
69
    public function increaseHandleRefCount($messageId)
70
    {
71
        $this->numRefCountsForHandles[$messageId] += 1;
72
    }
73
    
74
    /**
75
     * Decreases the reference count for streams using the resource handle
76
     * associated with the message id.  Once the reference count hits 0,
77
     * unregister is called.
78
     * 
79
     * @param int $messageId
80
     */
81
    public function decreaseHandleRefCount($messageId)
82
    {
83
        $this->numRefCountsForHandles[$messageId] -= 1;
84
        if ($this->numRefCountsForHandles[$messageId] === 0) {
85
            $this->unregister($messageId);
86
        }
87
    }
88
89
    /**
90
     * Returns the resource handle with the passed $id.
91
     * 
92
     * @param string $id
93
     * @return resource
94
     */
95
    public function get($id)
96
    {
97
        if (!isset($this->registeredHandles[$id])) {
98
            return null;
99
        }
100
        return $this->registeredHandles[$id];
101
    }
102
    
103
    /**
104
     * Attaches a stream filter on the passed resource $handle for the part's
105
     * encoding.
106
     * 
107
     * @param \ZBateson\MailMimeParser\MimePart $part
108
     * @param resource $handle
109
     */
110
    private function attachEncodingFilterToStream(MimePart $part, $handle)
111
    {
112
        $encoding = strtolower($part->getHeaderValue('Content-Transfer-Encoding'));
113
        switch ($encoding) {
114
            case 'quoted-printable':
115
                stream_filter_append($handle, 'convert.quoted-printable-decode', STREAM_FILTER_READ);
116
                break;
117
            case 'base64':
118
                stream_filter_append($handle, 'convert.base64-decode', STREAM_FILTER_READ);
119
                break;
120
            case 'x-uuencode':
121
                stream_filter_append($handle, 'mailmimeparser-uudecode', STREAM_FILTER_READ);
122
                break;
123
            default:
124
                break;
125
        }
126
    }
127
    
128
    /**
129
     * Attaches a mailmimeparser-encode stream filter based on the part's
130
     * defined charset.
131
     * 
132
     * @param \ZBateson\MailMimeParser\MimePart $part
133
     * @param resource $handle
134
     */
135
    private function attachCharsetFilterToStream(MimePart $part, $handle)
136
    {
137
        $contentType = strtolower($part->getHeaderValue('Content-Type', 'text/plain'));
138
        if (strpos($contentType, 'text/') === 0) {
139
            stream_filter_append(
140
                $handle,
141
                'mailmimeparser-encode.' . $part->getHeaderParameter('Content-Type', 'charset')
142
            );
143
        }
144
    }
145
146
    /**
147
     * Creates a part stream handle for the start and end position of the
148
     * message stream, and attaches it to the passed MimePart.
149
     * 
150
     * @param MimePart $part
151
     * @param Message $message
152
     * @param int $start
153
     * @param int $end
154
     */
155
    public function attachPartStreamHandle(MimePart $part, Message $message, $start, $end)
156
    {
157
        $id = $message->getObjectId();
158
        if (empty($this->registeredHandles[$id])) {
159
            return null;
160
        }
161
        $handle = fopen('mmp-mime-message://' . $id . '?start=' .
162
            $start . '&end=' . $end, 'r');
163
        
164
        $this->attachEncodingFilterToStream($part, $handle);
165
        $this->attachCharsetFilterToStream($part, $handle);
166
        $part->attachContentResourceHandle($handle);
167
    }
168
}
169