start refactoring to promises
authorMichael Wallner <mike@php.net>
Tue, 9 Jun 2015 09:42:39 +0000 (11:42 +0200)
committerMichael Wallner <mike@php.net>
Tue, 9 Jun 2015 09:42:39 +0000 (11:42 +0200)
app/Controller/Github/Callback.php
app/Github/API.php
app/Github/API/Call.php
app/Github/API/Users/ReadAuthToken.php
app/Github/API/Users/ReadAuthUser.php
composer.json
composer.lock

index e6429fcf7de18f57ef2b313fa2247224b75b7cc4..fefc12c77a2e9c76d628f80bba723f4ea74f42c2 100644 (file)
@@ -29,11 +29,33 @@ class Callback extends Github
                } else {
                        $this->github->fetchToken(
                                $this->app->getRequest()->getQuery("code"),
-                               $this->app->getRequest()->getQuery("state"),
-                               function($token) {
-                                       $this->github->setToken($token->access_token);
-                                       $this->github->readAuthUser($this->createUserCallback($token));
-                       })->send();
+                               $this->app->getRequest()->getQuery("state")
+                       )->then(function($result) {
+                               list($oauth) = $result;
+                               $this->github->setToken($oauth->access_token);
+                               return $this->github->readAuthUser()->then(function($result) use($oauth) {
+                                       list($user) = $result;
+                                       return [$oauth, $user];
+                               });
+                       })->then(function($result) {
+                               list($oauth, $user) = $result;
+                               $tx = $this->accounts->getConnection()->startTransaction();
+
+                               if (($cookie = $this->app->getRequest()->getCookie("account"))) {
+                                       $account = $this->accounts->find(["account=" => $cookie])->current();
+                               } elseif (!($account = $this->accounts->byOAuth("github", $oauth->access_token, $user->login))) {
+                                       $account = $this->accounts->createOAuthAccount("github", $oauth->access_token, $user->login);
+                               }
+                               $token = $account->updateToken("github", $oauth->access_token, $oauth);
+                               $owner = $account->updateOwner("github", $user->login, $user);
+
+                               $tx->commit();
+
+                               $this->login($account, $token, $owner);
+                       })->done();
+                       
+                       $this->github->getClient()->send();
+                       
                        if (isset($this->session->returnto)) {
                                $returnto = $this->session->returnto;
                                unset($this->session->returnto);
@@ -46,21 +68,4 @@ class Callback extends Github
                $this->app->display("github/callback");
        }
        
-       function createUserCallback($oauth) {
-               return function($user) use($oauth) {
-                       $tx = $this->accounts->getConnection()->startTransaction();
-
-                       if (($cookie = $this->app->getRequest()->getCookie("account"))) {
-                               $account = $this->accounts->find(["account=" => $cookie])->current();
-                       } elseif (!($account = $this->accounts->byOAuth("github", $oauth->access_token, $user->login))) {
-                               $account = $this->accounts->createOAuthAccount("github", $oauth->access_token, $user->login);
-                       }
-                       $token = $account->updateToken("github", $oauth->access_token, $oauth);
-                       $owner = $account->updateOwner("github", $user->login, $user);
-                       
-                       $tx->commit();
-                       
-                       $this->login($account, $token, $owner);
-               };
-       }
 }
index 9f37c4f2d56410af18e8a83ecd4769840625c64d..8e51489872e106c0ce83e6eb290bcca82a93c72f 100644 (file)
@@ -134,7 +134,7 @@ class API
                ], 0);
        }
 
