PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.5
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.5
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
wordpress-seo / vendor_prefixed / guzzlehttp / guzzle / src / HandlerStack.php

HandlerStack.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 28.5, at vendor_prefixed/guzzlehttp/guzzle/src/HandlerStack.php

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