compatibility with 2.6.0 and 3.1.0
[m6w6/seekat] / lib / API / Call.php
1 <?php
2
3 namespace seekat\API;
4
5 use Exception;
6 use http\ {
7 Client,
8 Client\Request,
9 Client\Response
10 };
11 use React\Promise\Deferred;
12 use seekat\API;
13 use SplObserver;
14 use SplSubject;
15
16 class Call extends Deferred implements SplObserver
17 {
18 /**
19 * The endpoint
20 * @var API
21 */
22 private $api;
23
24 /**
25 * The HTTP client
26 * @var Client
27 */
28 private $client;
29
30 /**
31 * The executed request
32 * @var Request
33 */
34 private $request;
35
36 /**
37 * The promised response
38 * @var Response
39 */
40 private $response;
41
42 /**
43 * Create a deferred promise for the response of $request
44 *
45 * @param API $api The endpoint of the request
46 * @param Client $client The HTTP client to send the request
47 * @param Request $request The request to execute
48 */
49 function __construct(API $api, Client $client, Request $request) {
50 $this->api = $api;
51 $this->client = $client;
52 $this->request = $request;
53
54 parent::__construct(function($resolve, $reject) {
55 return $this->cancel($resolve, $reject);
56 });
57
58 $client->attach($this);
59 $client->enqueue($request, function(Response $response) {
60 $this->response = $response;
61 $this->complete(
62 [$this, "resolve"],
63 [$this, "reject"]
64 );
65 return true;
66 });
67 /* start off */
68 $client->once();
69 }
70
71 /**
72 * Progress observer
73 *
74 * Import the response's data on success and resolve the promise.
75 *
76 * @param SplSubject $client The observed HTTP client
77 * @param Request $request The request which generated the update
78 * @param object $progress The progress information
79 */
80 function update(SplSubject $client, Request $request = null, $progress = null) {
81 if ($request !== $this->request) {
82 return;
83 }
84
85 $this->notify((object) compact("client", "request", "progress"));
86 }
87
88 /**
89 * Completion callback
90 * @param callable $resolve
91 * @param callable $reject
92 */
93 private function complete(callable $resolve, callable $reject) {
94 $this->client->detach($this);
95
96 if ($this->response) {
97 try {
98 $resolve($this->api->import($this->response));
99 } catch (Exception $e) {
100 $reject($e);
101 }
102 } else {
103 $reject($this->client->getTransferInfo($this->request)->error);
104 }
105 }
106
107 /**
108 * Cancellation callback
109 * @param callable $resolve
110 * @param callable $reject
111 */
112 private function cancel(callable $resolve, callable $reject) {
113 /* did we finish in the meantime? */
114 if ($this->response) {
115 $this->complete($resolve, $reject);
116 } else {
117 $this->client->detach($this);
118 $this->client->dequeue($this->request);
119 $reject("Cancelled");
120 }
121 }
122 }