| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455 | 
							- <?php
 
- namespace Aws;
 
- /**
 
-  * Builds a single handler function from zero or more middleware functions and
 
-  * a handler. The handler function is then used to send command objects and
 
-  * return a promise that is resolved with an AWS result object.
 
-  *
 
-  * The "front" of the list is invoked before the "end" of the list. You can add
 
-  * middleware to the front of the list using one of the "prepend" method, and
 
-  * the end of the list using one of the "append" method. The last function
 
-  * invoked in a handler list is the handler (a function that does not accept a
 
-  * next handler but rather is responsible for returning a promise that is
 
-  * fulfilled with an Aws\ResultInterface object).
 
-  *
 
-  * Handlers are ordered using a "step" that describes the step at which the
 
-  * SDK is when sending a command. The available steps are:
 
-  *
 
-  * - init: The command is being initialized, allowing you to do things like add
 
-  *   default options.
 
-  * - validate: The command is being validated before it is serialized
 
-  * - build: The command is being serialized into an HTTP request. A middleware
 
-  *   in this step MUST serialize an HTTP request and populate the "@request"
 
-  *   parameter of a command with the request such that it is available to
 
-  *   subsequent middleware.
 
-  * - sign: The request is being signed and prepared to be sent over the wire.
 
-  *
 
-  * Middleware can be registered with a name to allow you to easily add a
 
-  * middleware before or after another middleware by name. This also allows you
 
-  * to remove a middleware by name (in addition to removing by instance).
 
-  */
 
- class HandlerList implements \Countable
 
