Completed
Pull Request — master (#12)
by Frederik
12:11
created

Base64EncodedStream::eof()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

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