Chris@0
|
1 <?php
|
Chris@0
|
2 namespace GuzzleHttp\Handler;
|
Chris@0
|
3
|
Chris@0
|
4 use GuzzleHttp\Exception\RequestException;
|
Chris@0
|
5 use GuzzleHttp\HandlerStack;
|
Chris@0
|
6 use GuzzleHttp\Promise\PromiseInterface;
|
Chris@0
|
7 use GuzzleHttp\Promise\RejectedPromise;
|
Chris@0
|
8 use GuzzleHttp\TransferStats;
|
Chris@0
|
9 use Psr\Http\Message\RequestInterface;
|
Chris@0
|
10 use Psr\Http\Message\ResponseInterface;
|
Chris@0
|
11
|
Chris@0
|
12 /**
|
Chris@0
|
13 * Handler that returns responses or throw exceptions from a queue.
|
Chris@0
|
14 */
|
Chris@0
|
15 class MockHandler implements \Countable
|
Chris@0
|
16 {
|
Chris@0
|
17 private $queue = [];
|
Chris@0
|
18 private $lastRequest;
|
Chris@0
|
19 private $lastOptions;
|
Chris@0
|
20 private $onFulfilled;
|
Chris@0
|
21 private $onRejected;
|
Chris@0
|
22
|
Chris@0
|
23 /**
|
Chris@0
|
24 * Creates a new MockHandler that uses the default handler stack list of
|
Chris@0
|
25 * middlewares.
|
Chris@0
|
26 *
|
Chris@0
|
27 * @param array $queue Array of responses, callables, or exceptions.
|
Chris@0
|
28 * @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
Chris@0
|
29 * @param callable $onRejected Callback to invoke when the return value is rejected.
|
Chris@0
|
30 *
|
Chris@0
|
31 * @return HandlerStack
|
Chris@0
|
32 */
|
Chris@0
|
33 public static function createWithMiddleware(
|
Chris@0
|
34 array $queue = null,
|
Chris@0
|
35 callable $onFulfilled = null,
|
Chris@0
|
36 callable $onRejected = null
|
Chris@0
|
37 ) {
|
Chris@0
|
38 return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
|
Chris@0
|
39 }
|
Chris@0
|
40
|
Chris@0
|
41 /**
|
Chris@0
|
42 * The passed in value must be an array of
|
Chris@0
|
43 * {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
|
Chris@0
|
44 * callables, or Promises.
|
Chris@0
|
45 *
|
Chris@0
|
46 * @param array $queue
|
Chris@0
|
47 * @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
|
Chris@0
|
48 * @param callable $onRejected Callback to invoke when the return value is rejected.
|
Chris@0
|
49 */
|
Chris@0
|
50 public function __construct(
|
Chris@0
|
51 array $queue = null,
|
Chris@0
|
52 callable $onFulfilled = null,
|
Chris@0
|
53 callable $onRejected = null
|
Chris@0
|
54 ) {
|
Chris@0
|
55 $this->onFulfilled = $onFulfilled;
|
Chris@0
|
56 $this->onRejected = $onRejected;
|
Chris@0
|
57
|
Chris@0
|
58 if ($queue) {
|
Chris@0
|
59 call_user_func_array([$this, 'append'], $queue);
|
Chris@0
|
60 }
|
Chris@0
|
61 }
|
Chris@0
|
62
|
Chris@0
|
63 public function __invoke(RequestInterface $request, array $options)
|
Chris@0
|
64 {
|
Chris@0
|
65 if (!$this->queue) {
|
Chris@0
|
66 throw new \OutOfBoundsException('Mock queue is empty');
|
Chris@0
|
67 }
|
Chris@0
|
68
|
Chris@0
|
69 if (isset($options['delay'])) {
|
Chris@0
|
70 usleep($options['delay'] * 1000);
|
Chris@0
|
71 }
|
Chris@0
|
72
|
Chris@0
|
73 $this->lastRequest = $request;
|
Chris@0
|
74 $this->lastOptions = $options;
|
Chris@0
|
75 $response = array_shift($this->queue);
|
Chris@0
|
76
|
Chris@0
|
77 if (isset($options['on_headers'])) {
|
Chris@0
|
78 if (!is_callable($options['on_headers'])) {
|
Chris@0
|
79 throw new \InvalidArgumentException('on_headers must be callable');
|
Chris@0
|
80 }
|
Chris@0
|
81 try {
|
Chris@0
|
82 $options['on_headers']($response);
|
Chris@0
|
83 } catch (\Exception $e) {
|
Chris@0
|
84 $msg = 'An error was encountered during the on_headers event';
|
Chris@0
|
85 $response = new RequestException($msg, $request, $response, $e);
|
Chris@0
|
86 }
|
Chris@0
|
87 }
|
Chris@0
|
88
|
Chris@0
|
89 if (is_callable($response)) {
|
Chris@0
|
90 $response = call_user_func($response, $request, $options);
|
Chris@0
|
91 }
|
Chris@0
|
92
|
Chris@0
|
93 $response = $response instanceof \Exception
|
Chris@0
|
94 ? \GuzzleHttp\Promise\rejection_for($response)
|
Chris@0
|
95 : \GuzzleHttp\Promise\promise_for($response);
|
Chris@0
|
96
|
Chris@0
|
97 return $response->then(
|
Chris@0
|
98 function ($value) use ($request, $options) {
|
Chris@0
|
99 $this->invokeStats($request, $options, $value);
|
Chris@0
|
100 if ($this->onFulfilled) {
|
Chris@0
|
101 call_user_func($this->onFulfilled, $value);
|
Chris@0
|
102 }
|
Chris@0
|
103 if (isset($options['sink'])) {
|
Chris@0
|
104 $contents = (string) $value->getBody();
|
Chris@0
|
105 $sink = $options['sink'];
|
Chris@0
|
106
|
Chris@0
|
107 if (is_resource($sink)) {
|
Chris@0
|
108 fwrite($sink, $contents);
|
Chris@0
|
109 } elseif (is_string($sink)) {
|
Chris@0
|
110 file_put_contents($sink, $contents);
|
Chris@0
|
111 } elseif ($sink instanceof \Psr\Http\Message\StreamInterface) {
|
Chris@0
|
112 $sink->write($contents);
|
Chris@0
|
113 }
|
Chris@0
|
114 }
|
Chris@0
|
115
|
Chris@0
|
116 return $value;
|
Chris@0
|
117 },
|
Chris@0
|
118 function ($reason) use ($request, $options) {
|
Chris@0
|
119 $this->invokeStats($request, $options, null, $reason);
|
Chris@0
|
120 if ($this->onRejected) {
|
Chris@0
|
121 call_user_func($this->onRejected, $reason);
|
Chris@0
|
122 }
|
Chris@0
|
123 return \GuzzleHttp\Promise\rejection_for($reason);
|
Chris@0
|
124 }
|
Chris@0
|
125 );
|
Chris@0
|
126 }
|
Chris@0
|
127
|
Chris@0
|
128 /**
|
Chris@0
|
129 * Adds one or more variadic requests, exceptions, callables, or promises
|
Chris@0
|
130 * to the queue.
|
Chris@0
|
131 */
|
Chris@0
|
132 public function append()
|
Chris@0
|
133 {
|
Chris@0
|
134 foreach (func_get_args() as $value) {
|
Chris@0
|
135 if ($value instanceof ResponseInterface
|
Chris@0
|
136 || $value instanceof \Exception
|
Chris@0
|
137 || $value instanceof PromiseInterface
|
Chris@0
|
138 || is_callable($value)
|
Chris@0
|
139 ) {
|
Chris@0
|
140 $this->queue[] = $value;
|
Chris@0
|
141 } else {
|
Chris@0
|
142 throw new \InvalidArgumentException('Expected a response or '
|
Chris@0
|
143 . 'exception. Found ' . \GuzzleHttp\describe_type($value));
|
Chris@0
|
144 }
|
Chris@0
|
145 }
|
Chris@0
|
146 }
|
Chris@0
|
147
|
Chris@0
|
148 /**
|
Chris@0
|
149 * Get the last received request.
|
Chris@0
|
150 *
|
Chris@0
|
151 * @return RequestInterface
|
Chris@0
|
152 */
|
Chris@0
|
153 public function getLastRequest()
|
Chris@0
|
154 {
|
Chris@0
|
155 return $this->lastRequest;
|
Chris@0
|
156 }
|
Chris@0
|
157
|
Chris@0
|
158 /**
|
Chris@0
|
159 * Get the last received request options.
|
Chris@0
|
160 *
|
Chris@0
|
161 * @return array
|
Chris@0
|
162 */
|
Chris@0
|
163 public function getLastOptions()
|
Chris@0
|
164 {
|
Chris@0
|
165 return $this->lastOptions;
|
Chris@0
|
166 }
|
Chris@0
|
167
|
Chris@0
|
168 /**
|
Chris@0
|
169 * Returns the number of remaining items in the queue.
|
Chris@0
|
170 *
|
Chris@0
|
171 * @return int
|
Chris@0
|
172 */
|
Chris@0
|
173 public function count()
|
Chris@0
|
174 {
|
Chris@0
|
175 return count($this->queue);
|
Chris@0
|
176 }
|
Chris@0
|
177
|
Chris@0
|
178 private function invokeStats(
|
Chris@0
|
179 RequestInterface $request,
|
Chris@0
|
180 array $options,
|
Chris@0
|
181 ResponseInterface $response = null,
|
Chris@0
|
182 $reason = null
|
Chris@0
|
183 ) {
|
Chris@0
|
184 if (isset($options['on_stats'])) {
|
Chris@0
|
185 $stats = new TransferStats($request, $response, 0, $reason);
|
Chris@0
|
186 call_user_func($options['on_stats'], $stats);
|
Chris@0
|
187 }
|
Chris@0
|
188 }
|
Chris@0
|
189 }
|