40 public static function create(callable $handler =
null)
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');
54 public function __construct(callable $handler =
null)
56 $this->handler = $handler;
67 public function __invoke(RequestInterface $request, array $options)
69 $handler = $this->resolve();
71 return $handler($request, $options);
84 $stack[] =
"0) Handler: " . $this->debugCallable($this->handler);
88 foreach (array_reverse($this->stack) as $tuple) {
90 $str =
"{$depth}) Name: '{$tuple[1]}', ";
91 $str .=
"Function: " . $this->debugCallable($tuple[0]);
92 $result =
"> {$str}\n{$result}";
96 foreach (array_keys($stack) as $k) {
97 $result .=
"< {$stack[$k]}\n";
109 public function setHandler(callable $handler)
111 $this->handler = $handler;
112 $this->cached =
null;
120 public function hasHandler()
122 return (
bool) $this->handler;
131 public function unshift(callable $middleware, $name =
null)
133 array_unshift($this->stack, [$middleware, $name]);
134 $this->cached =
null;
143 public function push(callable $middleware, $name =
'')
145 $this->stack[] = [$middleware, $name];
146 $this->cached =
null;
156 public function before($findName, callable $middleware, $withName =
'')
158 $this->splice($findName, $withName, $middleware,
true);
168 public function after($findName, callable $middleware, $withName =
'')
170 $this->splice($findName, $withName, $middleware,
false);
178 public function remove($remove)
180 $this->cached =
null;
181 $idx = is_callable($remove) ? 0 : 1;
182 $this->stack = array_values(array_filter(
184 function ($tuple) use ($idx, $remove) {
185 return $tuple[$idx] !== $remove;
195 public function resolve()
197 if (!$this->cached) {
198 if (!($prev = $this->handler)) {
199 throw new \LogicException(
'No handler has been specified');
202 foreach (array_reverse($this->stack) as $fn) {
203 $prev = $fn[0]($prev);
206 $this->cached = $prev;
209 return $this->cached;
216 private function findByName($name)
218 foreach ($this->stack as $k => $v) {
219 if ($v[1] === $name) {
224 throw new \InvalidArgumentException(
"Middleware not found: $name");
235 private function splice($findName, $withName, callable $middleware, $before)
237 $this->cached =
null;
238 $idx = $this->findByName($findName);
239 $tuple = [$middleware, $withName];
243 array_unshift($this->stack, $tuple);
245 $replacement = [$tuple, $this->stack[$idx]];
246 array_splice($this->stack, $idx, 1, $replacement);
248 } elseif ($idx ===
count($this->stack) - 1) {
249 $this->stack[] = $tuple;
251 $replacement = [$this->stack[$idx], $tuple];
252 array_splice($this->stack, $idx, 1, $replacement);
263 private function debugCallable($fn)
265 if (is_string($fn)) {
266 return "callable({$fn})";
270 return is_string($fn[0])
271 ?
"callable({$fn[0]}::{$fn[1]})"
272 :
"callable(['" . get_class($fn[0]) .
"', '{$fn[1]}'])";
275 return 'callable(' . spl_object_hash($fn) .
')';