-       function fetchToken($code, $state, callable $callback) {
+       function fetchToken($code, $state) {
                if (!$this->tokens->get("state", $orig_state, true)) {
                        if (isset($orig_state)) {
                                $this->logger->notice("State expired", $orig_state);
@@ -152,12 +152,12 @@ class API
                        "client_id" => $this->config->client->id,
                        "client_secret" => $this->config->client->secret,
                ]);
-               return $call($callback);
+               return $call();
        }
        
-       function readAuthUser(callable $callback) {
+       function readAuthUser() {
                $call = new API\Users\ReadAuthUser($this);
-               return $call($callback);
+               return $call();
        }
 
        function listRepos($page, callable $callback) {
index 22a69516e3f7fb60d466e3eac46b1522e6e13122..0e8bd62583b00eda3e9a16bc739427f993881ad3 100644 (file)
@@ -4,10 +4,13 @@ namespace app\Github\API;
 
 use app\Github\API;
 use app\Github\Storage\Item;
+use http\Client\Response;
 use http\QueryString;
 use http\Url;
 use merry\Config;
 
+use React\Promise;
+
 abstract class Call
 {
        /**
@@ -41,9 +44,19 @@ abstract class Call
        protected $result;
        
        /**
-        * Queue this call to the API client
+        * @var \React\Promise\Deferred
         */
-       abstract function enqueue(callable $callback);
+       protected $deferred;
+       
+       /**
+        * @return Request
+        */
+       abstract protected function request();
+       
+       /**
+        * @return array
+        */
+       abstract protected function response(Response $response);
        
        /**
         * @param API $api
@@ -53,6 +66,7 @@ abstract class Call
                $this->api = $api;
                $this->config = $this->api->getConfig();
                $this->url = new Url($this->config->api->url, null, 0);
+               $this->deferred = new Promise\Deferred;
                
                if ($args) {
                        $this->args = $args;
@@ -62,13 +76,26 @@ abstract class Call
                }
        }
        
-       function __invoke(callable $callback) {
+       /**
+        * @return \React\Promise\Promise
+        */
+       function __invoke() {
                if ($this->readFromCache($this->result)) {
-                       call_user_func_array($callback, $this->result);
+                       return new Promise\FulfilledPromise($this->result);
                } else {
-                       $this->enqueue($callback);
+                       $this->api->getClient()->enqueue(
+                               $this->request(),
+                               function($response) {
+                                       try {
+                                               $this->deferred->resolve($this->response($response));
+                                       } catch (\Exception $e) {
+                                               $this->deferred->reject($e);
+                                       }
+                                       return true;
+                               }
+                       );
+                       return $this->deferred->promise();
                }
-               return $this;
        }
        
        /**
index e167eef40e5bd3341b0e1c7939793229e3103dd6..5959e3d8b3bca4a1ad3e78e3e9c014380b154904 100644 (file)
@@ -5,23 +5,24 @@ namespace app\Github\API\Users;
 use app\Github\API\Call;
 use app\Github\Exception\RequestException;
 use http\Client\Request;
+use http\Client\Response;
 use http\QueryString;
 
 class ReadAuthToken extends Call
 {
-       function enqueue(callable $callback) {
+       protected function request() {
                $request = new Request("POST", "https://github.com/login/oauth/access_token", [
                        "Accept" => "application/json",
                ]);
                $request->getBody()->append(new QueryString($this->args));
-               $this->api->getClient()->enqueue($request, function($response) use($callback) {
-                       if ($response->getResponseCode() >= 400 || null === ($json = json_decode($response->getBody()))) {
-                               throw new RequestException($response);
-                       }
-                       $this->result = [$json];
-                       $callback($json);
-                       return true;
-               });
+               return $request;
+       }
+       
+       protected function response(Response $response) {
+               if ($response->getResponseCode() >= 400 || null === ($json = json_decode($response->getBody()))) {
+                       throw new RequestException($response);
+               }
+               return $json;
        }
        
        function getCacheKey() {
index b5c4fa92b78382c66a2052eedd3f6927e18d1160..01bd78c09ba705f4dea732e83a8f878b00220b83 100644 (file)
@@ -5,23 +5,24 @@ namespace app\Github\API\Users;
 use app\Github\API\Call;
 use app\Github\Exception\RequestException;
 use http\Client\Request;
+use http\Client\Response;
 
 class ReadAuthUser extends Call
 {
-       function enqueue(callable $callback) {
+       function request() {
                $url = $this->url->mod("./user");
                $request = new Request("GET", $url, [
                        "Authorization" => "token ". $this->api->getToken(),
                        "Accept" => $this->config->api->accept,
                ]);
-               $this->api->getClient()->enqueue($request, function($response) use($callback) {
-                       if ($response->getResponseCode() >= 400 || null === ($json = json_decode($response->getBody()))) {
-                               throw new RequestException($response);
-                       }
-                       $this->result = [$json];
-                       $this->saveToCache($this->result);
-                       $callback($json);
-                       return true;
-               });
+               return $request;
+       }
+       
+       function response(Response $response) {
+               if ($response->getResponseCode() >= 400 || null === ($json = json_decode($response->getBody()))) {
+                       throw new RequestException($response);
+               }
+               $this->saveToCache([$json]);
+               return [$json];
        }
 }
index e456abe4fb3c401a014ffbd23d7f7ae47baa8635..6917945f27e07b21efce5a1a434888f35b2830fb 100644 (file)
@@ -25,6 +25,7 @@
                "rdlowrey/auryn": "dev-master",
                "m6w6/pharext.wiki": "dev-master",
                "m6w6/pq-gateway": "~2.1",
-               "monolog/monolog": "^1.13"
+               "monolog/monolog": "^1.13",
+               "react/promise": "^2.2"
        }
 }
index 4efa5ae3028af63e7afeae39a09de6c1017df478..e7d8ff2285f131891c43d736f848d805f6c30f98 100644 (file)
@@ -4,7 +4,7 @@
         "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "dd47dcfb975d0ad4b92b940fc58e1eaf",
+    "hash": "677e6adb8d6fb297c9c04630b5fc2f61",
     "packages": [
         {
             "name": "league/plates",
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/rdlowrey/Auryn/zipball/d0d875868e1d7d241983c88252c07965a65224c1",
+                "url": "https://api.github.com/repos/rdlowrey/Auryn/zipball/b57a5046cfcefb0cde7fc86f9915e54aa7196cba",
                 "reference": "d0d875868e1d7d241983c88252c07965a65224c1",
                 "shasum": ""
             },
                 "ioc"
             ],
             "time": "2015-05-17 18:29:19"
+        },
+        {
+            "name": "react/promise",
+            "version": "v2.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/reactphp/promise.git",
+                "reference": "365fcee430dfa4ace1fbc75737ca60ceea7eeeef"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/reactphp/promise/zipball/365fcee430dfa4ace1fbc75737ca60ceea7eeeef",
+                "reference": "365fcee430dfa4ace1fbc75737ca60ceea7eeeef",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.4.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "React\\Promise\\": "src/"
+                },
+                "files": [
+                    "src/functions_include.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jan Sorgalla",
+                    "email": "jsorgalla@googlemail.com"
+                }
+            ],
+            "description": "A lightweight implementation of CommonJS Promises/A for PHP",
+            "time": "2014-12-30 13:32:42"
         }
     ],
     "packages-dev": [],