PluginProbe
Media Cloud Sync / 1.3.11
Media Cloud Sync v1.3.11
1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 All 34 releases
media-cloud-sync / includes / sdk / s3 / Aws / HandlerList.php

HandlerList.php in Media Cloud Sync 1.3.11, at includes/sdk/s3/Aws/HandlerList.php

405 lines 13.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Dudlewebs\WPMCS\s3\Aws;
4
5 /**
6 * Builds a single handler function from zero or more middleware functions and
7 * a handler. The handler function is then used to send command objects and
8 * return a promise that is resolved with an AWS result object.
9 *
10 * The "front" of the list is invoked before the "end" of the list. You can add
11 * middleware to the front of the list using one of the "prepend" method, and
12 * the end of the list using one of the "append" method. The last function
13 * invoked in a handler list is the handler (a function that does not accept a
14 * next handler but rather is responsible for returning a promise that is
15 * fulfilled with an Aws\ResultInterface object).
16 *
17 * Handlers are ordered using a "step" that describes the step at which the
18 * SDK is when sending a command. The available steps are:
19 *
20 * - init: The command is being initialized, allowing you to do things like add
21 * default options.
22 * - validate: The command is being validated before it is serialized
23 * - build: The command is being serialized into an HTTP request. A middleware
24 * in this step MUST serialize an HTTP request and populate the "@request"
25 * parameter of a command with the request such that it is available to
26 * subsequent middleware.
27 * - sign: The request is being signed and prepared to be sent over the wire.
28 *
29 * Middleware can be registered with a name to allow you to easily add a
30 * middleware before or after another middleware by name. This also allows you
31 * to remove a middleware by name (in addition to removing by instance).
32 */
33 class HandlerList implements \Countable
34 {
35 const INIT = 'init';
36 const VALIDATE = 'validate';
37 const BUILD = 'build';
38 const SIGN = 'sign';
39 const ATTEMPT = 'attempt';
40 /** @var callable */
41 private $handler;
42 /** @var array */
43 private $named = [];
44 /** @var array */
45 private $sorted;
46 /** @var callable|null */
47 private $interposeFn;
48 /** @var array Steps (in reverse order) */
49 private $steps = [self::ATTEMPT => [], self::SIGN => [], self::BUILD => [], self::VALIDATE => [], self::INIT => []];
50 /**
51 * @param callable $handler HTTP handler.
52 */
53 public function __construct(?callable $handler = null)
54 {
55 $this->handler = $handler;
56 }
57 /**
58 * Dumps a string representation of the list.
59 *
60 * @return string
61 */
62 public function __toString()
63 {
64 $str = '';
65 $i = 0;
66 foreach (\array_reverse($this->steps) as $k => $step) {
67 foreach (\array_reverse($step) as $j => $tuple) {
68 $str .= "{$i}) Step: {$k}, ";
69 if ($tuple[1]) {
70 $str .= "Name: {$tuple[1]}, ";
71 }
72 $str .= "Function: " . $this->debugCallable($tuple[0]) . "\n";
73 $i++;
74 }
75 }
76 if ($this->handler) {
77 $str .= "{$i}) Handler: " . $this->debugCallable($this->handler) . "\n";
78 }
79 return $str;
80 }
81 /**
82 * Set the HTTP handler that actually returns a response.
83 *
84 * @param callable $handler Function that accepts a request and array of
85 * options and returns a Promise.
86 */
87 public function setHandler(callable $handler)
88 {
89 $this->handler = $handler;
90 }
91 /**
92 * Returns true if the builder has a handler.
93 *
94 * @return bool
95 */
96 public function hasHandler()
97 {
98 return (bool) $this->handler;
99 }
100 /**
101 * Checks if a middleware exists. The middleware
102 * should have been added with a name in order to
103 * use this method.
104 *
105 * @param string $name
106 *
107 * @return bool
108 */
109 public function hasMiddleware(string $name) : bool
110 {
111 return isset($this->named[$name]);
112 }
113 /**
114 * Append a middleware to the init step.
115 *
116 * @param callable $middleware Middleware function to add.
117 * @param string $name Name of the middleware.
118 */
119 public function appendInit(callable $middleware, $name = null)
120 {
121 $this->add(self::INIT, $name, $middleware);
122 }
123 /**
124 * Prepend a middleware to the init step.
125 *
126 * @param callable $middleware Middleware function to add.
127 * @param string $name Name of the middleware.
128 */
129 public function prependInit(callable $middleware, $name = null)
130 {
131 $this->add(self::INIT, $name, $middleware, \true);
132 }
133 /**
134 * Append a middleware to the validate step.
135 *
136 * @param callable $middleware Middleware function to add.
137 * @param string $name Name of the middleware.
138 */
139 public function appendValidate(callable $middleware, $name = null)
140 {
141 $this->add(self::VALIDATE, $name, $middleware);
142 }
143 /**
144 * Prepend a middleware to the validate step.
145 *
146 * @param callable $middleware Middleware function to add.
147 * @param string $name Name of the middleware.
148 */
149 public function prependValidate(callable $middleware, $name = null)
150 {
151 $this->add(self::VALIDATE, $name, $middleware, \true);
152 }
153 /**
154 * Append a middleware to the build step.
155 *
156 * @param callable $middleware Middleware function to add.
157 * @param string $name Name of the middleware.
158 */
159 public function appendBuild(callable $middleware, $name = null)
160 {
161 $this->add(self::BUILD, $name, $middleware);
162 }
163 /**
164 * Prepend a middleware to the build step.
165 *
166 * @param callable $middleware Middleware function to add.
167 * @param string $name Name of the middleware.
168 */
169 public function prependBuild(callable $middleware, $name = null)
170 {
171 $this->add(self::BUILD, $name, $middleware, \true);
172 }
173 /**
174 * Append a middleware to the sign step.
175 *
176 * @param callable $middleware Middleware function to add.
177 * @param string $name Name of the middleware.
178 */
179 public function appendSign(callable $middleware, $name = null)
180 {
181 $this->add(self::SIGN, $name, $middleware);
182 }
183 /**
184 * Prepend a middleware to the sign step.
185 *
186 * @param callable $middleware Middleware function to add.
187 * @param string $name Name of the middleware.
188 */
189 public function prependSign(callable $middleware, $name = null)
190 {
191 $this->add(self::SIGN, $name, $middleware, \true);
192 }
193 /**
194 * Append a middleware to the attempt step.
195 *
196 * @param callable $middleware Middleware function to add.
197 * @param string $name Name of the middleware.
198 */
199 public function appendAttempt(callable $middleware, $name = null)
200 {
201 $this->add(self::ATTEMPT, $name, $middleware);
202 }
203 /**
204 * Prepend a middleware to the attempt step.
205 *
206 * @param callable $middleware Middleware function to add.
207 * @param string $name Name of the middleware.
208 */
209 public function prependAttempt(callable $middleware, $name = null)
210 {
211 $this->add(self::ATTEMPT, $name, $middleware, \true);
212 }
213 /**
214 * Add a middleware before the given middleware by name.
215 *
216 * @param string|callable $findName Add before this
217 * @param string $withName Optional name to give the middleware
218 * @param callable $middleware Middleware to add.
219 */
220 public function before($findName, $withName, callable $middleware)
221 {
222 $this->splice($findName, $withName, $middleware, \true);
223 }
224 /**
225 * Add a middleware after the given middleware by name.
226 *
227 * @param string|callable $findName Add after this
228 * @param string $withName Optional name to give the middleware
229 * @param callable $middleware Middleware to add.
230 */
231 public function after($findName, $withName, callable $middleware)
232 {
233 $this->splice($findName, $withName, $middleware, \false);
234 }
235 /**
236 * Remove a middleware by name or by instance from the list.
237 *
238 * @param string|callable $nameOrInstance Middleware to remove.
239 */
240 public function remove($nameOrInstance)
241 {
242 if (\is_callable($nameOrInstance)) {
243 $this->removeByInstance($nameOrInstance);
244 } elseif (\is_string($nameOrInstance)) {
245 $this->removeByName($nameOrInstance);
246 }
247 }
248 /**
249 * Interpose a function between each middleware (e.g., allowing for a trace
250 * through the middleware layers).
251 *
252 * The interpose function is a function that accepts a "step" argument as a
253 * string and a "name" argument string. This function must then return a
254 * function that accepts the next handler in the list. This function must
255 * then return a function that accepts a CommandInterface and optional
256 * RequestInterface and returns a promise that is fulfilled with an
257 * Aws\ResultInterface or rejected with an Aws\Exception\AwsException
258 * object.
259 *
260 * @param callable|null $fn Pass null to remove any previously set function
261 */
262 public function interpose(?callable $fn = null)
263 {
264 $this->sorted = null;
265 $this->interposeFn = $fn;
266 }
267 /**
268 * Compose the middleware and handler into a single callable function.
269 *
270 * @return callable
271 */
272 public function resolve()
273 {
274 if (!($prev = $this->handler)) {
275 throw new \LogicException('No handler has been specified');
276 }
277 if ($this->sorted === null) {
278 $this->sortMiddleware();
279 }
280 foreach ($this->sorted as $fn) {
281 $prev = $fn($prev);
282 }
283 return $prev;
284 }
285 /**
286 * @return int
287 */
288 #[\ReturnTypeWillChange]
289 public function count()
290 {
291 return \count($this->steps[self::INIT]) + \count($this->steps[self::VALIDATE]) + \count($this->steps[self::BUILD]) + \count($this->steps[self::SIGN]) + \count($this->steps[self::ATTEMPT]);
292 }
293 /**
294 * Splices a function into the middleware list at a specific position.
295 *
296 * @param $findName
297 * @param $withName
298 * @param callable $middleware
299 * @param $before
300 */
301 private function splice($findName, $withName, callable $middleware, $before)
302 {
303 if (!isset($this->named[$findName])) {
304 throw new \InvalidArgumentException("{$findName} not found");
305 }
306 $idx = $this->sorted = null;
307 $step = $this->named[$findName];
308 if ($withName) {
309 $this->named[$withName] = $step;
310 }
311 foreach ($this->steps[$step] as $i => $tuple) {
312 if ($tuple[1] === $findName) {
313 $idx = $i;
314 break;
315 }
316 }
317 $replacement = $before ? [$this->steps[$step][$idx], [$middleware, $withName]] : [[$middleware, $withName], $this->steps[$step][$idx]];
318 \array_splice($this->steps[$step], $idx, 1, $replacement);
319 }
320 /**
321 * Provides a debug string for a given callable.
322 *
323 * @param array|callable $fn Function to write as a string.
324 *
325 * @return string
326 */
327 private function debugCallable($fn)
328 {
329 if (\is_string($fn)) {
330 return "callable({$fn})";
331 }
332 if (\is_array($fn)) {
333 $ele = \is_string($fn[0]) ? $fn[0] : \get_class($fn[0]);
334 return "callable(['{$ele}', '{$fn[1]}'])";
335 }
336 return 'callable(' . \spl_object_hash($fn) . ')';
337 }
338 /**
339 * Sort the middleware, and interpose if needed in the sorted list.
340 */
341 private function sortMiddleware()
342 {
343 $this->sorted = [];
344 if (!$this->interposeFn) {
345 foreach ($this->steps as $step) {
346 foreach ($step as $fn) {
347 $this->sorted[] = $fn[0];
348 }
349 }
350 return;
351 }
352 $ifn = $this->interposeFn;
353 // Interpose the interposeFn into the handler stack.
354 foreach ($this->steps as $stepName => $step) {
355 foreach ($step as $fn) {
356 $this->sorted[] = $ifn($stepName, $fn[1]);
357 $this->sorted[] = $fn[0];
358 }
359 }
360 }
361 private function removeByName($name)
362 {
363 if (!isset($this->named[$name])) {
364 return;
365 }
366 $this->sorted = null;
367 $step = $this->named[$name];
368 $this->steps[$step] = \array_values(\array_filter($this->steps[$step], function ($tuple) use($name) {
369 return $tuple[1] !== $name;
370 }));
371 }
372 private function removeByInstance(callable $fn)
373 {
374 foreach ($this->steps as $k => $step) {
375 foreach ($step as $j => $tuple) {
376 if ($tuple[0] === $fn) {
377 $this->sorted = null;
378 unset($this->named[$this->steps[$k][$j][1]]);
379 unset($this->steps[$k][$j]);
380 }
381 }
382 }
383 }
384 /**
385 * Add a middleware to a step.
386 *
387 * @param string $step Middleware step.
388 * @param string $name Middleware name.
389 * @param callable $middleware Middleware function to add.
390 * @param bool $prepend Prepend instead of append.
391 */
392 private function add($step, $name, callable $middleware, $prepend = \false)
393 {
394 $this->sorted = null;
395 if ($prepend) {
396 $this->steps[$step][] = [$middleware, $name];
397 } else {
398 \array_unshift($this->steps[$step], [$middleware, $name]);
399 }
400 if ($name) {
401 $this->named[$name] = $step;
402 }
403 }
404 }
405