refactor
[m6w6/seekat] / lib / API / Call.php
index 26a52ee0995fbff2807d3e4ab850ca97f157eea9..d84a24c673f71e438d2a5bb60cb14fceb28124aa 100644 (file)
 
 namespace seekat\API;
 
-use Exception;
-use http\ {
-       Client,
-       Client\Request,
-       Client\Response
-};
-use React\Promise\Deferred;
+use http\Url;
+use React\Promise\ExtendedPromiseInterface;
 use seekat\API;
-use SplObserver;
-use SplSubject;
+use seekat\Exception;
 
-class Call extends Deferred implements SplObserver
+class Call
 {
        /**
-        * The endpoint
         * @var API
         */
        private $api;
 
        /**
-        * The HTTP client
-        * @var Client
+        * @var string
         */
-       private $client;
+       private $call;
 
-       /**
-        * The executed request
-        * @var Request
-        */
-       private $request;
-
-       /**
-        * The promised response
-        * @var Response
-        */
-       private $response;
-
-       /**
-        * Create a deferred promise for the response of $request
-        *
-        * @param API $api The endpoint of the request
-        * @param Client $client The HTTP client to send the request
-        * @param Request $request The request to execute
-        */
-       function __construct(API $api, Client $client, Request $request) {
+       function __construct(API $api, string $call) {
                $this->api = $api;
-               $this->client = $client;
-               $this->request = $request;
-
-               parent::__construct(function($resolve, $reject) {
-                       return $this->cancel($resolve, $reject);
-               });
-
-               $client->attach($this);
-               $client->enqueue($request, function(Response $response) {
-                       $this->response = $response;
-                       $this->complete(
-                               [$this, "resolve"],
-                               [$this, "reject"]
-                       );
-                       return true;
-               });
-               /* start off */
-               $client->once();
+               $this->call = $call;
        }
 
-       /**
-        * Progress observer
-        *
-        * Import the response's data on success and resolve the promise.
-        *
-        * @param SplSubject $client The observed HTTP client
-        * @param Request $request The request which generated the update
-        * @param object $progress The progress information
-        */
-       function update(SplSubject $client, Request $request = null, $progress = null) {
-               if ($request !== $this->request) {
-                       return;
-               }
+       function __invoke(array $args) : ExtendedPromiseInterface {
+               $promise = $this->api->{$this->call}->get(...$args);
 
-               $this->notify((object) compact("client", "request", "progress"));
-       }
+               /* fetch resource, unless already localized, and try for {$method}_url */
+               if (!$this->api->exists($this->call)) {
+                       $promise = $promise->otherwise(function ($error) use($args) {
+                               if ($this->api->exists($this->call."_url", $url)) {
+                                       $url = new Url(uri_template($url, (array)current($args)));
+                                       return $this->api->withUrl($url)->get(...$args);
+                               }
 
-       /**
-        * Completion callback
-        * @param callable $resolve
-        * @param callable $reject
-        */
-       private function complete(callable $resolve, callable $reject) {
-               $this->client->detach($this);
+                               $message = Exception\message($error);
+                               $this->api->getLogger()->error("call($this->call): " . $message, [
+                                       "url" => (string) $this->api->getUrl()
+                               ]);
 
-               if ($this->response) {
-                       try {
-                               $resolve($this->api->import($this->response));
-                       } catch (Exception $e) {
-                               $reject($e);
-                       }
-               } else {
-                       $reject($this->client->getTransferInfo($this->request)->error);
+                               throw $error;
+                       });
                }
-       }
 
-       /**
-        * Cancellation callback
-        * @param callable $resolve
-        * @param callable $reject
-        */
-       private function cancel(callable $resolve, callable $reject) {
-               /* did we finish in the meantime? */
-               if ($this->response) {
-                       $this->complete($resolve, $reject);
-               } else {
-                       $this->client->detach($this);
-                       $this->client->dequeue($this->request);
-                       $reject("Cancelled");
-               }
+               return $promise;
        }
 }