Browse code

added appinfo/info.xml appinfo/signature.json CHANGELOG.txt lib/AppInfo/Application.php css/style.css providers/Plivo

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

removed appinfo/info.xml appinfo/signature.json CHANGELOG.txt lib/AppInfo/Application.php css/style.css providers/Plivo

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

Added README.md appinfo/info.xml appinfo/signature.json lib/Controller/AuthorApiController.php and the providers directory

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