123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- <?php
- namespace GuzzleHttp;
- use GuzzleHttp\Promise\PromiseInterface;
- use Psr\Http\Message\RequestInterface;
- use Psr\Http\Message\ResponseInterface;
- class HandlerStack
- {
-
- private $handler;
-
- private $stack = [];
-
- private $cached;
-
- public static function create(callable $handler = null): self
- {
- $stack = new self($handler ?: Utils::chooseHandler());
- $stack->push(Middleware::httpErrors(), 'http_errors');
- $stack->push(Middleware::redirect(), 'allow_redirects');
- $stack->push(Middleware::cookies(), 'cookies');
- $stack->push(Middleware::prepareBody(), 'prepare_body');
- return $stack;
- }
-
- public function __construct(callable $handler = null)
- {
- $this->handler = $handler;
- }
-
- public function __invoke(RequestInterface $request, array $options)
- {
- $handler = $this->resolve();
- return $handler($request, $options);
- }
-
- public function __toString()
- {
- $depth = 0;
- $stack = [];
- if ($this->handler !== null) {
- $stack[] = '0) Handler: '.$this->debugCallable($this->handler);
- }
- $result = '';
- foreach (\array_reverse($this->stack) as $tuple) {
- ++$depth;
- $str = "{$depth}) Name: '{$tuple[1]}', ";
- $str .= 'Function: '.$this->debugCallable($tuple[0]);
- $result = "> {$str}\n{$result}";
- $stack[] = $str;
- }
- foreach (\array_keys($stack) as $k) {
- $result .= "< {$stack[$k]}\n";
- }
- return $result;
- }
-
- public function setHandler(callable $handler): void
- {
- $this->handler = $handler;
- $this->cached = null;
- }
-
- public function hasHandler(): bool
- {
- return $this->handler !== null;
- }
-
- public function unshift(callable $middleware, string $name = null): void
- {
- \array_unshift($this->stack, [$middleware, $name]);
- $this->cached = null;
- }
-
- public function push(callable $middleware, string $name = ''): void
- {
- $this->stack[] = [$middleware, $name];
- $this->cached = null;
- }
-
- public function before(string $findName, callable $middleware, string $withName = ''): void
- {
- $this->splice($findName, $withName, $middleware, true);
- }
-
- public function after(string $findName, callable $middleware, string $withName = ''): void
- {
- $this->splice($findName, $withName, $middleware, false);
- }
-
- public function remove($remove): void
- {
- if (!is_string($remove) && !is_callable($remove)) {
- 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__);
- }
- $this->cached = null;
- $idx = \is_callable($remove) ? 0 : 1;
- $this->stack = \array_values(\array_filter(
- $this->stack,
- static function ($tuple) use ($idx, $remove) {
- return $tuple[$idx] !== $remove;
- }
- ));
- }
-
- public function resolve(): callable
- {
- if ($this->cached === null) {
- if (($prev = $this->handler) === null) {
- throw new \LogicException('No handler has been specified');
- }
- foreach (\array_reverse($this->stack) as $fn) {
-
- $prev = $fn[0]($prev);
- }
- $this->cached = $prev;
- }
- return $this->cached;
- }
- private function findByName(string $name): int
- {
- foreach ($this->stack as $k => $v) {
- if ($v[1] === $name) {
- return $k;
- }
- }
- throw new \InvalidArgumentException("Middleware not found: $name");
- }
-
- private function splice(string $findName, string $withName, callable $middleware, bool $before): void
- {
- $this->cached = null;
- $idx = $this->findByName($findName);
- $tuple = [$middleware, $withName];
- if ($before) {
- if ($idx === 0) {
- \array_unshift($this->stack, $tuple);
- } else {
- $replacement = [$tuple, $this->stack[$idx]];
- \array_splice($this->stack, $idx, 1, $replacement);
- }
- } elseif ($idx === \count($this->stack) - 1) {
- $this->stack[] = $tuple;
- } else {
- $replacement = [$this->stack[$idx], $tuple];
- \array_splice($this->stack, $idx, 1, $replacement);
- }
- }
-
- private function debugCallable($fn): string
- {
- if (\is_string($fn)) {
- return "callable({$fn})";
- }
- if (\is_array($fn)) {
- return \is_string($fn[0])
- ? "callable({$fn[0]}::{$fn[1]})"
- : "callable(['".\get_class($fn[0])."', '{$fn[1]}'])";
- }
-
- return 'callable('.\spl_object_hash($fn).')';
- }
- }
|