Passed
Pull Request — master (#56)
by Yasin
04:06 queued 01:57
created

FnStream::read()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace One\Http;
4
5
use Psr\Http\Message\StreamInterface;
6
7
/**
8
 * @property string $_fn___toString Contains function name as value
9
 * @property string $_fn_close Contains function name as value
10
 * @property string $_fn_detach Contains function name as value
11
 * @property string $_fn_rewind Contains function name as value
12
 * @property string $_fn_getSize Contains function name as value
13
 * @property string $_fn_tell Contains function name as value
14
 * @property string $_fn_eof Contains function name as value
15
 * @property string $_fn_isSeekable Contains function name as value
16
 * @property string $_fn_seek Contains function name as value
17
 * @property string $_fn_isWritable Contains function name as value
18
 * @property string $_fn_write Contains function name as value
19
 * @property string $_fn_isReadable Contains function name as value
20
 * @property string $_fn_read Contains function name as value
21
 * @property string $_fn_getContents Contains function name as value
22
 * @property string $_fn_getMetadata Contains function name as value
23
 * @property string[] $methods
24
 * @property string[] $slots An array that store list of function name
25
 */
26
class FnStream implements StreamInterface
27
{
28
    private $methods;
29
30
    private static $slots = ['__toString', 'close', 'detach', 'rewind',
31
        'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',
32
        'isReadable', 'read', 'getContents', 'getMetadata'];
33
34
    /**
35
     * @param array $methods Hash of method name to a callable.
36
     */
37
    public function __construct(array $methods)
38
    {
39
        $this->methods = $methods;
40
        // Create the functions on the class
41
        foreach ($methods as $name => $fn) {
42
            $this->{'_fn_' . $name} = $fn;
43
        }
44
    }
45
46
    /**
47
     * Lazily determine which methods are not implemented.
48
     * @throws \BadMethodCallException
49
     */
50
    public function __get($name)
51
    {
52
        throw new \BadMethodCallException(str_replace('_fn_', '', $name)
53
            . '() is not implemented in the FnStream');
54
    }
55
56
    /**
57
     * The close method is called on the underlying stream only if possible.
58
     */
59
    public function __destruct()
60
    {
61
        if (isset($this->_fn_close)) {
62
            call_user_func($this->_fn_close);
63
        }
64
    }
65
66
    /**
67
     * An unserialize would allow the __destruct to run when the unserialized value goes out of scope.
68
     * @throws \LogicException
69
     */
70
    public function __wakeup()
71
    {
72
        throw new \LogicException('FnStream should never be unserialized');
73
    }
74
75
    /**
76
     * Adds custom functionality to an underlying stream by intercepting
77
     * specific method calls.
78
     *
79
     * @param StreamInterface $stream  Stream to decorate
80
     * @param array           $methods Hash of method name to a closure
81
     *
82
     * @return FnStream
83
     */
84
    public static function decorate(StreamInterface $stream, array $methods)
85
    {
86
        // If any of the required methods were not provided, then simply
87
        // proxy to the decorated stream.
88
        foreach (array_diff(self::$slots, array_keys($methods)) as $diff) {
89
            $methods[$diff] = [$stream, $diff];
90
        }
91
        return new self($methods);
92
    }
93
  
94
    /**
95
     * @inheritDoc
96
     */
97
    public function __toString()
98
    {
99
        return call_user_func($this->_fn___toString);
100
    }
101
  
102
    /**
103
     * @inheritDoc
104
     */
105
    public function close()
106
    {
107
        return call_user_func($this->_fn_close);
108
    }
109
  
110
    /**
111
     * @inheritDoc
112
     */
113
    public function detach()
114
    {
115
        return call_user_func($this->_fn_detach);
116
    }
117
  
118
    /**
119
     * @inheritDoc
120
     */
121
    public function getSize()
122
    {
123
        return call_user_func($this->_fn_getSize);
124
    }
125
  
126
    /**
127
     * @inheritDoc
128
     */
129
    public function tell()
130
    {
131
        return call_user_func($this->_fn_tell);
132
    }
133
  
134
    /**
135
     * @inheritDoc
136
     */
137
    public function eof()
138
    {
139
        return call_user_func($this->_fn_eof);
140
    }
141
142
    /**
143
     * @inheritDoc
144
     */
145
    public function isSeekable()
146
    {
147
        return call_user_func($this->_fn_isSeekable);
148
    }
149
150
    /**
151
     * @inheritDoc
152
     */
153
    public function rewind()
154
    {
155
        call_user_func($this->_fn_rewind);
156
    }
157
158
    /**
159
     * @inheritDoc
160
     */
161
    public function seek($offset, $whence = SEEK_SET)
162
    {
163
        call_user_func($this->_fn_seek, $offset, $whence);
164
    }
165
166
    /**
167
     * @inheritDoc
168
     */
169
    public function isWritable()
170
    {
171
        return call_user_func($this->_fn_isWritable);
172
    }
173
174
    /**
175
     * @inheritDoc
176
     */
177
    public function write($string)
178
    {
179
        return call_user_func($this->_fn_write, $string);
180
    }
181
182
    /**
183
     * @inheritDoc
184
     */
185
    public function isReadable()
186
    {
187
        return call_user_func($this->_fn_isReadable);
188
    }
189
190
    /**
191
     * @inheritDoc
192
     */
193
    public function read($length)
194
    {
195
        return call_user_func($this->_fn_read, $length);
196
    }
197
198
    /**
199
     * @inheritDoc
200
     */
201
    public function getContents()
202
    {
203
        return call_user_func($this->_fn_getContents);
204
    }
205
206
    /**
207
     * @inheritDoc
208
     */
209
    public function getMetadata($key = null)
210
    {
211
        return call_user_func($this->_fn_getMetadata, $key);
212
    }
213
}
214