ResourceStream::__construct()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3.072

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 2
nop 1
dl 0
loc 7
ccs 4
cts 5
cp 0.8
crap 3.072
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace Wandu\Http\Psr\Stream;
3
4
use InvalidArgumentException;
5
use Psr\Http\Message\StreamInterface;
6
use Wandu\Http\Psr\Stream;
7
use RuntimeException;
8
9
class ResourceStream implements StreamInterface
10
{
11
    /** @var resource */
12
    protected $resource;
13
14
    /**
15
     * @param resource $resource
16
     */
17 27
    public function __construct($resource)
18
    {
19 27
        if (!is_resource($resource) || get_resource_type($resource) !== 'stream') {
20
            throw new InvalidArgumentException("Argument 1 must be of the type stream resource.");
21
        }
22 27
        $this->resource = $resource;
23 27
    }
24
    
25
    /**
26
     * {@inheritdoc}
27
     */
28 15
    public function __toString()
29
    {
30 15
        if (!$this->isReadable()) {
31 2
            return '';
32
        }
33
        try {
34 13
            $this->rewind();
35 13
            return $this->getContents();
36
        } catch (RuntimeException $e) {
37
            return '';
38
        }
39
    }
40
41
    /**
42
     * {@inheritdoc}
43
     */
44 2
    public function close()
45
    {
46 2
        if (!$this->resource) {
47 2
            return;
48
        }
49 2
        $resource = $this->detach();
50 2
        fclose($resource);
51 2
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56 2
    public function detach()
57
    {
58 2
        $resource = $this->resource;
59 2
        $this->resource = null;
60 2
        return $resource;
61
    }
62
63
    /**
64
     * {@inheritdoc}
65
     */
66 4
    public function getSize()
67
    {
68 4
        if (!isset($this->resource)) {
69 2
            return null;
70
        }
71 2
        return fstat($this->resource)['size'];
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77 2
    public function tell()
78
    {
79 2
        $this->isAvailableAndException();
80 2
        $result = ftell($this->resource);
81 2
        if (!is_int($result)) {
82
            throw new RuntimeException('Error occurred during tell operation');
83
        }
84 2
        return $result;
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90 4
    public function eof()
91
    {
92 4
        if (!$this->resource) {
93 2
            return true;
94
        }
95 2
        return feof($this->resource);
96
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101 18
    public function isSeekable()
102
    {
103 18
        if (!$this->resource) {
104 2
            return false;
105
        }
106 16
        return stream_get_meta_data($this->resource)['seekable'];
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112 15
    public function seek($offset, $whence = SEEK_SET)
113
    {
114 15
        $this->isAvailableAndException();
115 15
        if (!$this->isSeekable()) {
116
            throw new RuntimeException('Stream is not seekable');
117
        }
118 15
        if (0 !== fseek($this->resource, $offset, $whence)) {
119 1
            throw new RuntimeException('Error seeking within stream.');
120
        }
121 15
    }
122
123
    /**
124
     * {@inheritdoc}
125
     */
126 13
    public function rewind()
127
    {
128 13
        $this->seek(0);
129 13
    }
130
131
    /**
132
     * {@inheritdoc}
133
     */
134 10
    public function isWritable()
135
    {
136 10
        if (!$this->resource) {
137 2
            return false;
138
        }
139 8
        $mode = stream_get_meta_data($this->resource)['mode'];
140 8
        return strpos($mode, 'w') !== false || strpos($mode, '+') !== false;
141
    }
142
143
    /**
144
     * {@inheritdoc}
145
     */
146 9
    public function write($string)
147
    {
148 9
        $this->isAvailableAndException();
149 7
        if (!$this->isWritable()) {
150 1
            throw new RuntimeException('Stream is not writable.');
151
        }
152 6
        if (false === $result = fwrite($this->resource, $string)) {
153
            throw new RuntimeException('Error writing to stream.');
154
        }
155 6
        return $result;
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161 19
    public function isReadable()
162
    {
163 19
        if (!$this->resource) {
164 2
            return false;
165
        }
166 17
        $mode = stream_get_meta_data($this->resource)['mode'];
167 17
        return strpos($mode, 'r') !== false || strpos($mode, '+') !== false;
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173 3
    public function read($length)
174
    {
175 3
        $this->isAvailableAndException();
176 3
        if (!$this->isReadable()) {
177 1
            throw new RuntimeException('Stream is not readable.');
178
        }
179 2
        if (false === $result = fread($this->resource, $length)) {
180
            throw new RuntimeException('Error reading from stream.');
181
        }
182 2
        return $result;
183
    }
184
185
    /**
186
     * {@inheritdoc}
187
     */
188 15
    public function getContents()
189
    {
190 15
        if (!$this->isReadable()) {
191
            return '';
192
        }
193 15
        if (false === $result = stream_get_contents($this->resource)) {
194
            throw new RuntimeException('Error reading from stream.');
195
        }
196 15
        return $result;
197
    }
198
199
    /**
200
     * {@inheritdoc}
201
     */
202 4
    public function getMetadata($key = null)
203
    {
204 4
        $metaData = stream_get_meta_data($this->resource);
205 4
        if (!isset($key)) {
206 2
            return $metaData;
207
        }
208 4
        return isset($metaData[$key]) ? $metaData[$key] : null;
209
    }
210
211
    /**
212
     * @throws \RuntimeException
213
     */
214 18
    protected function isAvailableAndException()
215
    {
216 18
        if (!$this->resource) {
217 2
            throw new RuntimeException('No resource available.');
218
        }
219 16
    }
220
}
221