1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Http\Message\Stream; |
4
|
|
|
|
5
|
|
|
use Psr\Http\Message\StreamInterface; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* A buffered stream allow to buffer over an existing. |
9
|
|
|
* |
10
|
|
|
* You should use this decorator when you want to seek over a not seekable stream. |
11
|
|
|
* This stream is however read-only. |
12
|
|
|
*/ |
13
|
|
|
class BufferedStream implements StreamInterface |
14
|
|
|
{ |
15
|
|
|
/** @var resource The buffered resource used to seek previous data */ |
16
|
|
|
private $resource; |
17
|
|
|
|
18
|
|
|
/** @var integer size of the stream if available */ |
19
|
|
|
private $size; |
20
|
|
|
|
21
|
|
|
/** @var StreamInterface The underlying stream decorated by this class */ |
22
|
|
|
private $stream; |
23
|
|
|
|
24
|
|
|
/** @var int How many bytes were written */ |
25
|
|
|
private $writed = 0; |
26
|
|
|
|
27
|
13 |
|
public function __construct(StreamInterface $stream, $useFileBuffer = true, $memoryBuffer = 2097152) |
28
|
|
|
{ |
29
|
13 |
|
$this->stream = $stream; |
30
|
13 |
|
$this->size = $stream->getSize(); |
31
|
|
|
|
32
|
13 |
|
if ($useFileBuffer) { |
33
|
13 |
|
$this->resource = fopen('php://temp/maxmemory:'.$memoryBuffer, 'rw+'); |
34
|
13 |
|
} else { |
35
|
|
|
$this->resource = fopen('php://memory', 'rw+'); |
36
|
|
|
} |
37
|
|
|
|
38
|
13 |
|
if (false === $this->resource) { |
39
|
|
|
throw new \RuntimeException('Cannot create a resource over temp or memory implementation'); |
40
|
|
|
} |
41
|
13 |
|
} |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* {@inheritdoc} |
45
|
|
|
*/ |
46
|
1 |
|
public function __toString() |
47
|
|
|
{ |
48
|
|
|
try { |
49
|
1 |
|
$this->rewind(); |
50
|
|
|
|
51
|
1 |
|
return $this->getContents(); |
52
|
|
|
} catch (\Throwable $throwable) { |
|
|
|
|
53
|
|
|
return ''; |
54
|
|
|
} catch (\Exception $exception) { |
55
|
|
|
return ''; |
56
|
|
|
} |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* {@inheritdoc} |
61
|
|
|
*/ |
62
|
|
|
public function close() |
63
|
|
|
{ |
64
|
|
|
if (null === $this->resource) { |
65
|
|
|
throw new \RuntimeException('Cannot close on a detached stream'); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
$this->stream->close(); |
69
|
|
|
fclose($this->resource); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* {@inheritdoc} |
74
|
|
|
*/ |
75
|
1 |
|
public function detach() |
76
|
|
|
{ |
77
|
1 |
|
if (null === $this->resource) { |
78
|
1 |
|
return null; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
// Force reading the remaining data of the stream |
82
|
1 |
|
$this->getContents(); |
83
|
|
|
|
84
|
1 |
|
$resource = $this->resource; |
85
|
1 |
|
$this->stream = null; |
86
|
1 |
|
$this->resource = null; |
87
|
|
|
|
88
|
1 |
|
return $resource; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* {@inheritdoc} |
93
|
|
|
*/ |
94
|
1 |
|
public function getSize() |
95
|
|
|
{ |
96
|
1 |
|
if (null === $this->size && $this->stream->eof()) { |
97
|
1 |
|
if (null === $this->resource) { |
98
|
|
|
return null; |
99
|
|
|
} |
100
|
|
|
|
101
|
1 |
|
return $this->writed; |
102
|
|
|
} |
103
|
|
|
|
104
|
1 |
|
return $this->size; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* {@inheritdoc} |
109
|
|
|
*/ |
110
|
3 |
|
public function tell() |
111
|
|
|
{ |
112
|
3 |
|
if (null === $this->resource) { |
113
|
|
|
throw new \RuntimeException('Cannot tell on a detached stream'); |
114
|
|
|
} |
115
|
|
|
|
116
|
3 |
|
return ftell($this->resource); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* {@inheritdoc} |
121
|
|
|
*/ |
122
|
2 |
|
public function eof() |
123
|
|
|
{ |
124
|
2 |
|
if (null === $this->resource) { |
125
|
|
|
throw new \RuntimeException('Cannot call eof on a detached stream'); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
// We are at the end only when both our resource and underlying stream are at eof |
129
|
2 |
|
return $this->stream->eof() && (ftell($this->resource) === $this->writed); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* {@inheritdoc} |
134
|
|
|
*/ |
135
|
1 |
|
public function isSeekable() |
136
|
|
|
{ |
137
|
1 |
|
if (null === $this->resource) { |
138
|
|
|
return false; |
139
|
|
|
} |
140
|
|
|
|
141
|
1 |
|
return true; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* {@inheritdoc} |
146
|
|
|
*/ |
147
|
2 |
|
public function seek($offset, $whence = SEEK_SET) |
148
|
|
|
{ |
149
|
2 |
|
if (null === $this->resource) { |
150
|
|
|
throw new \RuntimeException('Cannot seek on a detached stream'); |
151
|
|
|
} |
152
|
|
|
|
153
|
2 |
|
fseek($this->resource, $offset, $whence); |
154
|
2 |
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* {@inheritdoc} |
158
|
|
|
*/ |
159
|
3 |
|
public function rewind() |
160
|
|
|
{ |
161
|
3 |
|
if (null === $this->resource) { |
162
|
|
|
throw new \RuntimeException('Cannot rewind on a detached stream'); |
163
|
|
|
} |
164
|
|
|
|
165
|
3 |
|
rewind($this->resource); |
166
|
3 |
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* {@inheritdoc} |
170
|
|
|
*/ |
171
|
1 |
|
public function isWritable() |
172
|
|
|
{ |
173
|
1 |
|
return false; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* {@inheritdoc} |
178
|
|
|
*/ |
179
|
1 |
|
public function write($string) |
180
|
|
|
{ |
181
|
1 |
|
throw new \RuntimeException('Cannot write on this stream'); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* {@inheritdoc} |
186
|
|
|
*/ |
187
|
1 |
|
public function isReadable() |
188
|
|
|
{ |
189
|
1 |
|
return (null !== $this->resource); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* {@inheritdoc} |
194
|
|
|
*/ |
195
|
8 |
|
public function read($length) |
196
|
|
|
{ |
197
|
8 |
|
if (null === $this->resource) { |
198
|
|
|
throw new \RuntimeException('Cannot read on a detached stream'); |
199
|
|
|
} |
200
|
|
|
|
201
|
8 |
|
$read = ""; |
202
|
|
|
|
203
|
|
|
// First read from the resource |
204
|
8 |
|
if (ftell($this->resource) !== $this->writed) { |
205
|
1 |
|
$read = fread($this->resource, $length); |
206
|
1 |
|
} |
207
|
|
|
|
208
|
8 |
|
$bytesRead = strlen($read); |
209
|
|
|
|
210
|
8 |
|
if ($bytesRead < $length) { |
211
|
8 |
|
$streamRead = $this->stream->read($length - $bytesRead); |
212
|
|
|
|
213
|
|
|
// Write on the underlying stream what we read |
214
|
8 |
|
$this->writed += fwrite($this->resource, $streamRead); |
215
|
8 |
|
$read .= $streamRead; |
216
|
8 |
|
} |
217
|
|
|
|
218
|
8 |
|
return $read; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
/** |
222
|
|
|
* {@inheritdoc} |
223
|
|
|
*/ |
224
|
8 |
|
public function getContents() |
225
|
|
|
{ |
226
|
8 |
|
if (null === $this->resource) { |
227
|
|
|
throw new \RuntimeException('Cannot read on a detached stream'); |
228
|
|
|
} |
229
|
|
|
|
230
|
8 |
|
$read = ""; |
231
|
|
|
|
232
|
8 |
|
while (!$this->stream->eof()) { |
233
|
7 |
|
$read .= $this->read(8192); |
234
|
7 |
|
} |
235
|
|
|
|
236
|
8 |
|
return $read; |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* {@inheritdoc} |
241
|
|
|
*/ |
242
|
1 |
|
public function getMetadata($key = null) |
243
|
|
|
{ |
244
|
1 |
|
if (null === $this->resource) { |
245
|
|
|
if (null === $key) { |
246
|
|
|
return []; |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
return null; |
250
|
|
|
} |
251
|
|
|
|
252
|
1 |
|
$metadata = stream_get_meta_data($this->resource); |
253
|
|
|
|
254
|
1 |
|
if (null === $key) { |
255
|
1 |
|
return $metadata; |
256
|
|
|
} |
257
|
|
|
|
258
|
1 |
|
if (!array_key_exists($key, $metadata)) { |
259
|
1 |
|
return null; |
260
|
|
|
} |
261
|
|
|
|
262
|
1 |
|
return $metadata[$key]; |
263
|
|
|
} |
264
|
|
|
} |
265
|
|
|
|
Scrutinizer analyzes your
composer.json
/composer.lock
file if available to determine the classes, and functions that are defined by your dependencies.It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.