]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/YammerImport/lib/snyammerclient.php
Documentation + filename uniqueness in File class
[quix0rs-gnu-social.git] / plugins / YammerImport / lib / snyammerclient.php
1 <?php
2 /*
3  * StatusNet - the distributed open-source microblogging tool
4  * Copyright (C) 2010, StatusNet, Inc.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /**
21  * Basic client class for Yammer's OAuth/JSON API.
22  *
23  * @package YammerImportPlugin
24  * @author Brion Vibber <brion@status.net>
25  */
26 class SNYammerClient
27 {
28     protected $apiBase = "https://www.yammer.com";
29     protected $consumerKey, $consumerSecret;
30     protected $token, $tokenSecret, $verifier;
31
32     public function __construct($consumerKey, $consumerSecret, $token=null, $tokenSecret=null)
33     {
34         $this->consumerKey = $consumerKey;
35         $this->consumerSecret = $consumerSecret;
36         $this->token = $token;
37         $this->tokenSecret = $tokenSecret;
38     }
39
40     /**
41      * Make an HTTP GET request with OAuth headers and return an HTTPResponse
42      * with the returned body and codes.
43      *
44      * @param string $url
45      * @return HTTPResponse
46      *
47      * @throws Exception on low-level network error
48      */
49     protected function httpGet($url)
50     {
51         $headers = array('Authorization: ' . $this->authHeader());
52
53         $client = HTTPClient::start();
54         return $client->get($url, $headers);
55     }
56
57     /**
58      * Make an HTTP GET request with OAuth headers and return the response body
59      * on success.
60      *
61      * @param string $url
62      * @return string
63      *
64      * @throws Exception on low-level network or HTTP error
65      */
66     public function fetchUrl($url)
67     {
68         $response = $this->httpGet($url);
69         if ($response->isOk()) {
70             return $response->getBody();
71         } else {
72             // TRANS: Exeption thrown when an external Yammer system gives an error.
73             // TRANS: %1$s is an HTTP error code, %2$s is the error message body.
74             throw new Exception(sprintf(_m('Yammer API returned HTTP code %1$s: %2$s'),
75                                 $response->getStatus(),
76                                 $response->getBody()));
77         }
78     }
79
80     /**
81      * Make an HTTP hit with OAuth headers and return the response body on success.
82      *
83      * @param string $path URL chunk for the API method
84      * @param array $params
85      * @return string
86      *
87      * @throws Exception on low-level network or HTTP error
88      */
89     protected function fetchApi($path, $params=array())
90     {
91         $url = $this->apiBase . '/' . $path;
92         if ($params) {
93             $url .= '?' . http_build_query($params, null, '&');
94         }
95         return $this->fetchUrl($url);
96     }
97
98     /**
99      * Hit the main Yammer API point and decode returned JSON data.
100      *
101      * @param string $method
102      * @param array $params
103      * @return array from JSON data
104      *
105      * @throws Exception for HTTP error or bad JSON return
106      */
107     public function api($method, $params=array())
108     {
109         $body = $this->fetchApi("api/v1/$method.json", $params);
110         $data = json_decode($body, true);
111         if ($data === null) {
112             common_log(LOG_ERR, "Invalid JSON response from Yammer API: " . $body);
113             // TRANS: Exeption thrown when an external Yammer system an invalid JSON response.
114             throw new Exception(_m('Invalid JSON response from Yammer API.'));
115         }
116         return $data;
117     }
118
119     /**
120      * Build an Authorization header value from the keys we have available.
121      */
122     protected function authHeader()
123     {
124         // token
125         // token_secret
126         $params = array('realm' => '',
127                         'oauth_consumer_key' => $this->consumerKey,
128                         'oauth_signature_method' => 'PLAINTEXT',
129                         'oauth_timestamp' => time(),
130                         'oauth_nonce' => time(),
131                         'oauth_version' => '1.0');
132         if ($this->token) {
133             $params['oauth_token'] = $this->token;
134         }
135         if ($this->tokenSecret) {
136             $params['oauth_signature'] = $this->consumerSecret . '&' . $this->tokenSecret;
137         } else {
138             $params['oauth_signature'] = $this->consumerSecret . '&';
139         }
140         if ($this->verifier) {
141             $params['oauth_verifier'] = $this->verifier;
142         }
143         $parts = array_map(array($this, 'authHeaderChunk'), array_keys($params), array_values($params));
144         return 'OAuth ' . implode(', ', $parts);
145     }
146
147     /**
148      * Encode a key-value pair for use in an authentication header.
149      *
150      * @param string $key
151      * @param string $val
152      * @return string
153      */
154     protected function authHeaderChunk($key, $val)
155     {
156         return urlencode($key) . '="' . urlencode($val) . '"';
157     }
158
159     /**
160      * Ask the Yammer server for a request token, which can be passed on
161      * to authorizeUrl() for the user to start the authentication process.
162      *
163      * @return array of oauth return data; should contain nice things
164      */
165     public function requestToken()
166     {
167         if ($this->token || $this->tokenSecret) {
168             // TRANS: Exeption thrown when a trust relationship has already been established.
169             throw new Exception(_m('Requesting a token, but already set up with a token.'));
170         }
171         $data = $this->fetchApi('oauth/request_token');
172         $arr = array();
173         parse_str($data, $arr);
174         return $arr;
175     }
176
177     /**
178      * Get a final access token from the verifier/PIN code provided to
179      * the user from Yammer's auth pages.
180      *
181      * @return array of oauth return data; should contain nice things
182      */
183     public function accessToken($verifier)
184     {
185         $this->verifier = $verifier;
186         $data = $this->fetchApi('oauth/access_token');
187         $this->verifier = null;
188         $arr = array();
189         parse_str($data, $arr);
190         return $arr;
191     }
192
193     /**
194      * Give the URL to send users to to authorize a new app setup.
195      *
196      * @param string $token as returned from accessToken()
197      * @return string URL
198      */
199     public function authorizeUrl($token)
200     {
201         return $this->apiBase . '/oauth/authorize?oauth_token=' . urlencode($token);
202     }
203
204     /**
205      * High-level API hit: fetch all messages in the network (up to 20 at a time).
206      * Return data is the full JSON array returned, including meta and references
207      * sections.
208      *
209      * The matching messages themselves will be in the 'messages' item within.
210      *
211      * @param array $options optional set of additional params for the request.
212      * @return array
213      *
214      * @throws Exception on low-level or HTTP error
215      */
216     public function messages($params=array())
217     {
218         return $this->api('messages', $params);
219     }
220
221     /**
222      * High-level API hit: fetch all users in the network (up to 50 at a time).
223      * Return data is the full JSON array returned, listing user items.
224      *
225      * The matching messages themselves will be in the 'users' item within.
226      *
227      * @param array $options optional set of additional params for the request.
228      * @return array of JSON-sourced user data arrays
229      *
230      * @throws Exception on low-level or HTTP error
231      */
232     public function users($params=array())
233     {
234         return $this->api('users', $params);
235     }
236
237     /**
238      * High-level API hit: fetch all groups in the network (up to 20 at a time).
239      * Return data is the full JSON array returned, listing user items.
240      *
241      * The matching messages themselves will be in the 'users' item within.
242      *
243      * @param array $options optional set of additional params for the request.
244      * @return array of JSON-sourced user data arrays
245      *
246      * @throws Exception on low-level or HTTP error
247      */
248     public function groups($params=array())
249     {
250         return $this->api('groups', $params);
251     }
252 }