Test Failed
Pull Request — master (#171)
by Zaahid
04:32
created

MessagePart::notify()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 4
c 1
b 0
f 0
nc 4
nop 0
dl 0
loc 7
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\MailMimeParser;
10
use GuzzleHttp\Psr7\StreamWrapper;
11
use GuzzleHttp\Psr7\Utils;
12
use Psr\Http\Message\StreamInterface;
13
use SplObjectStorage;
14
use SplObserver;
15
16
/**
17
 * Most basic representation of a single part of an email.
18
 *
19
 * @author Zaahid Bateson
20
 */
21
abstract class MessagePart implements IMessagePart
22
{
23
    /**
24
     * @var IMimePart parent part
25
     */
26
    protected $parent;
27
28
    /**
29
     * @var PartStreamContainer holds 'stream' and 'content stream'.
30
     */
31
    protected $partStreamContainer;
32
33
    /**
34
     * @var string can be used to set an override for content's charset in cases
35
     *      where a user knows the charset on the content is not what it claims
36
     *      to be.
37
     */
38
    protected $charsetOverride;
39
40
    /**
41
     * @var bool set to true when a user attaches a stream manually, it's
42
     *      assumed to already be decoded or to have relevant transfer encoding
43
     *      decorators attached already.
44
     */
45
    protected $ignoreTransferEncoding;
46
47
    /**
48
     * @var SplObjectStorage attached observers that need to be notified of
49
     *      modifications to this part.
50
     */
51
    protected $observers;
52
53
    public function __construct(PartStreamContainer $streamContainer, IMimePart $parent = null)
54
    {
55
        $this->partStreamContainer = $streamContainer;
56
        $this->parent = $parent;
57
        $this->observers = new SplObjectStorage();
58
    }
59
60
    public function attach(SplObserver $observer)
61
    {
62
        $this->observers->attach($observer);
63
    }
64
65
    public function detach(SplObserver $observer)
66
    {
67
        $this->observers->detach($observer);
68
    }
69
70
    public function notify()
71
    {
72
        foreach ($this->observers as $observer) {
73
            $observer->update($this);
74
        }
75
        if ($this->parent !== null) {
76
            $this->parent->notify();
77
        }
78
    }
79
80
    public function getParent()
81
    {
82
        return $this->parent;
83
    }
84
85
    public function hasContent()
86
    {
87
        return $this->partStreamContainer->hasContent();
88
    }
89
90
    public function getFilename()
91
    {
92
        return null;
93
    }
94
95
    public function setCharsetOverride($charsetOverride, $onlyIfNoCharset = false)
96
    {
97
        if (!$onlyIfNoCharset || $this->getCharset() === null) {
98
            $this->charsetOverride = $charsetOverride;
99
        }
100
    }
101
102
    public function getContentStream($charset = MailMimeParser::DEFAULT_CHARSET)
103
    {
104
        if ($this->hasContent()) {
105
            $tr = ($this->ignoreTransferEncoding) ? '' : $this->getContentTransferEncoding();
106
            $ch = ($this->charsetOverride !== null) ? $this->charsetOverride : $this->getCharset();
107
            return $this->partStreamContainer->getContentStream(
108
                $tr,
109
                $ch,
110
                $charset
111
            );
112
        }
113
        return null;
114
    }
115
116
    public function getBinaryContentStream()
117
    {
118
        if ($this->hasContent()) {
119
            $tr = ($this->ignoreTransferEncoding) ? '' : $this->getContentTransferEncoding();
120
            return $this->partStreamContainer->getBinaryContentStream($tr);
121
        }
122
        return null;
123
    }
124
125
    public function getBinaryContentResourceHandle()
126
    {
127
        $stream = $this->getBinaryContentStream();
128
        if ($stream !== null) {
129
            return StreamWrapper::getResource($stream);
130
        }
131
        return null;
132
    }
133
134
    public function saveContent($filenameResourceOrStream)
135
    {
136
        $resourceOrStream = $filenameResourceOrStream;
137
        if (is_string($filenameResourceOrStream)) {
138
            $resourceOrStream = fopen($filenameResourceOrStream, 'w+');
139
        }
140
141
        $stream = Utils::streamFor($resourceOrStream);
142
        Utils::copyToStream($this->getBinaryContentStream(), $stream);
0 ignored issues
show
Bug introduced by
It seems like $this->getBinaryContentStream() can also be of type null; however, parameter $source of GuzzleHttp\Psr7\Utils::copyToStream() does only seem to accept Psr\Http\Message\StreamInterface, 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

142
        Utils::copyToStream(/** @scrutinizer ignore-type */ $this->getBinaryContentStream(), $stream);
Loading history...
143
144
        if (!is_string($filenameResourceOrStream)
145
            && !($filenameResourceOrStream instanceof StreamInterface)) {
146
            // only detach if it wasn't a string or StreamInterface, so the
147
            // fopen call can be properly closed if it was
148
            $stream->detach();
149
        }
150
    }
151
152
    public function getContent($charset = MailMimeParser::DEFAULT_CHARSET)
153
    {
154
        $stream = $this->getContentStream($charset);
155
        if ($stream !== null) {
156
            return $stream->getContents();
157
        }
158
        return null;
159
    }
160
161
    public function attachContentStream(StreamInterface $stream, $streamCharset = MailMimeParser::DEFAULT_CHARSET)
162
    {
163
        $ch = ($this->charsetOverride !== null) ? $this->charsetOverride : $this->getCharset();
164
        if ($ch !== null && $streamCharset !== $ch) {
165
            $this->charsetOverride = $streamCharset;
166
        }
167
        $this->ignoreTransferEncoding = true;
168
        $this->partStreamContainer->setContentStream($stream);
169
        $this->notify();
170
    }
171
172
    public function detachContentStream()
173
    {
174
        $this->partStreamContainer->setContentStream(null);
175
        $this->notify();
176
    }
177
178
    public function setContent($resource, $charset = MailMimeParser::DEFAULT_CHARSET)
179
    {
180
        $stream = Utils::streamFor($resource);
181
        $this->attachContentStream($stream, $charset);
182
        // this->notify() called in attachContentStream
183
    }
184
185
    public function getResourceHandle()
186
    {
187
        return StreamWrapper::getResource($this->getStream());
188
    }
189
190
    public function getStream()
191
    {
192
        return $this->partStreamContainer->getStream();
193
    }
194
195
    public function save($filenameResourceOrStream, $filemode = 'w+')
196
    {
197
        $resourceOrStream = $filenameResourceOrStream;
198
        if (is_string($filenameResourceOrStream)) {
199
            $resourceOrStream = fopen($filenameResourceOrStream, $filemode);
200
        }
201
202
        $partStream = $this->getStream();
203
        $partStream->rewind();
204
        $stream = Utils::streamFor($resourceOrStream);
205
        Utils::copyToStream($partStream, $stream);
206
207
        if (!is_string($filenameResourceOrStream)
208
            && !($filenameResourceOrStream instanceof StreamInterface)) {
209
            // only detach if it wasn't a string or StreamInterface, so the
210
            // fopen call can be properly closed if it was
211
            $stream->detach();
212
        }
213
    }
214
215
    public function __toString()
216
    {
217
        return $this->getStream()->getContents();
218
    }
219
}
220