CallbackStream::eof()   A
last analyzed

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 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
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
namespace Kambo\Http\Stream;
3
4
// \Spl
5
use RuntimeException;
6
use Exception;
7
8
// \Psr
9
use Psr\Http\Message\StreamInterface;
10
11
/**
12
 * Describes a callback stream.
13
 *
14
 * It provides a stream wrapper around the provided callback.
15
 *
16
 * @package Kambo\Http\Stream
17
 * @author  Bohuslav Simek <[email protected]>
18
 * @license MIT
19
 */
20
class CallbackStream implements StreamInterface
21
{
22
    /**
23
     * Stream callback
24
     *
25
     * @var callable|null
26
     */
27
    protected $callback;
28
29
    /**
30
     * Constructor - CallbackStream accept callback as an only parameter.
31
     *
32
     * @param callable $callback
33
     */
34 19
    public function __construct(callable $callback)
35
    {
36 19
        $this->callback = $callback;
37 19
    }
38
39
    /**
40
     * Closes the stream and null the callback.
41
     *
42
     * @return void
43
     */
44 1
    public function close()
45
    {
46 1
        $this->callback = null;
47 1
    }
48
49
    /**
50
     * Separates underline callback from the stream.
51
     *
52
     * After the stream has been detached, the stream is in an unusable state.
53
     *
54
     * @return callable|null Underlying callback, if any
55
     */
56 6
    public function detach()
57
    {
58 6
        $oldCallback    = $this->callback;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->callback; of type callable|null adds the type callable to the return on line 61 which is incompatible with the return type declared by the interface Psr\Http\Message\StreamInterface::detach of type resource|null.
Loading history...
59 6
        $this->callback = null;
60
61 6
        return $oldCallback;
62
    }
63
64
    /**
65
     * Get the size of the stream if known.
66
     * Size of the callback stream is always unknown, thus a null value is returned.
67
     *
68
     * @return null Returns the size in bytes if known, or null if unknown.
69
     */
70 1
    public function getSize()
71
    {
72 1
        return null;
73
    }
74
75
    /**
76
     * Returns the current position of the file read/write pointer.
77
     * This is not supported for the callback stream.
78
     *
79
     * @return void
80
     *
81
     * @throws \RuntimeException on error.
82
     */
83 1
    public function tell()
84
    {
85 1
        throw new RuntimeException('Callback stream do not provide current position');
86
    }
87
88
    /**
89
     * Returns true if the stream is at the end of the stream.
90
     *
91
     * @return bool
92
     */
93 4
    public function eof()
94
    {
95 4
        return empty($this->callback);
96
    }
97
98
    /**
99
     * Returns whether or not the stream is seekable.
100
     * The callback stream is not seekable.
101
     *
102
     * @return bool 
103
     */
104 1
    public function isSeekable()
105
    {
106 1
        return false;
107
    }
108
109
    /**
110
     * Seek to a position in the stream.
111
     * The callback stream is not seekable, this method will raise an exception.
112
     *
113
     * @link http://www.php.net/manual/en/function.fseek.php
114
     *
115
     * @param int $offset Stream offset
116
     * @param int $whence Specifies how the cursor position will be calculated
117
     *                    based on the seek offset. Valid values are identical to the built-in
118
     *                    PHP $whence values for `fseek()`.  SEEK_SET: Set position equal to
119
     *                    offset bytes SEEK_CUR: Set position to current location plus offset
120
     *                    SEEK_END: Set position to end-of-stream plus offset.
121
     *
122
     * @return void
123
     *
124
     * @throws \RuntimeException on failure.
125
     */
126 1
    public function seek($offset, $whence = SEEK_SET)
127
    {
128 1
        throw new RuntimeException('Cannot seek in callback stream');
129
    }
130
131
    /**
132
     * Seek to the beginning of the stream.
133
     * The callback stream is not seekable, this method will raise an exception.
134
     *
135
     * @see seek()
136
     * @link http://www.php.net/manual/en/function.fseek.php
137
     *
138
     * @return void
139
     *
140
     * @throws \RuntimeException on failure.
141
     */
142 1
    public function rewind()
143
    {
144 1
        throw new RuntimeException('Cannot rewind callback stream');
145
    }
146
147
    /**
148
     * Returns whether or not the stream is writable.
149
     * The callback stream is not writable, this method will raise an exception.
150
     *
151
     * @return bool
152
     */
153 1
    public function isWritable()
154
    {
155 1
        return false;
156
    }
157
158
    /**
159
     * Write data to the stream.
160
     * The callback stream is not writable, this method will raise an exception.
161
     *
162
     * @param string $string The string that is to be written.
163
     *
164
     * @return void
165
     *
166
     * @throws \RuntimeException on failure.
167
     */
168 1
    public function write($string)
169
    {
170 1
        throw new RuntimeException('Cannot write into callback stream');
171
    }
172
173
    /**
174
     * Returns whether or not the stream is readable.
175
     * The callback stream is not readable.
176
     *
177
     * @return bool
178
     */
179 1
    public function isReadable()
180
    {
181 1
        return false;
182
    }
183
184
    /**
185
     * Read data from the stream.
186
     * The callback stream is not readable, this method will raise an exception.
187
     *
188
     * @param int $length Read up to $length bytes from the object and return
189
     *                    them. Fewer than $length bytes may be returned if underlying stream
190
     *                    call returns fewer bytes.
191
     *
192
     * @return string Returns the data read from the stream, or an empty string
193
     *                if no bytes are available.
194
     *
195
     * @throws \RuntimeException if an error occurs.
196
     */
197 1
    public function read($length)
198
    {
199 1
        throw new RuntimeException('Cannot read in callback stream');
200
    }
201
202
    /**
203
     * Execute callback function and return its content as a string.
204
     *
205
     * @return string
206
     *
207
     * @throws \RuntimeException if unable to read or an error occurs while reading.
208
     */
209 5
    public function getContents()
210
    {
211 5
        $callback = $this->detach();
212 5
        return $callback ? $callback() : '';
213
    }
214
215
    /**
216
     * Get stream metadata as an associative array or retrieve a specific key.
217
     *
218
     * The keys returned are same to the keys returned from PHP's
219
     * stream_get_meta_data() function.
220
     *
221
     * @link http://php.net/manual/en/function.stream-get-meta-data.php
222
     *
223
     * @param string $key Specific metadata to retrieve.
224
     *
225
     * @return array|mixed|null Returns an associative array if no key is provided.
226
     *                          Returns a specific key value if a key is provided and the
227
     *                          value is found, or null if the key is not found.
228
     */
229 3
    public function getMetadata($key = null)
230
    {
231
        $metadata = [
232 3
            'eof' => $this->eof(),
233 3
            'stream_type' => 'callback',
234
            'seekable' => false
235 3
        ];
236
237 3
        if (is_null($key) === true) {
238 1
            return $metadata;
239
        }
240
241 2
        return isset($metadata[$key]) ? $metadata[$key] : null;
242
    }
243
244
    /**
245
     * Execute callback function and return its content as a string.
246
     *
247
     * This method does not raise an exception in order to conform with PHP's
248
     * string casting operations.
249
     *
250
     * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring
251
     *
252
     * @return string
253
     */
254 2
    public function __toString()
255
    {
256
        try {
257 2
            return $this->getContents();
258 1
        } catch (Exception $e) {
259 1
            return '';
260
        }
261
    }
262
}
263