- {
 
-     const INIT = 'init';
 
-     const VALIDATE = 'validate';
 
-     const BUILD = 'build';
 
-     const SIGN = 'sign';
 
-     const ATTEMPT = 'attempt';
 
-     /** @var callable */
 
-     private $handler;
 
-     /** @var array */
 
-     private $named = [];
 
-     /** @var array */
 
-     private $sorted;
 
-     /** @var callable|null */
 
-     private $interposeFn;
 
-     /** @var array Steps (in reverse order) */
 
-     private $steps = [
 
-         self::ATTEMPT  => [],
 
-         self::SIGN     => [],
 
-         self::BUILD    => [],
 
-         self::VALIDATE => [],
 
-         self::INIT     => [],
 
-     ];
 
-     /**
 
-      * @param callable $handler HTTP handler.
 
-      */
 
-     public function __construct(callable $handler = null)
 
-     {
 
-         $this->handler = $handler;
 
-     }
 
-     /**
 
-      * Dumps a string representation of the list.
 
-      *
 
-      * @return string
 
-      */
 
-     public function __toString()
 
-     {
 
-         $str = '';
 
-         $i = 0;
 
-         foreach (array_reverse($this->steps) as $k => $step) {
 
-             foreach (array_reverse($step) as $j => $tuple) {
 
-                 $str .= "{$i}) Step: {$k}, ";
 
-                 if ($tuple[1]) {
 
-                     $str .= "Name: {$tuple[1]}, ";
 
-                 }
 
-                 $str .= "Function: " . $this->debugCallable($tuple[0]) . "\n";
 
-                 $i++;
 
-             }
 
-         }
 
-         if ($this->handler) {
 
-             $str .= "{$i}) Handler: " . $this->debugCallable($this->handler) . "\n";
 
-         }
 
-         return $str;
 
-     }
 
-     /**
 
-      * Set the HTTP handler that actually returns a response.
 
-      *
 
-      * @param callable $handler Function that accepts a request and array of
 
-      *                          options and returns a Promise.
 
-      */
 
-     public function setHandler(callable $handler)
 
-     {
 
-         $this->handler = $handler;
 
-     }
 
-     /**
 
-      * Returns true if the builder has a handler.
 
-      *
 
-      * @return bool
 
-      */
 
-     public function hasHandler()
 
-     {
 
-         return (bool) $this->handler;
 
-     }
 
-     /**
 
-      * Append a middleware to the init step.
 
-      *
 
-      * @param callable $middleware Middleware function to add.
 
-      * @param string   $name       Name of the middleware.
 
-      */
 
-     public function appendInit(callable $middleware, $name = null)
 
-     {
 
-         $this->add(self::INIT, $name, $middleware);
 
-     }
 
-     /**
 
-      * Prepend a middleware to the init step.
 
-      *
 
-      * @param callable $middleware Middleware function to add.
 
-      * @param string   $name       Name of the middleware.
 
-      */
 
-     public function prependInit(callable $middleware, $name = null)
 
-     {
 
-         $this->add(self::INIT, $name, $middleware, true);
 
-     }
 
-     /**
 
-      * Append a middleware to the validate step.
 
-      *
 
-      * @param callable $middleware Middleware function to add.
 
-      * @param string   $name       Name of the middleware.
 
-      */
 
-     public function appendValidate(callable $middleware, $name = null)
 
-     {
 
-         $this->add(self::VALIDATE, $name, $middleware);
 
-     }
 
-     /**
 
-      * Prepend a middleware to the validate step.
 
-      *
 
-      * @param callable $middleware Middleware function to add.
 
-      * @param string   $name       Name of the middleware.
 
-      */
 
-     public function prependValidate(callable $middleware, $name = null)
 
-     {
 
-         $this->add(self::VALIDATE, $name, $middleware, true);
 
-     }
 
-     /**
 
-      * Append a middleware to the build step.
 
-      *
 
-      * @param callable $middleware Middleware function to add.
 
-      * @param string   $name       Name of the middleware.
 
-      */
 
-     public function appendBuild(callable $middleware, $name = null)
 
-     {
 
-         $this->add(self::BUILD, $name, $middleware);
 
-     }
 
-     /**
 
-      * Prepend a middleware to the build step.
 
-      *
 
-      * @param callable $middleware Middleware function to add.
 
-      * @param string   $name       Name of the middleware.
 
-      */
 
-     public function prependBuild(callable $middleware, $name = null)
 
-     {
 
-         $this->add(self::BUILD, $name, $middleware, true);
 
-     }
 
-     /**
 
-      * Append a middleware to the sign step.
 
-      *
 
-      * @param callable $middleware Middleware function to add.
 
-      * @param string   $name       Name of the middleware.
 
-      */
 
-     public function appendSign(callable $middleware, $name = null)
 
-     {
 
-         $this->add(self::SIGN, $name, $middleware);
 
-     }
 
-     /**
 
-      * Prepend a middleware to the sign step.
 
-      *
 
-      * @param callable $middleware Middleware function to add.
 
-      * @param string   $name       Name of the middleware.
 
-      */
 
-     public function prependSign(callable $middleware, $name = null)
 
-     {
 
-         $this->add(self::SIGN, $name, $middleware, true);
 
-     }
 
-     /**
 
-      * Append a middleware to the attempt step.
 
-      *
 
-      * @param callable $middleware Middleware function to add.
 
-      * @param string   $name       Name of the middleware.
 
-      */
 
-     public function appendAttempt(callable $middleware, $name = null)
 
-     {
 
-         $this->add(self::ATTEMPT, $name, $middleware);
 
-     }
 
-     /**
 
-      * Prepend a middleware to the attempt step.
 
-      *
 
-      * @param callable $middleware Middleware function to add.
 
-      * @param string   $name       Name of the middleware.
 
-      */
 
-     public function prependAttempt(callable $middleware, $name = null)
 
-     {
 
-         $this->add(self::ATTEMPT, $name, $middleware, true);
 
-     }
 
-     /**
 
-      * Add a middleware before the given middleware by name.
 
-      *
 
-      * @param string|callable $findName   Add before this
 
-      * @param string          $withName   Optional name to give the middleware
 
-      * @param callable        $middleware Middleware to add.
 
-      */
 
-     public function before($findName, $withName, callable $middleware)
 
-     {
 
-         $this->splice($findName, $withName, $middleware, true);
 
-     }
 
-     /**
 
-      * Add a middleware after the given middleware by name.
 
-      *
 
-      * @param string|callable $findName   Add after this
 
-      * @param string          $withName   Optional name to give the middleware
 
-      * @param callable        $middleware Middleware to add.
 
-      */
 
-     public function after($findName, $withName, callable $middleware)
 
-     {
 
-         $this->splice($findName, $withName, $middleware, false);
 
-     }
 
-     /**
 
-      * Remove a middleware by name or by instance from the list.
 
-      *
 
-      * @param string|callable $nameOrInstance Middleware to remove.
 
-      */
 
-     public function remove($nameOrInstance)
 
-     {
 
-         if (is_callable($nameOrInstance)) {
 
-             $this->removeByInstance($nameOrInstance);
 
-         } elseif (is_string($nameOrInstance)) {
 
-             $this->removeByName($nameOrInstance);
 
-         }
 
-     }
 
-     /**
 
-      * Interpose a function between each middleware (e.g., allowing for a trace
 
-      * through the middleware layers).
 
-      *
 
-      * The interpose function is a function that accepts a "step" argument as a
 
-      * string and a "name" argument string. This function must then return a
 
-      * function that accepts the next handler in the list. This function must
 
-      * then return a function that accepts a CommandInterface and optional
 
-      * RequestInterface and returns a promise that is fulfilled with an
 
-      * Aws\ResultInterface or rejected with an Aws\Exception\AwsException
 
-      * object.
 
-      *
 
-      * @param callable|null $fn Pass null to remove any previously set function
 
-      */
 
-     public function interpose(callable $fn = null)
 
-     {
 
-         $this->sorted = null;
 
-         $this->interposeFn = $fn;
 
-     }
 
-     /**
 
-      * Compose the middleware and handler into a single callable function.
 
-      *
 
-      * @return callable
 
-      */
 
-     public function resolve()
 
-     {
 
-         if (!($prev = $this->handler)) {
 
-             throw new \LogicException('No handler has been specified');
 
-         }
 
-         if ($this->sorted === null) {
 
-             $this->sortMiddleware();
 
-         }
 
-         foreach ($this->sorted as $fn) {
 
-             $prev = $fn($prev);
 
-         }
 
-         return $prev;
 
-     }
 
-     /**
 
-      * @return int
 
-      */
 
-     #[\ReturnTypeWillChange]
 
-     public function count()
 
-     {
 
-         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]);
 
