Passed
Push — master ( df14ff...ea468d )
by Rougin
01:40
created

Stream::rewind()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Zapheus\Bridge\Psr;
4
5
/*
6
 * This file is part of the Symfony package.
7
 *
8
 * (c) Fabien Potencier <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
use Psr\Http\Message\StreamInterface;
15
16
/**
17
 * Stream
18
 *
19
 * @package Zapheus
20
 * @author  Kévin Dunglas <[email protected]>
21
 * @author  Jérémy 'Jejem' Desvages <[email protected]>
22
 * @author  Rougin Royce Gutib <[email protected]>
23
 */
24
class Stream implements StreamInterface
25
{
26
    /**
27
     * @var array|null
28
     */
29
    protected $meta = null;
30
31
    /**
32
     * @var array
33
     */
34
    protected $readable = array('r', 'r+', 'w+', 'a+', 'x+', 'c+', 'w+b');
35
36
    /**
37
     * @var integer|null
38
     */
39
    protected $size = null;
40
41
    /**
42
     * @var resource|null
43
     */
44
    protected $stream = null;
45
46
    /**
47
     * @var array
48
     */
49
    protected $writable = array('r+', 'w', 'w+', 'a', 'a+', 'x', 'x+', 'c', 'c+', 'w+b');
50
51
    /**
52
     * Initializes the stream instance.
53
     *
54
     * @param resource|null $stream
55
     */
56 144
    public function __construct($stream = null)
57
    {
58 144
        $this->stream = $stream;
59 144
    }
60
61
    /**
62
     * Reads all data from the stream into a string, from the beginning to end.
63
     *
64
     * @return string
65
     */
66 6
    public function __toString()
67
    {
68 6
        $this->rewind();
69
70 6
        return $this->getContents();
71
    }
72
73
    /**
74
     * Closes the stream and any underlying resources.
75
     *
76
     * @return void
77
     */
78 6
    public function close()
79
    {
80 6
        is_null($this->stream) ?: fclose($this->stream);
81
82 6
        $this->detach();
83 6
    }
84
85
    /**
86
     * Separates any underlying resources from the stream.
87
     *
88
     * @return resource|null
89
     */
90 12
    public function detach()
91
    {
92 12
        $stream = $this->stream;
93
94 12
        $this->meta = null;
95
96 12
        $this->size = null;
97
98 12
        $this->stream = null;
99
100 12
        return $stream;
101
    }
102
103
    /**
104
     * Returns true if the stream is at the end of the stream.
105
     *
106
     * @return boolean
107
     */
108 3
    public function eof()
109
    {
110 3
        return is_null($this->stream) ?: feof($this->stream);
111
    }
112
113
    /**
114
     * Returns the remaining contents in a string
115
     *
116
     * @return string
117
     *
118
     * @throws \RuntimeException
119
     */
120 12
    public function getContents()
121
    {
122 12
        if (is_null($this->stream) || ! $this->isReadable()) {
123 3
            $message = 'Could not get contents of stream';
124
125 3
            throw new \RuntimeException($message);
126
        }
127
128 9
        return stream_get_contents($this->stream);
129
    }
130
131
    /**
132
     * Returns stream metadata as an associative array or retrieve a specific key.
133
     *
134
     * @param  string $key
135
     * @return array|mixed|null
136
     */
137 39
    public function getMetadata($key = null)
138
    {
139 39
        isset($this->stream) && $this->meta = stream_get_meta_data($this->stream);
140
141 39
        $metadata = isset($this->meta[$key]) ? $this->meta[$key] : null;
142
143 39
        return is_null($key) ? $this->meta : $metadata;
144
    }
145
146
    /**
147
     * Returns the size of the stream if known.
148
     *
149
     * @return integer|null
150
     */
151 3
    public function getSize()
152
    {
153 3
        if (is_null($this->size) === true) {
154 3
            $stats = fstat($this->stream);
155
156 3
            $this->size = $stats['size'];
157 3
        }
158
159 3
        return $this->size;
160
    }
161
162
    /**
163
     * Returns whether or not the stream is readable.
164
     *
165
     * @return boolean
166
     */
167 21
    public function isReadable()
168
    {
169 21
        $mode = $this->getMetadata('mode');
170
171 21
        return in_array($mode, $this->readable);
172
    }
173
174
    /**
175
     * Returns whether or not the stream is seekable.
176
     *
177
     * @return boolean
178
     */
179 18
    public function isSeekable()
180
    {
181 18
        return $this->getMetadata('seekable');
182
    }
183
184
    /**
185
     * Returns whether or not the stream is writable.
186
     *
187
     * @return boolean
188
     */
189 9
    public function isWritable()
190
    {
191 9
        $mode = $this->getMetadata('mode');
192
193 9
        return in_array($mode, $this->writable);
194
    }
195
196
    /**
197
     * Read data from the stream.
198
     *
199
     * @param  integer $length
200
     * @return string
201
     *
202
     * @throws \RuntimeException
203
     */
204 6
    public function read($length)
205
    {
206 6
        $data = fread($this->stream, $length);
207
208 6
        if (! $this->isReadable() || $data === false) {
209 3
            $message = 'Could not read from stream';
210
211 3
            throw new \RuntimeException($message);
212
        }
213
214 3
        return $data;
215
    }
216
217
    /**
218
     * Seek to the beginning of the stream.
219
     *
220
     * @throws \RuntimeException
221
     */
222 6
    public function rewind()
223
    {
224 6
        $this->seek(0);
225 6
    }
226
227
    /**
228
     * Seek to a position in the stream.
229
     *
230
     * @param integer $offset
231
     * @param integer $whence
232
     *
233
     * @throws \RuntimeException
234
     */
235 15
    public function seek($offset, $whence = SEEK_SET)
236
    {
237 15
        $seek = -1;
238
239 15
        $this->stream && $seek = fseek($this->stream, $offset, $whence);
240
241 15
        if (! $this->isSeekable() || $seek === -1) {
242 3
            $message = 'Could not seek in stream';
243
244 3
            throw new \RuntimeException($message);
245
        }
246 12
    }
247
248
    /**
249
     * Returns the current position of the file read/write pointer.
250
     *
251
     * @return integer
252
     *
253
     * @throws \RuntimeException
254
     */
255 6
    public function tell()
256
    {
257 6
        $position = false;
258
259 6
        $this->stream && $position = ftell($this->stream);
260
261 6
        if (is_null($this->stream) || $position === false) {
262 3
            $message = 'Could not get position of pointer in stream';
263
264 3
            throw new \RuntimeException($message);
265
        }
266
267 3
        return $position;
268
    }
269
270
    /**
271
     * Write data to the stream.
272
     *
273
     * @param  string $string
274
     * @return integer
275
     *
276
     * @throws \RuntimeException
277
     */
278 6
    public function write($string)
279
    {
280 6
        if (! $this->isWritable()) {
281 3
            $message = 'Stream is not writable';
282
283 3
            throw new \RuntimeException($message);
284
        }
285
286 3
        $this->size = null;
287
288 3
        return fwrite($this->stream, $string);
289
    }
290
}
291