diff options
author | Brion Vibber <brion@pobox.com> | 2010-09-27 17:26:14 -0700 |
---|---|---|
committer | Brion Vibber <brion@pobox.com> | 2010-09-27 17:26:14 -0700 |
commit | f0b39defb24bcc9c9e403ac66e7d6a1621a4bd18 (patch) | |
tree | 2997b756dce0e41ffc760fbf0763a161237cfe2a /plugins/YammerImport/lib/sn_yammerclient.php | |
parent | 87a12b7fcf85851918192375687081e8fc78e16b (diff) | |
parent | 0477101af7bda9d8e58f3315837a81fca17d06b4 (diff) |
Merge branch 'yammer' of gitorious.org:~brion/statusnet/brion-fixes into 0.9.x
Diffstat (limited to 'plugins/YammerImport/lib/sn_yammerclient.php')
-rw-r--r-- | plugins/YammerImport/lib/sn_yammerclient.php | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/plugins/YammerImport/lib/sn_yammerclient.php b/plugins/YammerImport/lib/sn_yammerclient.php new file mode 100644 index 000000000..5da1cc5e7 --- /dev/null +++ b/plugins/YammerImport/lib/sn_yammerclient.php @@ -0,0 +1,246 @@ +<?php +/* + * StatusNet - the distributed open-source microblogging tool + * Copyright (C) 2010, StatusNet, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Basic client class for Yammer's OAuth/JSON API. + * + * @package YammerImportPlugin + * @author Brion Vibber <brion@status.net> + */ +class SN_YammerClient +{ + protected $apiBase = "https://www.yammer.com"; + protected $consumerKey, $consumerSecret; + protected $token, $tokenSecret, $verifier; + + public function __construct($consumerKey, $consumerSecret, $token=null, $tokenSecret=null) + { + $this->consumerKey = $consumerKey; + $this->consumerSecret = $consumerSecret; + $this->token = $token; + $this->tokenSecret = $tokenSecret; + } + + /** + * Make an HTTP GET request with OAuth headers and return an HTTPResponse + * with the returned body and codes. + * + * @param string $url + * @return HTTPResponse + * + * @throws Exception on low-level network error + */ + protected function httpGet($url) + { + $headers = array('Authorization: ' . $this->authHeader()); + + $client = HTTPClient::start(); + return $client->get($url, $headers); + } + + /** + * Make an HTTP GET request with OAuth headers and return the response body + * on success. + * + * @param string $url + * @return string + * + * @throws Exception on low-level network or HTTP error + */ + public function fetchUrl($url) + { + $response = $this->httpGet($url); + if ($response->isOk()) { + return $response->getBody(); + } else { + throw new Exception("Yammer API returned HTTP code " . $response->getStatus() . ': ' . $response->getBody()); + } + } + + /** + * Make an HTTP hit with OAuth headers and return the response body on success. + * + * @param string $path URL chunk for the API method + * @param array $params + * @return string + * + * @throws Exception on low-level network or HTTP error + */ + protected function fetchApi($path, $params=array()) + { + $url = $this->apiBase . '/' . $path; + if ($params) { + $url .= '?' . http_build_query($params, null, '&'); + } + return $this->fetchUrl($url); + } + + /** + * Hit the main Yammer API point and decode returned JSON data. + * + * @param string $method + * @param array $params + * @return array from JSON data + * + * @throws Exception for HTTP error or bad JSON return + */ + public function api($method, $params=array()) + { + $body = $this->fetchApi("api/v1/$method.json", $params); + $data = json_decode($body, true); + if ($data === null) { + common_log(LOG_ERR, "Invalid JSON response from Yammer API: " . $body); + throw new Exception("Invalid JSON response from Yammer API"); + } + return $data; + } + + /** + * Build an Authorization header value from the keys we have available. + */ + protected function authHeader() + { + // token + // token_secret + $params = array('realm' => '', + 'oauth_consumer_key' => $this->consumerKey, + 'oauth_signature_method' => 'PLAINTEXT', + 'oauth_timestamp' => time(), + 'oauth_nonce' => time(), + 'oauth_version' => '1.0'); + if ($this->token) { + $params['oauth_token'] = $this->token; + } + if ($this->tokenSecret) { + $params['oauth_signature'] = $this->consumerSecret . '&' . $this->tokenSecret; + } else { + $params['oauth_signature'] = $this->consumerSecret . '&'; + } + if ($this->verifier) { + $params['oauth_verifier'] = $this->verifier; + } + $parts = array_map(array($this, 'authHeaderChunk'), array_keys($params), array_values($params)); + return 'OAuth ' . implode(', ', $parts); + } + + /** + * Encode a key-value pair for use in an authentication header. + * + * @param string $key + * @param string $val + * @return string + */ + protected function authHeaderChunk($key, $val) + { + return urlencode($key) . '="' . urlencode($val) . '"'; + } + + /** + * Ask the Yammer server for a request token, which can be passed on + * to authorizeUrl() for the user to start the authentication process. + * + * @return array of oauth return data; should contain nice things + */ + public function requestToken() + { + if ($this->token || $this->tokenSecret) { + throw new Exception("Requesting a token, but already set up with a token"); + } + $data = $this->fetchApi('oauth/request_token'); + $arr = array(); + parse_str($data, $arr); + return $arr; + } + + /** + * Get a final access token from the verifier/PIN code provided to + * the user from Yammer's auth pages. + * + * @return array of oauth return data; should contain nice things + */ + public function accessToken($verifier) + { + $this->verifier = $verifier; + $data = $this->fetchApi('oauth/access_token'); + $this->verifier = null; + $arr = array(); + parse_str($data, $arr); + return $arr; + } + + /** + * Give the URL to send users to to authorize a new app setup. + * + * @param string $token as returned from accessToken() + * @return string URL + */ + public function authorizeUrl($token) + { + return $this->apiBase . '/oauth/authorize?oauth_token=' . urlencode($token); + } + + /** + * High-level API hit: fetch all messages in the network (up to 20 at a time). + * Return data is the full JSON array returned, including meta and references + * sections. + * + * The matching messages themselves will be in the 'messages' item within. + * + * @param array $options optional set of additional params for the request. + * @return array + * + * @throws Exception on low-level or HTTP error + */ + public function messages($params=array()) + { + return $this->api('messages', $params); + } + + /** + * High-level API hit: fetch all users in the network (up to 50 at a time). + * Return data is the full JSON array returned, listing user items. + * + * The matching messages themselves will be in the 'users' item within. + * + * @param array $options optional set of additional params for the request. + * @return array of JSON-sourced user data arrays + * + * @throws Exception on low-level or HTTP error + */ + public function users($params=array()) + { + return $this->api('users', $params); + } + + /** + * High-level API hit: fetch all groups in the network (up to 20 at a time). + * Return data is the full JSON array returned, listing user items. + * + * The matching messages themselves will be in the 'users' item within. + * + * @param array $options optional set of additional params for the request. + * @return array of JSON-sourced user data arrays + * + * @throws Exception on low-level or HTTP error + */ + public function groups($params=array()) + { + return $this->api('groups', $params); + } +} |