-     }
 
-     /**
 
-      * Splices a function into the middleware list at a specific position.
 
-      *
 
-      * @param          $findName
 
-      * @param          $withName
 
-      * @param callable $middleware
 
-      * @param          $before
 
-      */
 
-     private function splice($findName, $withName, callable $middleware, $before)
 
-     {
 
-         if (!isset($this->named[$findName])) {
 
-             throw new \InvalidArgumentException("$findName not found");
 
-         }
 
-         $idx = $this->sorted = null;
 
-         $step = $this->named[$findName];
 
-         if ($withName) {
 
-             $this->named[$withName] = $step;
 
-         }
 
-         foreach ($this->steps[$step] as $i => $tuple) {
 
-             if ($tuple[1] === $findName) {
 
-                 $idx = $i;
 
-                 break;
 
-             }
 
-         }
 
-         $replacement = $before
 
-             ? [$this->steps[$step][$idx], [$middleware, $withName]]
 
-             : [[$middleware, $withName], $this->steps[$step][$idx]];
 
-         array_splice($this->steps[$step], $idx, 1, $replacement);
 
-     }
 
-     /**
 
-      * Provides a debug string for a given callable.
 
-      *
 
-      * @param array|callable $fn Function to write as a string.
 
-      *
 
-      * @return string
 
-      */
 
-     private function debugCallable($fn)
 
-     {
 
-         if (is_string($fn)) {
 
-             return "callable({$fn})";
 
-         }
 
-         if (is_array($fn)) {
 
-             $ele = is_string($fn[0]) ? $fn[0] : get_class($fn[0]);
 
-             return "callable(['{$ele}', '{$fn[1]}'])";
 
-         }
 
-         return 'callable(' . spl_object_hash($fn) . ')';
 
-     }
 
-     /**
 
-      * Sort the middleware, and interpose if needed in the sorted list.
 
-      */
 
-     private function sortMiddleware()
 
-     {
 
-         $this->sorted = [];
 
-         if (!$this->interposeFn) {
 
-             foreach ($this->steps as $step) {
 
-                 foreach ($step as $fn) {
 
-                     $this->sorted[] = $fn[0];
 
-                 }
 
-             }
 
-             return;
 
-         }
 
-         $ifn = $this->interposeFn;
 
-         // Interpose the interposeFn into the handler stack.
 
-         foreach ($this->steps as $stepName => $step) {
 
-             foreach ($step as $fn) {
 
-                 $this->sorted[] = $ifn($stepName, $fn[1]);
 
-                 $this->sorted[] = $fn[0];
 
-             }
 
-         }
 
-     }
 
-     private function removeByName($name)
 
-     {
 
-         if (!isset($this->named[$name])) {
 
-             return;
 
-         }
 
-         $this->sorted = null;
 
-         $step = $this->named[$name];
 
-         $this->steps[$step] = array_values(
 
-             array_filter(
 
-                 $this->steps[$step],
 
-                 function ($tuple) use ($name) {
 
-                     return $tuple[1] !== $name;
 
-                 }
 
-             )
 
-         );
 
-     }
 
-     private function removeByInstance(callable $fn)
 
-     {
 
-         foreach ($this->steps as $k => $step) {
 
-             foreach ($step as $j => $tuple) {
 
-                 if ($tuple[0] === $fn) {
 
-                     $this->sorted = null;
 
-                     unset($this->named[$this->steps[$k][$j][1]]);
 
-                     unset($this->steps[$k][$j]);
 
-                 }
 
-             }
 
-         }
 
-     }
 
-     /**
 
-      * Add a middleware to a step.
 
-      *
 
-      * @param string   $step       Middleware step.
 
-      * @param string   $name       Middleware name.
 
-      * @param callable $middleware Middleware function to add.
 
-      * @param bool     $prepend    Prepend instead of append.
 
-      */
 
-     private function add($step, $name, callable $middleware, $prepend = false)
 
-     {
 
-         $this->sorted = null;
 
-         if ($prepend) {
 
-             $this->steps[$step][] = [$middleware, $name];
 
-         } else {
 
-             array_unshift($this->steps[$step], [$middleware, $name]);
 
-         }
 
-         if ($name) {
 
-             $this->named[$name] = $step;
 
-         }
 
-     }
 
- }
 
 
  |