| 
<?phpnamespace GuzzleHttp\Handler;
 
 use GuzzleHttp\HandlerStack;
 use GuzzleHttp\Promise\PromiseInterface;
 use GuzzleHttp\Promise\RejectedPromise;
 use GuzzleHttp\TransferStats;
 use Psr\Http\Message\RequestInterface;
 use Psr\Http\Message\ResponseInterface;
 
 /**
 * Handler that returns responses or throw exceptions from a queue.
 */
 class MockHandler implements \Countable
 {
 private $queue;
 private $lastRequest;
 private $lastOptions;
 private $onFulfilled;
 private $onRejected;
 
 /**
 * Creates a new MockHandler that uses the default handler stack list of
 * middlewares.
 *
 * @param array $queue Array of responses, callables, or exceptions.
 * @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
 * @param callable $onRejected  Callback to invoke when the return value is rejected.
 *
 * @return MockHandler
 */
 public static function createWithMiddleware(
 array $queue = null,
 callable $onFulfilled = null,
 callable $onRejected = null
 ) {
 return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
 }
 
 /**
 * The passed in value must be an array of
 * {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
 * callables, or Promises.
 *
 * @param array $queue
 * @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
 * @param callable $onRejected  Callback to invoke when the return value is rejected.
 */
 public function __construct(
 array $queue = null,
 callable $onFulfilled = null,
 callable $onRejected = null
 ) {
 $this->onFulfilled = $onFulfilled;
 $this->onRejected = $onRejected;
 
 if ($queue) {
 call_user_func_array([$this, 'append'], $queue);
 }
 }
 
 public function __invoke(RequestInterface $request, array $options)
 {
 if (!$this->queue) {
 throw new \OutOfBoundsException('Mock queue is empty');
 }
 
 if (isset($options['delay'])) {
 usleep($options['delay'] * 1000);
 }
 
 $this->lastRequest = $request;
 $this->lastOptions = $options;
 $response = array_shift($this->queue);
 
 if (is_callable($response)) {
 $response = $response($request, $options);
 }
 
 $response = $response instanceof \Exception
 ? new RejectedPromise($response)
 : \GuzzleHttp\Promise\promise_for($response);
 
 return $response->then(
 function ($value) use ($request, $options) {
 $this->invokeStats($request, $options, $value);
 if ($this->onFulfilled) {
 call_user_func($this->onFulfilled, $value);
 }
 if (isset($options['sink'])) {
 $contents = (string) $value->getBody();
 $sink = $options['sink'];
 
 if (is_resource($sink)) {
 fwrite($sink, $contents);
 } elseif (is_string($sink)) {
 file_put_contents($sink, $contents);
 } elseif ($sink instanceof \Psr\Http\Message\StreamInterface) {
 $sink->write($contents);
 }
 }
 
 return $value;
 },
 function ($reason) use ($request, $options) {
 $this->invokeStats($request, $options, null, $reason);
 if ($this->onRejected) {
 call_user_func($this->onRejected, $reason);
 }
 return new RejectedPromise($reason);
 }
 );
 }
 
 /**
 * Adds one or more variadic requests, exceptions, callables, or promises
 * to the queue.
 */
 public function append()
 {
 foreach (func_get_args() as $value) {
 if ($value instanceof ResponseInterface
 || $value instanceof \Exception
 || $value instanceof PromiseInterface
 || is_callable($value)
 ) {
 $this->queue[] = $value;
 } else {
 throw new \InvalidArgumentException('Expected a response or '
 . 'exception. Found ' . \GuzzleHttp\describe_type($value));
 }
 }
 }
 
 /**
 * Get the last received request.
 *
 * @return RequestInterface
 */
 public function getLastRequest()
 {
 return $this->lastRequest;
 }
 
 /**
 * Get the last received request options.
 *
 * @return RequestInterface
 */
 public function getLastOptions()
 {
 return $this->lastOptions;
 }
 
 /**
 * Returns the number of remaining items in the queue.
 *
 * @return int
 */
 public function count()
 {
 return count($this->queue);
 }
 
 private function invokeStats(
 RequestInterface $request,
 array $options,
 ResponseInterface $response = null,
 $reason = null
 ) {
 if (isset($options['on_stats'])) {
 $stats = new TransferStats($request, $response, 0, $reason);
 call_user_func($options['on_stats'], $stats);
 }
 }
 }
 
 |