ConcatenatedStream::detach()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Genkgo\Mail\Stream;
5
6
use Genkgo\Mail\StreamInterface;
7
8
final class ConcatenatedStream implements StreamInterface
9
{
10
    /**
11
     * @var array|StreamInterface[]
12
     */
13
    private $streams = [];
14
15
    /**
16
     * @var int
17
     */
18
    private $position = 0;
19
20
    /**
21
     * @var int
22
     */
23
    private $index = 0;
24
25
    /**
26
     * @param iterable<StreamInterface> $streams
0 ignored issues
show
Documentation introduced by
The doc-type iterable<StreamInterface> could not be parsed: Expected "|" or "end of type", but got "<" at position 8. (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...
27
     */
28 120
    public function __construct(iterable $streams)
29
    {
30 120
        foreach ($streams as $stream) {
31 120
            $this->addStream($stream);
32
        }
33 120
    }
34
35
    /**
36
     * @param StreamInterface $stream
37
     */
38 120
    private function addStream(StreamInterface $stream): void
39
    {
40 120
        $this->streams[] = $stream;
41 120
    }
42
43
    /**
44
     * @return string
45
     */
46 92
    public function __toString(): string
47
    {
48 92
        $result = [];
49
50 92
        foreach ($this->streams as $stream) {
51 92
            $result[] = $stream->__toString();
52
        }
53
54 92
        return \implode('', $result);
55
    }
56
    
57
    public function close(): void
58
    {
59
        foreach ($this->streams as $stream) {
60
            $stream->close();
61
        }
62
    }
63
64
    /**
65
     * @return mixed
66
     */
67
    public function detach()
68
    {
69
        return null;
70
    }
71
72
    /**
73
     * @return int|null
74
     */
75 1
    public function getSize(): ?int
76
    {
77 1
        $size = 0;
78 1
        foreach ($this->streams as $stream) {
79 1
            $streamSize = $stream->getSize();
80
81 1
            if ($streamSize === null) {
82
                return null;
83
            }
84
85 1
            $size += $streamSize;
86
        }
87
88 1
        return $size;
89
    }
90
91
    /**
92
     * @return int
93
     * @throws \RuntimeException
94
     */
95 1
    public function tell(): int
96
    {
97 1
        return $this->position;
98
    }
99
100
    /**
101
     * @return bool
102
     */
103 22
    public function eof(): bool
104
    {
105 22
        if (!isset($this->streams[$this->index])) {
106 22
            return true;
107
        }
108
109 22
        if (!$this->streams[$this->index]->eof()) {
110 22
            return false;
111
        }
112
113
        return isset($this->streams[$this->index + 1]);
114
    }
115
116
    /**
117
     * @return bool
118
     */
119
    public function isSeekable(): bool
120
    {
121
        foreach ($this->streams as $stream) {
122
            if ($stream->isSeekable() === false) {
123
                return false;
124
            }
125
        }
126
127
        return true;
128
    }
129
130
    /**
131
     * @param int $offset
132
     * @param int $whence
133
     * @return int
134
     */
135 1
    public function seek(int $offset, int $whence = SEEK_SET): int
136
    {
137 1
        $seek = 0;
138 1
        while (isset($this->streams[$this->index]) && $offset > $seek) {
139 1
            $streamSize = $this->streams[$this->index]->getSize();
140 1
            if ($this->streams[$this->index]->seek($offset - $seek) === -1) {
141
                return -1;
142
            }
143
144 1
            if ($streamSize > $offset - $seek) {
145 1
                $seek += $offset - $seek;
146
            } else {
147 1
                $seek += $streamSize;
148
            }
149
150 1
            if ($this->streams[$this->index]->eof()) {
151 1
                $this->index++;
152
            }
153
        }
154
155 1
        $this->position = $seek;
156 1
        return 0;
157
    }
158
159
    /**
160
     * @return bool
161
     */
162 22
    public function rewind(): bool
163
    {
164 22
        $this->position = 0;
165 22
        $this->index = 0;
166
167 22
        foreach ($this->streams as $stream) {
168 22
            $stream->rewind();
169
        }
170
171 22
        return true;
172
    }
173
174
    /**
175
     * @return bool
176
     */
177 1
    public function isWritable(): bool
178
    {
179 1
        return false;
180
    }
181
182
    /**
183
     * @param string $string
184
     * @return int
185
     */
186 1
    public function write($string): int
187
    {
188 1
        throw new \RuntimeException('Cannot write to stream');
189
    }
190
191
    /**
192
     * @return bool
193
     */
194
    public function isReadable(): bool
195
    {
196
        return true;
197
    }
198
199
    /**
200
     * @param int $length
201
     * @return string
202
     */
203 24
    public function read(int $length): string
204
    {
205 24
        $result = '';
206 24
        while (\strlen($result) < $length && isset($this->streams[$this->index])) {
207 24
            $result .= $this->streams[$this->index]->read($length);
208 24
            if ($this->streams[$this->index]->eof()) {
209 22
                $this->index++;
210
            }
211
        }
212
213 24
        $this->position += \strlen($result);
214 24
        return $result;
215
    }
216
217
    /**
218
     * @return string
219
     */
220 3
    public function getContents(): string
221
    {
222 3
        $result = '';
223
224 3
        while (isset($this->streams[$this->index])) {
225 3
            $result .= $this->streams[$this->index]->getContents();
226 3
            $this->index++;
227
        }
228
229 3
        return $result;
230
    }
231
232
    /**
233
     * @param array<int, string> $keys
234
     * @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...
235
     */
236
    public function getMetadata(array $keys = []): array
237
    {
238
        return [];
239
    }
240
}
241