Completed
Pull Request — master (#64)
by Frederik
03:38 queued 01:09
created

QuotedPrintableStream::fromString()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2.004

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 9
cts 10
cp 0.9
rs 9.7333
c 0
b 0
f 0
cc 2
nc 2
nop 3
crap 2.004
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Stream;
5
6
use Genkgo\Mail\StreamInterface;
7
8
final class QuotedPrintableStream implements StreamInterface
9
{
10
    /**
11
     * @var StreamInterface
12
     */
13
    private $decoratedStream;
14
15
    /**
16
     * @var int
17
     */
18
    private $lineLength;
19
20
    /**
21
     * @var resource
22
     */
23
    private $filter;
24
25
    /**
26
     * @var string
27
     */
28
    private $lineBreak;
29
30
    /**
31
     * @param resource $resource
32
     * @param int $lineLength
33
     * @param string $lineBreak
34
     */
35 24
    public function __construct($resource, int $lineLength = 75, string $lineBreak = "\r\n")
36
    {
37 24
        $this->decoratedStream = new ResourceStream($resource);
38 24
        $this->lineLength = $lineLength;
39 24
        $this->lineBreak = $lineBreak;
40
41 24
        $this->applyFilter();
42 24
    }
43
44
    /**
45
     * @param string $string
46
     * @param int $lineLength
47
     * @param string $lineBreak
48
     * @return QuotedPrintableStream
49
     */
50 23
    public static function fromString(string $string, int $lineLength = 75, string $lineBreak = "\r\n"): QuotedPrintableStream
51
    {
52 23
        $string = \str_replace(
53 23
            ["\r\n", "\r", "\n", "\t\r\n", " \r\n"],
54 23
            ["\n", "\n", "\r\n", "\r\n", "\r\n"],
55 23
            $string
56
        );
57
58 23
        $resource = \fopen('php://memory', 'r+');
59 23
        if ($resource === false) {
60
            throw new \UnexpectedValueException('Cannot open php://memory for writing');
61
        }
62
63 23
        \fwrite($resource, $string);
64 23
        return new self($resource, $lineLength, $lineBreak);
65
    }
66
    
67 24
    private function applyFilter(): void
68
    {
69 24
        $filter = \stream_filter_prepend(
70 24
            $this->decoratedStream->detach(),
71 24
            'convert.quoted-printable-encode',
72 24
            STREAM_FILTER_READ,
73
            [
74 24
                'line-length' => $this->lineLength,
75 24
                'line-break-chars' => $this->lineBreak
76
            ]
77
        );
78
79 24
        if ($filter === false) {
80
            throw new \UnexpectedValueException('Cannot append filter to stream');
81
        }
82
83 24
        $this->filter = $filter;
84 24
    }
85
    
86 15
    private function removeFilter(): void
87
    {
88 15
        if ($this->filter !== null) {
89 15
            \stream_filter_remove($this->filter);
90
        }
91 15
    }
92
93
    /**
94
     * @return string
95
     */
96 14
    public function __toString(): string
97
    {
98 14
        $this->rewind();
99 14
        return $this->decoratedStream->__toString();
100
    }
101
    
102
    public function close(): void
103
    {
104
        $this->decoratedStream->close();
105
    }
106
107
    /**
108
     * @return mixed
109
     */
110
    public function detach()
111
    {
112
        return $this->decoratedStream->detach();
113
    }
114
115
    /**
116
     * @return int|null
117
     */
118 9
    public function getSize(): ?int
119
    {
120 9
        return null;
121
    }
122
123
    /**
124
     * @return int
125
     * @throws \RuntimeException
126
     */
127 1
    public function tell(): int
128
    {
129 1
        return $this->decoratedStream->tell();
130
    }
131
132
    /**
133
     * @return bool
134
     */
135 4
    public function eof(): bool
136
    {
137 4
        return $this->decoratedStream->eof();
138
    }
139
140
    /**
141
     * @return bool
142
     */
143
    public function isSeekable(): bool
144
    {
145
        return false;
146
    }
147
148
    /**
149
     * @param int $offset
150
     * @param int $whence
151
     * @return int
152
     */
153 1
    public function seek(int $offset, int $whence = SEEK_SET): int
154
    {
155 1
        return -1;
156
    }
157
158
    /**
159
     * @return bool
160
     */
161 15
    public function rewind(): bool
162
    {
163 15
        $this->removeFilter();
164 15
        if (!$this->decoratedStream->rewind()) {
165
            return false;
166
        }
167
168 15
        $this->applyFilter();
169 15
        return true;
170
    }
171
172
    /**
173
     * @return bool
174
     */
175 1
    public function isWritable(): bool
176
    {
177 1
        return false;
178
    }
179
180
    /**
181
     * @param string $string
182
     * @return int
183
     */
184 1
    public function write($string): int
185
    {
186 1
        throw new \RuntimeException('Cannot write to stream');
187
    }
188
189
    /**
190
     * @return bool
191
     */
192
    public function isReadable(): bool
193
    {
194
        return true;
195
    }
196
197
    /**
198
     * @param int $length
199
     * @return string
200
     */
201 5
    public function read(int $length): string
202
    {
203 5
        return $this->decoratedStream->read($length);
204
    }
205
206
    /**
207
     * @return string
208
     */
209 2
    public function getContents(): string
210
    {
211 2
        return $this->decoratedStream->getContents();
212
    }
213
214
    /**
215
     * @param array<int, string> $keys
216
     * @return array<string, mixed>
0 ignored issues
show
Documentation introduced by
The doc-type array<string, could not be parsed: Expected ">" at position 5, but found "end of type". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
217
     */
218 13
    public function getMetadata(array $keys = []): array
219
    {
220 13
        return $this->decoratedStream->getMetadata();
221
    }
222
}
223