diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -106,6 +106,7 @@ 'PhutilAuthAdapterOAuthJIRA' => 'auth/PhutilAuthAdapterOAuthJIRA.php', 'PhutilAuthAdapterOAuthTwitch' => 'auth/PhutilAuthAdapterOAuthTwitch.php', 'PhutilAuthAdapterOAuthTwitter' => 'auth/PhutilAuthAdapterOAuthTwitter.php', + 'PhutilAuthAdapterOAuthWordPress' => 'auth/PhutilAuthAdapterOAuthWordPress.php', 'PhutilAuthAdapterPersona' => 'auth/PhutilAuthAdapterPersona.php', 'PhutilAuthConfigurationException' => 'auth/exception/PhutilAuthConfigurationException.php', 'PhutilAuthCredentialException' => 'auth/exception/PhutilAuthCredentialException.php', @@ -308,6 +309,7 @@ 'PhutilURITestCase' => 'parser/__tests__/PhutilURITestCase.php', 'PhutilUTF8TestCase' => 'utils/__tests__/PhutilUTF8TestCase.php', 'PhutilUtilsTestCase' => 'utils/__tests__/PhutilUtilsTestCase.php', + 'PhutilWordPressFuture' => 'future/wordpress/PhutilWordPressFuture.php', 'PhutilXHPASTSyntaxHighlighter' => 'markup/syntax/highlighter/PhutilXHPASTSyntaxHighlighter.php', 'PhutilXHPASTSyntaxHighlighterFuture' => 'markup/syntax/highlighter/xhpast/PhutilXHPASTSyntaxHighlighterFuture.php', 'PhutilXHPASTSyntaxHighlighterTestCase' => 'markup/syntax/highlighter/__tests__/PhutilXHPASTSyntaxHighlighterTestCase.php', @@ -525,6 +527,7 @@ 'PhutilAuthAdapterOAuthJIRA' => 'PhutilAuthAdapterOAuth1', 'PhutilAuthAdapterOAuthTwitch' => 'PhutilAuthAdapterOAuth', 'PhutilAuthAdapterOAuthTwitter' => 'PhutilAuthAdapterOAuth1', + 'PhutilAuthAdapterOAuthWordPress' => 'PhutilAuthAdapterOAuth', 'PhutilAuthAdapterPersona' => 'PhutilAuthAdapter', 'PhutilAuthConfigurationException' => 'PhutilAuthException', 'PhutilAuthCredentialException' => 'PhutilAuthException', diff --git a/src/auth/PhutilAuthAdapterOAuthWordPress.php b/src/auth/PhutilAuthAdapterOAuthWordPress.php new file mode 100644 --- /dev/null +++ b/src/auth/PhutilAuthAdapterOAuthWordPress.php @@ -0,0 +1,73 @@ +getOAuthAccountData('ID'); + } + + public function getAccountEmail() { + return $this->getOAuthAccountData('email'); + } + + public function getAccountName() { + return $this->getOAuthAccountData('username'); + } + + public function getAccountImageURI() { + return $this->getOAuthAccountData('avatar_URL'); + } + + public function getAccountURI() { + return $this->getOAuthAccountData('profile_URL'); + } + + public function getAccountRealName() { + return $this->getOAuthAccountData('display_name'); + } + + protected function getAuthenticateBaseURI() { + return 'https://public-api.wordpress.com/oauth2/authorize'; + } + + protected function getTokenBaseURI() { + return 'https://public-api.wordpress.com/oauth2/token'; + } + + public function getScope() { + return 'user_read'; + } + + public function getExtraAuthenticateParameters() { + return array( + 'response_type' => 'code', + 'blog_id' => 0, + ); + } + + public function getExtraTokenParameters() { + return array( + 'grant_type' => 'authorization_code', + ); + } + + protected function loadOAuthAccountData() { + return id(new PhutilWordPressFuture()) + ->setClientID($this->getClientID()) + ->setAccessToken($this->getAccessToken()) + ->setRawWordPressQuery('/me/') + ->resolve(); + } + +} diff --git a/src/future/wordpress/PhutilWordPressFuture.php b/src/future/wordpress/PhutilWordPressFuture.php new file mode 100644 --- /dev/null +++ b/src/future/wordpress/PhutilWordPressFuture.php @@ -0,0 +1,87 @@ +accessToken = $token; + return $this; + } + + public function setClientID($client_id) { + $this->clientID = $client_id; + return $this; + } + + public function setRawWordPressQuery($action, array $params = array()) { + $this->action = $action; + $this->params = $params; + return $this; + } + + public function setMethod($method) { + $this->method = $method; + return $this; + } + + protected function getProxiedFuture() { + if (!$this->future) { + $params = $this->params; + + if (!$this->action) { + throw new Exception("You must setRawWordPressQuery()!"); + } + + if (!$this->accessToken) { + throw new Exception("You must setAccessToken()!"); + } + + $uri = new PhutilURI('https://public-api.wordpress.com/'); + $uri->setPath('/rest/v1/'.ltrim($this->action, '/')); + + $future = new HTTPSFuture($uri); + $future->setData($this->params); + $future->setMethod($this->method); + + // NOTE: This is how WordPress.com REST API authenticates + $future->addHeader('Authorization', 'Bearer ' . $this->accessToken); + + $this->future = $future; + } + + return $this->future; + } + + protected function didReceiveResult($result) { + list($status, $body, $headers) = $result; + + if ($status->isError()) { + throw $status; + } + + $data = phutil_json_decode($body); + if (empty($data)) { + throw new Exception( + pht('Expected JSON response from WordPress.com, got: %s', $body)); + } + + if (idx($data, 'error')) { + $error = $data['error']; + throw new Exception( + pht('Received error from WordPress.com: %s', $error)); + } + + return $data; + } + +}