Passed
Push — master ( 42b16f...37358f )
by Zlatin
01:56
created

Stream::__toString()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 3
nop 0
dl 0
loc 7
ccs 0
cts 5
cp 0
crap 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace DevOp\Core\Http;
3
4
use Psr\Http\Message\StreamInterface;
5
6
class Stream implements StreamInterface
7
{
8
9
    /**
10
     * @var array
11
     */
12
    private static $modes = [
13
        'readable' => [
14
            'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
15
            'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
16
            'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
17
            'x+t' => true, 'c+t' => true, 'a+' => true
18
        ],
19
        'writable' => [
20
            'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
21
            'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true,
22
            'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
23
            'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
24
        ],
25
    ];
26
27
    /**
28
     * @var resource
29
     */
30
    private $stream;
31
32
    /**
33
     * @param StreamInterface $handle
34
     * @throws \InvalidArgumentException
35
     */
36 16
    public function __construct($handle)
37
    {
38 16
        $this->stream = $handle;
0 ignored issues
show
Documentation Bug introduced by
It seems like $handle of type Psr\Http\Message\StreamInterface is incompatible with the declared type resource of property $stream.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
39 16
    }
40
41
    /**
42
     * @return string
43
     */
44
    public function __toString()
45
    {
46
        try {
47
            $this->rewind();
48
            return $this->getContents();
49
        } catch (\Exception $e) {
50
            return '';
51
        }
52
    }
53
54
    /**
55
     * @return boolean
56
     */
57
    public function close()
58
    {
59
        if (!$this->stream) {
60
            return;
61
        }
62
63
        $handle = $this->detach();
64
        fclose($handle);
65
    }
66
67
    /**
68
     * @return resource
69
     */
70
    public function detach()
71
    {
72
        $handle = $this->stream;
73
        $this->stream = null;
74
75
        return $handle;
76
    }
77
78
    /**
79
     * @return boolean
80
     */
81
    public function eof()
82
    {
83
        if (!$this->stream) {
84
            return true;
85
        }
86
87
        return feof($this->stream);
88
    }
89
90
    /**
91
     * @return string
92
     * @throws \RuntimeException
93
     */
94
    public function getContents()
95
    {
96
        if (!$this->stream) {
97
            throw new \RuntimeException('Empty stream');
98
        }
99
100
        if ($this->isReadable()) {
101
            throw new \RuntimeException('Unable to read stream');
102
        }
103
104
        return (string) stream_get_contents($this->stream);
105
    }
106
107
    /**
108
     * @param string|null $key
109
     * @return mixed
110
     */
111 6
    public function getMetadata($key = null)
112
    {
113 6
        $metadata = stream_get_meta_data($this->stream);
114
115 6
        if (null === $key) {
116
            return $metadata;
117
        }
118
119 6
        if (isset($metadata[$key])) {
120 6
            return $metadata[$key];
121
        }
122
123
        return null;
124
    }
125
126
    /**
127
     * @return int
128
     */
129
    public function getSize()
130
    {
131
        $fstats = fstat($this->stream);
132
        if (isset($fstats['size'])) {
133
            return $fstats['size'];
134
        }
135
136
        return null;
137
    }
138
139
    /**
140
     * @return boolean
141
     */
142 2
    public function isReadable()
143
    {
144 2
        if (!$this->stream) {
145
            return false;
146
        }
147
148 2
        $mode = $this->getMetadata('mode');
149 2
        return isset(self::$modes['readable'][$mode]);
150
    }
151
152
    /**
153
     * @return boolean
154
     */
155 2
    public function isSeekable()
156
    {
157 2
        if (!$this->stream) {
158
            return false;
159
        }
160
161 2
        if ($this->getMetadata('seekable')) {
162 2
            return true;
163
        }
164
165
        return false;
166
    }
167
168
    /**
169
     * @return boolean
170
     */
171 2
    public function isWritable()
172
    {
173 2
        if (!$this->stream) {
174
            return false;
175
        }
176
177 2
        $mode = $this->getMetadata('mode');
178 2
        return isset(self::$modes['writable'][$mode]);
179
    }
180
181
    /**
182
     * @param int $length
183
     * @return string
184
     * @throws \RuntimeException
185
     */
186
    public function read($length)
187
    {
188
        if (!$this->isReadable()) {
189
            throw new \RuntimeException('Stream is not readable');
190
        }
191
192
        return fread($this->stream, $length);
193
    }
194
195
    /**
196
     * @throws \RuntimeException
197
     */
198
    public function rewind()
199
    {
200
        if ($this->isSeekable()) {
201
            throw new \RuntimeException('Stream is not seekable');
202
        }
203
204
        $this->seek(0);
205
    }
206
207
    /**
208
     * @param int $offset
209
     * @param int $whence
210
     * @throws \RuntimeException
211
     */
212
    public function seek($offset, $whence = SEEK_SET)
213
    {
214
        if (!$this->isSeekable()) {
215
            throw new \RuntimeException('Stream is not seekable');
216
        }
217
218
        return fseek($this->stream, $offset, $whence);
219
    }
220
221
    /**
222
     * @return int
223
     * @throws \RuntimeException
224
     */
225
    public function tell()
226
    {
227
        if (!$this->stream) {
228
            throw new \RuntimeException('Invalid stream handle');
229
        }
230
231
        return ftell($this->stream);
232
    }
233
234
    /**
235
     * @param string $string
236
     * @return int
237
     * @throws \RuntimeException
238
     */
239
    public function write($string)
240
    {
241
        if (!$this->isWritable()) {
242
            throw new \RuntimeException('Stream is not writable');
243
        }
244
245
        return fwrite($this->stream, $string);
246
    }
247
}
248