Completed
Push — master ( 04ea00...5840b0 )
by Frederik
02:29
created

QuotedPrintableStream   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 212
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 83.87%

Importance

Changes 0
Metric Value
wmc 21
lcom 1
cbo 2
dl 0
loc 212
ccs 52
cts 62
cp 0.8387
rs 10
c 0
b 0
f 0

19 Methods

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