scratch – Blame information for rev 87

Subversion Repositories:
Rev:
Rev Author Line No. Line
87 office 1 <?php
2 namespace GuzzleHttp\Stream;
3  
4 /**
5 * Compose stream implementations based on a hash of functions.
6 *
7 * Allows for easy testing and extension of a provided stream without needing
8 * to create a concrete class for a simple extension point.
9 */
10 class FnStream implements MetadataStreamInterface
11 {
12 /** @var array */
13 private $methods;
14  
15 /** @var array Methods that must be implemented in the given array */
16 private static $slots = ['__toString', 'close', 'detach', 'getSize',
17 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write', 'flush',
18 'isReadable', 'read', 'getContents', 'getMetadata'];
19  
20 /**
21 * @param array $methods Hash of method name to a callable.
22 */
23 public function __construct(array $methods)
24 {
25 $this->methods = $methods;
26  
27 // Create the functions on the class
28 foreach ($methods as $name => $fn) {
29 $this->{'_fn_' . $name} = $fn;
30 }
31 }
32  
33 /**
34 * Lazily determine which methods are not implemented.
35 * @throws \BadMethodCallException
36 */
37 public function __get($name)
38 {
39 throw new \BadMethodCallException(str_replace('_fn_', '', $name)
40 . '() is not implemented in the FnStream');
41 }
42  
43 /**
44 * The close method is called on the underlying stream only if possible.
45 */
46 public function __destruct()
47 {
48 if (isset($this->_fn_close)) {
49 call_user_func($this->_fn_close);
50 }
51 }
52  
53 /**
54 * Adds custom functionality to an underlying stream by intercepting
55 * specific method calls.
56 *
57 * @param StreamInterface $stream Stream to decorate
58 * @param array $methods Hash of method name to a closure
59 *
60 * @return FnStream
61 */
62 public static function decorate(StreamInterface $stream, array $methods)
63 {
64 // If any of the required methods were not provided, then simply
65 // proxy to the decorated stream.
66 foreach (array_diff(self::$slots, array_keys($methods)) as $diff) {
67 $methods[$diff] = [$stream, $diff];
68 }
69  
70 return new self($methods);
71 }
72  
73 public function __toString()
74 {
75 return call_user_func($this->_fn___toString);
76 }
77  
78 public function close()
79 {
80 return call_user_func($this->_fn_close);
81 }
82  
83 public function detach()
84 {
85 return call_user_func($this->_fn_detach);
86 }
87  
88 public function getSize()
89 {
90 return call_user_func($this->_fn_getSize);
91 }
92  
93 public function tell()
94 {
95 return call_user_func($this->_fn_tell);
96 }
97  
98 public function eof()
99 {
100 return call_user_func($this->_fn_eof);
101 }
102  
103 public function isSeekable()
104 {
105 return call_user_func($this->_fn_isSeekable);
106 }
107  
108 public function seek($offset, $whence = SEEK_SET)
109 {
110 return call_user_func($this->_fn_seek, $offset, $whence);
111 }
112  
113 public function isWritable()
114 {
115 return call_user_func($this->_fn_isWritable);
116 }
117  
118 public function write($string)
119 {
120 return call_user_func($this->_fn_write, $string);
121 }
122  
123 public function flush()
124 {
125 return call_user_func($this->_fn_flush);
126 }
127  
128 public function isReadable()
129 {
130 return call_user_func($this->_fn_isReadable);
131 }
132  
133 public function read($length)
134 {
135 return call_user_func($this->_fn_read, $length);
136 }
137  
138 public function getContents($maxLength = -1)
139 {
140 return call_user_func($this->_fn_getContents, $maxLength);
141 }
142  
143 public function getMetadata($key = null)
144 {
145 return call_user_func($this->_fn_getMetadata, $key);
146 }
147 }