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