PluginProbe
StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more / 2.1
StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more v2.1
3.7.0 3.6.0 3.6.1 3.5.2 trunk 2.0 2.1 2.2 2.3 2.4 2.4.1 2.4.2 2.4.3 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.6.0 2.6.1 3.0.0 3.0.1 All 71 releases
stockpack / vendor / guzzlehttp / guzzle / src / HandlerStack.php

HandlerStack.php in StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more 2.1, at vendor/guzzlehttp/guzzle/src/HandlerStack.php

278 lines 7.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace GuzzleHttp;
3
4 use GuzzleHttp\Promise\PromiseInterface;
5 use Psr\Http\Message\RequestInterface;
6 use Psr\Http\Message\ResponseInterface;
7
8 /**
9 * Creates a composed Guzzle handler function by stacking middlewares on top of
10 * an HTTP handler function.
11 */
12 class HandlerStack
13 {
14 /** @var callable|null */
15 private $handler;
16
17 /** @var array */
18 private $stack = [];
19
20 /** @var callable|null */
21 private $cached;
22
23 /**
24 * Creates a default handler stack that can be used by clients.
25 *
26 * The returned handler will wrap the provided handler or use the most
27 * appropriate default handler for your system. The returned HandlerStack has
28 * support for cookies, redirects, HTTP error exceptions, and preparing a body
29 * before sending.
30 *
31 * The returned handler stack can be passed to a client in the "handler"
32 * option.
33 *
34 * @param callable $handler HTTP handler function to use with the stack. If no
35 * handler is provided, the best handler for your
36 * system will be utilized.
37 *
38 * @return HandlerStack
39 */
40 public static function create(callable $handler = null)
41 {
42 $stack = new self($handler ?: choose_handler());
43 $stack->push(Middleware::httpErrors(), 'http_errors');
44 $stack->push(Middleware::redirect(), 'allow_redirects');
45 $stack->push(Middleware::cookies(), 'cookies');
46 $stack->push(Middleware::prepareBody(), 'prepare_body');
47
48 return $stack;
49 }
50
51 /**
52 * @param callable $handler Underlying HTTP handler.
53 */
54 public function __construct(callable $handler = null)
55 {
56 $this->handler = $handler;
57 }
58
59 /**
60 * Invokes the handler stack as a composed handler
61 *
62 * @param RequestInterface $request
63 * @param array $options
64 *
65 * @return ResponseInterface|PromiseInterface
66 */
67 public function __invoke(RequestInterface $request, array $options)
68 {
69 $handler = $this->resolve();
70
71 return $handler($request, $options);
72 }
73
74 /**
75 * Dumps a string representation of the stack.
76 *
77 * @return string
78 */
79 public function __toString()
80 {
81 $depth = 0;
82 $stack = [];
83 if ($this->handler) {
84 $stack[] = "0) Handler: " . $this->debugCallable($this->handler);
85 }
86
87 $result = '';
88 foreach (array_reverse($this->stack) as $tuple) {
89 $depth++;
90 $str = "{$depth}) Name: '{$tuple[1]}', ";
91 $str .= "Function: " . $this->debugCallable($tuple[0]);
92 $result = "> {$str}\n{$result}";
93 $stack[] = $str;
94 }
95
96 foreach (array_keys($stack) as $k) {
97 $result .= "< {$stack[$k]}\n";
98 }
99
100 return $result;
101 }
102
103 /**
104 * Set the HTTP handler that actually returns a promise.
105 *
106 * @param callable $handler Accepts a request and array of options and
107 * returns a Promise.
108 */
109 public function setHandler(callable $handler)
110 {
111 $this->handler = $handler;
112 $this->cached = null;
113 }
114
115 /**
116 * Returns true if the builder has a handler.
117 *
118 * @return bool
119 */
120 public function hasHandler()
121 {
122 return (bool) $this->handler;
123 }
124
125 /**
126 * Unshift a middleware to the bottom of the stack.
127 *
128 * @param callable $middleware Middleware function
129 * @param string $name Name to register for this middleware.
130 */
131 public function unshift(callable $middleware, $name = null)
132 {
133 array_unshift($this->stack, [$middleware, $name]);
134 $this->cached = null;
135 }
136
137 /**
138 * Push a middleware to the top of the stack.
139 *
140 * @param callable $middleware Middleware function
141 * @param string $name Name to register for this middleware.
142 */
143 public function push(callable $middleware, $name = '')
144 {
145 $this->stack[] = [$middleware, $name];
146 $this->cached = null;
147 }
148
149 /**
150 * Add a middleware before another middleware by name.
151 *
152 * @param string $findName Middleware to find
153 * @param callable $middleware Middleware function
154 * @param string $withName Name to register for this middleware.
155 */
156 public function before($findName, callable $middleware, $withName = '')
157 {
158 $this->splice($findName, $withName, $middleware, true);
159 }
160
161 /**
162 * Add a middleware after another middleware by name.
163 *
164 * @param string $findName Middleware to find
165 * @param callable $middleware Middleware function
166 * @param string $withName Name to register for this middleware.
167 */
168 public function after($findName, callable $middleware, $withName = '')
169 {
170 $this->splice($findName, $withName, $middleware, false);
171 }
172
173 /**
174 * Remove a middleware by instance or name from the stack.
175 *
176 * @param callable|string $remove Middleware to remove by instance or name.
177 */
178 public function remove($remove)
179 {
180 $this->cached = null;
181 $idx = is_callable($remove) ? 0 : 1;
182 $this->stack = array_values(array_filter(
183 $this->stack,
184 function ($tuple) use ($idx, $remove) {
185 return $tuple[$idx] !== $remove;
186 }
187 ));
188 }
189
190 /**
191 * Compose the middleware and handler into a single callable function.
192 *
193 * @return callable
194 */
195 public function resolve()
196 {
197 if (!$this->cached) {
198 if (!($prev = $this->handler)) {
199 throw new \LogicException('No handler has been specified');
200 }
201
202 foreach (array_reverse($this->stack) as $fn) {
203 $prev = $fn[0]($prev);
204 }
205
206 $this->cached = $prev;
207 }
208
209 return $this->cached;
210 }
211
212 /**
213 * @param string $name
214 * @return int
215 */
216 private function findByName($name)
217 {
218 foreach ($this->stack as $k => $v) {
219 if ($v[1] === $name) {
220 return $k;
221 }
222 }
223
224 throw new \InvalidArgumentException("Middleware not found: $name");
225 }
226
227 /**
228 * Splices a function into the middleware list at a specific position.
229 *
230 * @param string $findName
231 * @param string $withName
232 * @param callable $middleware
233 * @param bool $before
234 */
235 private function splice($findName, $withName, callable $middleware, $before)
236 {
237 $this->cached = null;
238 $idx = $this->findByName($findName);
239 $tuple = [$middleware, $withName];
240
241 if ($before) {
242 if ($idx === 0) {
243 array_unshift($this->stack, $tuple);
244 } else {
245 $replacement = [$tuple, $this->stack[$idx]];
246 array_splice($this->stack, $idx, 1, $replacement);
247 }
248 } elseif ($idx === count($this->stack) - 1) {
249 $this->stack[] = $tuple;
250 } else {
251 $replacement = [$this->stack[$idx], $tuple];
252 array_splice($this->stack, $idx, 1, $replacement);
253 }
254 }
255
256 /**
257 * Provides a debug string for a given callable.
258 *
259 * @param array|callable $fn Function to write as a string.
260 *
261 * @return string
262 */
263 private function debugCallable($fn)
264 {
265 if (is_string($fn)) {
266 return "callable({$fn})";
267 }
268
269 if (is_array($fn)) {
270 return is_string($fn[0])
271 ? "callable({$fn[0]}::{$fn[1]})"
272 : "callable(['" . get_class($fn[0]) . "', '{$fn[1]}'])";
273 }
274
275 return 'callable(' . spl_object_hash($fn) . ')';
276 }
277 }
278