Stream::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 2
rs 10
1
<?php
2
3
/**
4
 * This file is part of the miBadger package.
5
 *
6
 * @author Michael Webbers <[email protected]>
7
 * @license http://opensource.org/licenses/Apache-2.0 Apache v2 License
8
 */
9
10
namespace miBadger\Http;
11
12
use Psr\Http\Message\StreamInterface;
13
14
/**
15
 * The stream class
16
 *
17
 * @see http://www.php-fig.org/psr/psr-7/
18
 * @since 1.0.0
19
 */
20
class Stream implements StreamInterface
21
{
22
	/** @var resource The resource. */
23
	private $resource;
24
25
	/** @var array The metadata. */
26
	private $metadata;
27
28
	/** @var string[] The read modes. */
29
	private static $readModes = ['r', 'w+', 'r+', 'x+', 'c+', 'rb', 'w+b', 'r+b', 'x+b', 'c+b', 'rt', 'w+t', 'r+t', 'x+t', 'c+t', 'a+'];
30
31
	/** @var string[] The write modes. */
32
	private static $writeModes = ['w', 'w+', 'rw', 'r+', 'x+', 'c+', 'wb', 'w+b', 'r+b', 'x+b', 'c+b', 'w+t', 'r+t', 'x+t', 'c+t', 'a', 'a+'];
33
34
	/**
35
	 * Construct a Stream object with the given resource.
36
	 *
37
	 * @param resource $resource
38
	 */
39 73
	public function __construct($resource)
40
	{
41 73
		if (!is_resource($resource)) {
42 1
			throw new \InvalidArgumentException('Invalid resource');
43
		}
44
45 73
		$this->resource = $resource;
46 73
		$this->metadata = stream_get_meta_data($resource);
47 73
	}
48
49
	/**
50
	 * Destruct the Stream object.
51
	 */
52 10
	public function __destruct()
53
	{
54 10
		$this->close();
55 10
	}
56
57
	/**
58
	 * {@inheritdoc}
59
	 */
60 5
	public function __toString()
61
	{
62
		try {
63 5
			$this->seek(0);
64
65 3
			return $this->getContents();
66 2
		} catch (\Exception $e) {
67 2
			return '';
68
		}
69
	}
70
71
	/**
72
	 * {@inheritdoc}
73
	 */
74 11
	public function close()
75
	{
76 11
		if (isset($this->resource)) {
77 11
			if (is_resource($this->resource)) {
78 11
				fclose($this->resource);
79
			}
80
81 11
			$this->detach();
82
		}
83 11
	}
84
85
	/**
86
	 * {@inheritdoc}
87
	 */
88 17
	public function detach()
89
	{
90 17
		if (!isset($this->resource)) {
91 1
			return null;
92
		}
93
94 17
		$result = $this->resource;
95 17
		unset($this->resource);
96
97 17
		return $result;
98
	}
99
100
	/**
101
	 * {@inheritdoc}
102
	 */
103 2
	public function getSize()
104
	{
105 2
		if (!isset($this->resource)) {
106 1
			return null;
107
		}
108
109 1
		if ($this->getMetadata('uri')) {
110 1
			clearstatcache(true, $this->getMetadata('uri'));
111
		}
112
113 1
		$stats = fstat($this->resource);
114
115 1
		return isset($stats['size']) ? $stats['size'] : null;
116
	}
117
118
	/**
119
	 * {@inheritdoc}
120
	 */
121 2
	public function tell()
122
	{
123 2
		try {
124
			$result = ftell($this->resource);
125 2
		} catch (\TypeError $e) {
126 1
			throw new \RuntimeException('Error while getting the position of the pointer', 0, $e);
127
		}
128
129 1
		if ($result === false) {
130
			throw new \RuntimeException('Error while getting the position of the pointer');
131
		}
132
133
		return $result;
134
	}
135 1
136
	/**
137 1
	 * {@inheritdoc}
138
	 */
139
	public function eof()
140
	{
141
		return isset($this->resource) && feof($this->resource);
142
	}
143 10
144
	/**
145 10
	 * {@inheritdoc}
146
	 */
147
	public function isSeekable()
148
	{
149
		return isset($this->resource) && $this->getMetadata('seekable');
150
	}
151 9
152
	/**
153 9
	 * {@inheritdoc}
154 3
	 */
155
	public function seek($offset, $whence = SEEK_SET)
156
	{
157 6
		if (!$this->isSeekable()) {
158 1
			throw new \RuntimeException('Stream is not seekable');
159
		}
160 5
		
161
		try {
162
			$result = fseek($this->resource, $offset, $whence);
163
		} catch (\TypeError $e) {
164
			throw new \RuntimeException('Error while seeking the stream', 0, $e);
165 1
		}
166
167 1
		if ($result === false) {
168 1
			throw new \RuntimeException('Error while seeking the stream');
169
		}
170
	}
171
172
	/**
173 7
	 * {@inheritdoc}
174
	 */
175 7
	public function rewind()
176
	{
177
		$this->seek(0);
178
	}
179
180
	/**
181 6
	 * {@inheritdoc}
182
	 */
183 6
	public function isWritable()
184 1
	{
185
		return isset($this->resource) && in_array($this->getMetadata('mode'), self::$writeModes);
186
	}
187 5
188
	/**
189 5
	 * {@inheritdoc}
190 1
	 */
191
	public function write($string)
192
	{
193 4
		if (!$this->isWritable()) {
194
			throw new \RuntimeException('Stream is not writable');
195
		}
196
197
		try {
198
			$result = fwrite($this->resource, $string);
199 9
		} catch (\TypeError $e) {
200
			throw new \RuntimeException('Error while writing the stream', 0, $e);
201 9
		}
202
203
		if ($result === false) {
204
			throw new \RuntimeException('Error while writing the stream');
205
		}
206
207 8
		return $result;
208
	}
209 8
210 1
	/**
211
	 * {@inheritdoc}
212
	 */
213 7
	public function isReadable()
214
	{
215 7
		return isset($this->resource) && in_array($this->getMetadata('mode'), self::$readModes);
216 1
	}
217
218
	/**
219 6
	 * {@inheritdoc}
220
	 */
221
	public function read($length)
222
	{
223
		if (!$this->isReadable()) {
224
			throw new \RuntimeException('Stream is not readable');
225 5
		}
226
227 5
		try {
228
			$result = stream_get_contents($this->resource, $length);
229
		} catch (\TypeError $e) {
230
			throw new \RuntimeException('Error while reading the stream', 0, $e);
231
		}
232
233 18
		if ($result === false) {
234
			throw new \RuntimeException('Error while reading the stream');
235 18
		}
236 1
237
		return $result;
238
	}
239 17
240
	/**
241
	 * {@inheritdoc}
242
	 */
243
	public function getContents()
244
	{
245
		return $this->read(-1);
246
	}
247
248
	/**
249
	 * {@inheritdoc}
250
	 */
251
	public function getMetadata($key = null)
252
	{
253
		if ($key === null) {
254
			return $this->metadata;
255
		}
256
257
		return isset($this->metadata[$key]) ? $this->metadata[$key] : null;
258
	}
259
}
260