Completed
Push — master ( 16c8a5...965897 )
by Michael
02:58
created

Stream::getContents()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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