ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/facebook/trunk/facebookapi_php5_restlib.php
Revision: 943
Committed: 2007-08-29T17:44:10-07:00 (17 years, 10 months ago) by douglas
File size: 23158 byte(s)
Log Message:
Blah!

File Contents

# Content
1 <?php
2 //
3 // +---------------------------------------------------------------------------+
4 // | Facebook Platform PHP5 client |
5 // +---------------------------------------------------------------------------+
6 // | Copyright (c) 2007 Facebook, Inc. |
7 // | All rights reserved. |
8 // | |
9 // | Redistribution and use in source and binary forms, with or without |
10 // | modification, are permitted provided that the following conditions |
11 // | are met: |
12 // | |
13 // | 1. Redistributions of source code must retain the above copyright |
14 // | notice, this list of conditions and the following disclaimer. |
15 // | 2. Redistributions in binary form must reproduce the above copyright |
16 // | notice, this list of conditions and the following disclaimer in the |
17 // | documentation and/or other materials provided with the distribution. |
18 // | |
19 // | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
20 // | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
21 // | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
22 // | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
23 // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
24 // | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
28 // | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 // +---------------------------------------------------------------------------+
30 // | For help with this library, contact developers-help@facebook.com |
31 // +---------------------------------------------------------------------------+
32 //
33
34 class FacebookRestClient {
35 public $secret;
36 public $session_key;
37 public $api_key;
38 public $friends_list; // to save making the friends.get api call, this will get prepopulated on canvas pages
39 public $added; // to save making the users.isAppAdded api call, this will get prepopulated on canvas pages
40
41 /**
42 * Create the client.
43 * @param string $session_key if you haven't gotten a session key yet, leave
44 * this as null and then set it later by just
45 * directly accessing the $session_key member
46 * variable.
47 */
48 public function __construct($api_key, $secret, $session_key=null) {
49 $this->secret = $secret;
50 $this->session_key = $session_key;
51 $this->api_key = $api_key;
52 $this->last_call_id = 0;
53 $this->server_addr = Facebook::get_facebook_url('api') . '/restserver.php';
54 if ($GLOBALS['facebook_config']['debug']) {
55 $this->cur_id = 0;
56 ?>
57 <script type="text/javascript">
58 var types = ['params', 'xml', 'php', 'sxml'];
59 function toggleDisplay(id, type) {
60 for each (var t in types) {
61 if (t != type || document.getElementById(t + id).style.display == 'block') {
62 document.getElementById(t + id).style.display = 'none';
63 } else {
64 document.getElementById(t + id).style.display = 'block';
65 }
66 }
67 return false;
68 }
69 </script>
70 <?php
71 }
72 }
73
74 /**
75 * Returns the session information available after current user logs in.
76 * @param string $auth_token the token returned by auth_createToken or
77 * passed back to your callback_url.
78 * @return assoc array containing session_key, uid
79 */
80 public function auth_getSession($auth_token) {
81 $result = $this->call_method('facebook.auth.getSession', array('auth_token'=>$auth_token));
82 $this->session_key = $result['session_key'];
83 if (isset($result['secret']) && $result['secret']) {
84 // desktop apps have a special secret
85 $this->secret = $result['secret'];
86 }
87 return $result;
88 }
89
90 /**
91 * Returns events according to the filters specified.
92 * @param int $uid Optional: User associated with events.
93 * A null parameter will default to the session user.
94 * @param array $eids Optional: Filter by these event ids.
95 * A null parameter will get all events for the user.
96 * @param int $start_time Optional: Filter with this UTC as lower bound.
97 * A null or zero parameter indicates no lower bound.
98 * @param int $end_time Optional: Filter with this UTC as upper bound.
99 * A null or zero parameter indicates no upper bound.
100 * @param string $rsvp_status Optional: Only show events where the given uid
101 * has this rsvp status. This only works if you have specified a value for
102 * $uid. Values are as in events.getMembers. Null indicates to ignore
103 * rsvp status when filtering.
104 * @return array of events
105 */
106 public function events_get($uid, $eids, $start_time, $end_time, $rsvp_status) {
107 return $this->call_method('facebook.events.get',
108 array(
109 'uid' => $uid,
110 'eids' => $eids,
111 'start_time' => $start_time,
112 'end_time' => $end_time,
113 'rsvp_status' => $rsvp_status));
114 }
115
116 /**
117 * Returns membership list data associated with an event
118 * @param int $eid : event id
119 * @return assoc array of four membership lists, with keys 'attending',
120 * 'unsure', 'declined', and 'not_replied'
121 */
122 public function events_getMembers($eid) {
123 return $this->call_method('facebook.events.getMembers',
124 array('eid' => $eid));
125 }
126
127 /**
128 * Makes an FQL query. This is a generalized way of accessing all the data
129 * in the API, as an alternative to most of the other method calls. More
130 * info at http://developers.facebook.com/documentation.php?v=1.0&doc=fql
131 * @param string $query the query to evaluate
132 * @return generalized array representing the results
133 */
134 public function fql_query($query) {
135 return $this->call_method('facebook.fql.query',
136 array('query' => $query));
137 }
138
139 public function feed_publishStoryToUser($title, $body,
140 $image_1=null, $image_1_link=null,
141 $image_2=null, $image_2_link=null,
142 $image_3=null, $image_3_link=null,
143 $image_4=null, $image_4_link=null,
144 $priority=1) {
145 return $this->call_method('facebook.feed.publishStoryToUser',
146 array('title' => $title,
147 'body' => $body,
148 'image_1' => $image_1,
149 'image_1_link' => $image_1_link,
150 'image_2' => $image_2,
151 'image_2_link' => $image_2_link,
152 'image_3' => $image_3,
153 'image_3_link' => $image_3_link,
154 'image_4' => $image_4,
155 'image_4_link' => $image_4_link,
156 'priority' => $priority));
157 }
158
159 public function feed_publishActionOfUser($title, $body,
160 $image_1=null, $image_1_link=null,
161 $image_2=null, $image_2_link=null,
162 $image_3=null, $image_3_link=null,
163 $image_4=null, $image_4_link=null,
164 $priority=1) {
165 return $this->call_method('facebook.feed.publishActionOfUser',
166 array('title' => $title,
167 'body' => $body,
168 'image_1' => $image_1,
169 'image_1_link' => $image_1_link,
170 'image_2' => $image_2,
171 'image_2_link' => $image_2_link,
172 'image_3' => $image_3,
173 'image_3_link' => $image_3_link,
174 'image_4' => $image_4,
175 'image_4_link' => $image_4_link,
176 'priority' => $priority));
177 }
178
179 /**
180 * Returns whether or not pairs of users are friends.
181 * Note that the Facebook friend relationship is symmetric.
182 * @param array $uids1: array of ids (id_1, id_2,...) of some length X
183 * @param array $uids2: array of ids (id_A, id_B,...) of SAME length X
184 * @return array of uid pairs with bool, true if pair are friends, e.g.
185 * array( 0 => array('uid1' => id_1, 'uid2' => id_A, 'are_friends' => 1),
186 * 1 => array('uid1' => id_2, 'uid2' => id_B, 'are_friends' => 0)
187 * ...)
188 */
189 public function friends_areFriends($uids1, $uids2) {
190 return $this->call_method('facebook.friends.areFriends',
191 array('uids1'=>$uids1, 'uids2'=>$uids2));
192 }
193
194 /**
195 * Returns the friends of the current session user.
196 * @return array of friends
197 */
198 public function friends_get() {
199 if (isset($this->friends_list)) {
200 return $this->friends_list;
201 }
202 return $this->call_method('facebook.friends.get', array());
203 }
204
205 /**
206 * Returns the friends of the session user, who are also users
207 * of the calling application.
208 * @return array of friends
209 */
210 public function friends_getAppUsers() {
211 return $this->call_method('facebook.friends.getAppUsers', array());
212 }
213
214 /**
215 * Returns groups according to the filters specified.
216 * @param int $uid Optional: User associated with groups.
217 * A null parameter will default to the session user.
218 * @param array $gids Optional: group ids to query.
219 * A null parameter will get all groups for the user.
220 * @return array of groups
221 */
222 public function groups_get($uid, $gids) {
223 return $this->call_method('facebook.groups.get',
224 array(
225 'uid' => $uid,
226 'gids' => $gids));
227 }
228
229 /**
230 * Returns the membership list of a group
231 * @param int $gid : Group id
232 * @return assoc array of four membership lists, with keys
233 * 'members', 'admins', 'officers', and 'not_replied'
234 */
235 public function groups_getMembers($gid) {
236 return $this->call_method('facebook.groups.getMembers',
237 array('gid' => $gid));
238 }
239
240 /**
241 * Returns the outstanding notifications for the session user.
242 * @return assoc array of
243 * notification count objects for 'messages', 'pokes' and 'shares',
244 * a uid list of 'friend_requests', a gid list of 'group_invites',
245 * and an eid list of 'event_invites'
246 */
247 public function notifications_get() {
248 return $this->call_method('facebook.notifications.get', array());
249 }
250
251 /**
252 * Sends an email notification to the specified user.
253 * @return string url which you should send the logged in user to to finalize the message.
254 */
255 public function notifications_send($to_ids, $notification, $email='') {
256 return $this->call_method('facebook.notifications.send',
257 array('to_ids' => $to_ids, 'notification' => $notification, 'email' => $email));
258 }
259
260 /**
261 * Sends a request to the specified user (e.g. "you have 1 event invitation")
262 * @param array $to_ids user ids to receive the request (must be friends with sender, capped at 10)
263 * @param string $type type of request, e.g. "event" (as in "You have an event invitation.")
264 * @param string $content fbml content of the request. really stripped down fbml - just
265 * text/names/links. also, use the special tag <fb:req-choice url="" label="" />
266 * to specify the buttons to be included.
267 * @param string $image url of an image to show beside the request
268 * @param bool $invite whether to call it an "invitation" or a "request"
269 * @return string url which you should send the logged in user to to finalize the message.
270 */
271 public function notifications_sendRequest($to_ids, $type, $content, $image, $invite) {
272 return $this->call_method('facebook.notifications.sendRequest',
273 array('to_ids' => $to_ids, 'type' => $type, 'content' => $content,
274 'image' => $image, 'invite' => $invite));
275 }
276
277 /**
278 * Returns photos according to the filters specified.
279 * @param int $subj_id Optional: Filter by uid of user tagged in the photos.
280 * @param int $aid Optional: Filter by an album, as returned by
281 * photos_getAlbums.
282 * @param array $pids Optional: Restrict to a list of pids
283 * Note that at least one of these parameters needs to be specified, or an
284 * error is returned.
285 * @return array of photo objects.
286 */
287 public function photos_get($subj_id, $aid, $pids) {
288 return $this->call_method('facebook.photos.get',
289 array('subj_id' => $subj_id, 'aid' => $aid, 'pids' => $pids));
290 }
291
292 /**
293 * Returns the albums created by the given user.
294 * @param int $uid Optional: the uid of the user whose albums you want.
295 * A null value will return the albums of the session user.
296 * @param array $aids Optional: a list of aids to restrict the query.
297 * Note that at least one of the (uid, aids) parameters must be specified.
298 * @returns an array of album objects.
299 */
300 public function photos_getAlbums($uid, $aids) {
301 return $this->call_method('facebook.photos.getAlbums',
302 array('uid' => $uid,
303 'aids' => $aids));
304 }
305
306 /**
307 * Returns the tags on all photos specified.
308 * @param string $pids : a list of pids to query
309 * @return array of photo tag objects, with include pid, subject uid,
310 * and two floating-point numbers (xcoord, ycoord) for tag pixel location
311 */
312 public function photos_getTags($pids) {
313 return $this->call_method('facebook.photos.getTags',
314 array('pids' => $pids));
315 }
316
317 /**
318 * Returns the requested info fields for the requested set of users
319 * @param array $uids an array of user ids
320 * @param array $fields an array of strings describing the info fields desired
321 * @return array of users
322 */
323 public function users_getInfo($uids, $fields) {
324 return $this->call_method('facebook.users.getInfo', array('uids' => $uids, 'fields' => $fields));
325 }
326
327 /**
328 * Returns the user corresponding to the current session object.
329 * @return integer uid
330 */
331 public function users_getLoggedInUser(){
332 return $this->call_method('facebook.users.getLoggedInUser', array());
333 }
334
335
336 /**
337 * Returns whether or not the user corresponding to the current session object has the app installed
338 * @return boolean
339 */
340 public function users_isAppAdded() {
341 if (isset($this->added)) {
342 return $this->added;
343 }
344 return $this->call_method('facebook.users.isAppAdded', array());
345 }
346
347 /**
348 * Sets the FBML for the profile of the user attached to this session
349 * @param string $markup The FBML that describes the profile presence of this app for the user
350 * @return array A list of strings describing any compile errors for the submitted FBML
351 */
352 public function profile_setFBML($markup, $uid = null) {
353 return $this->call_method('facebook.profile.setFBML', array('markup' => $markup, 'uid' => $uid));
354 }
355
356 public function profile_getFBML($uid) {
357 return $this->call_method('facebook.profile.getFBML', array('uid' => $uid));
358 }
359
360 public function fbml_refreshImgSrc($url) {
361 return $this->call_method('facebook.fbml.refreshImgSrc', array('url' => $url));
362 }
363
364 public function fbml_refreshRefUrl($url) {
365 return $this->call_method('facebook.fbml.refreshRefUrl', array('url' => $url));
366 }
367
368 public function fbml_setRefHandle($handle, $fbml) {
369 return $this->call_method('facebook.fbml.setRefHandle', array('handle' => $handle, 'fbml' => $fbml));
370 }
371
372 /* UTILITY FUNCTIONS */
373
374 public function call_method($method, $params) {
375 $xml = $this->post_request($method, $params);
376 $sxml = simplexml_load_string($xml);
377 $result = self::convert_simplexml_to_array($sxml);
378 if ($GLOBALS['facebook_config']['debug']) {
379 // output the raw xml and its corresponding php object, for debugging:
380 print '<div style="margin: 10px 30px; padding: 5px; border: 2px solid black; background: gray; color: white; font-size: 12px; font-weight: bold;">';
381 $this->cur_id++;
382 print $this->cur_id . ': Called ' . $method . ', show ' .
383 '<a href=# onclick="return toggleDisplay(' . $this->cur_id . ', \'params\');">Params</a> | '.
384 '<a href=# onclick="return toggleDisplay(' . $this->cur_id . ', \'xml\');">XML</a> | '.
385 '<a href=# onclick="return toggleDisplay(' . $this->cur_id . ', \'sxml\');">SXML</a> | '.
386 '<a href=# onclick="return toggleDisplay(' . $this->cur_id . ', \'php\');">PHP</a>';
387 print '<pre id="params'.$this->cur_id.'" style="display: none; overflow: auto;">'.print_r($params, true).'</pre>';
388 print '<pre id="xml'.$this->cur_id.'" style="display: none; overflow: auto;">'.htmlspecialchars($xml).'</pre>';
389 print '<pre id="php'.$this->cur_id.'" style="display: none; overflow: auto;">'.print_r($result, true).'</pre>';
390 print '<pre id="sxml'.$this->cur_id.'" style="display: none; overflow: auto;">'.print_r($sxml, true).'</pre>';
391 print '</div>';
392 }
393 if (is_array($result) && isset($result['error_code'])) {
394 throw new FacebookRestClientException($result['error_msg'], $result['error_code']);
395 }
396 return $result;
397 }
398
399 public function post_request($method, $params) {
400 $params['method'] = $method;
401 $params['session_key'] = $this->session_key;
402 $params['api_key'] = $this->api_key;
403 $params['call_id'] = microtime(true);
404 if ($params['call_id'] <= $this->last_call_id) {
405 $params['call_id'] = $this->last_call_id + 0.001;
406 }
407 $this->last_call_id = $params['call_id'];
408 if (!isset($params['v'])) {
409 $params['v'] = '1.0';
410 }
411 $post_params = array();
412 foreach ($params as $key => &$val) {
413 if (is_array($val)) $val = implode(',', $val);
414 $post_params[] = $key.'='.urlencode($val);
415 }
416 $secret = $this->secret;
417 $post_params[] = 'sig='.Facebook::generate_sig($params, $secret);
418 $post_string = implode('&', $post_params);
419
420 if (function_exists('curl_init')) {
421 // Use CURL if installed...
422 $ch = curl_init();
423 curl_setopt($ch, CURLOPT_URL, $this->server_addr);
424 curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);
425 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
426 curl_setopt($ch, CURLOPT_USERAGENT, 'Facebook API PHP5 Client 1.1 (curl) ' . phpversion());
427 $result = curl_exec($ch);
428 curl_close($ch);
429 } else {
430 // Non-CURL based version...
431 $context =
432 array('http' =>
433 array('method' => 'POST',
434 'header' => 'Content-type: application/x-www-form-urlencoded'."\r\n".
435 'User-Agent: Facebook API PHP5 Client 1.1 (non-curl) '.phpversion()."\r\n".
436 'Content-length: ' . strlen($post_string),
437 'content' => $post_string));
438 $contextid=stream_context_create($context);
439 $sock=fopen($this->server_addr, 'r', false, $contextid);
440 if ($sock) {
441 $result='';
442 while (!feof($sock))
443 $result.=fgets($sock, 4096);
444
445 fclose($sock);
446 }
447 }
448 return $result;
449 }
450
451 public static function convert_simplexml_to_array($sxml) {
452 $arr = array();
453 if ($sxml) {
454 foreach ($sxml as $k => $v) {
455 if ($sxml['list']) {
456 $arr[] = self::convert_simplexml_to_array($v);
457 } else {
458 $arr[$k] = self::convert_simplexml_to_array($v);
459 }
460 }
461 }
462 if (sizeof($arr) > 0) {
463 return $arr;
464 } else {
465 return (string)$sxml;
466 }
467 }
468 }
469
470 class FacebookRestClientException extends Exception {
471 }
472
473 // Supporting methods and values------
474
475 /**
476 * Error codes and descriptions for the Facebook API.
477 */
478
479 class FacebookAPIErrorCodes {
480
481 const API_EC_SUCCESS = 0;
482
483 /*
484 * GENERAL ERRORS
485 */
486 const API_EC_UNKNOWN = 1;
487 const API_EC_SERVICE = 2;
488 const API_EC_METHOD = 3;
489 const API_EC_TOO_MANY_CALLS = 4;
490 const API_EC_BAD_IP = 5;
491
492 /*
493 * PARAMETER ERRORS
494 */
495 const API_EC_PARAM = 100;
496 const API_EC_PARAM_API_KEY = 101;
497 const API_EC_PARAM_SESSION_KEY = 102;
498 const API_EC_PARAM_CALL_ID = 103;
499 const API_EC_PARAM_SIGNATURE = 104;
500 const API_EC_PARAM_USER_ID = 110;
501 const API_EC_PARAM_USER_FIELD = 111;
502 const API_EC_PARAM_SOCIAL_FIELD = 112;
503 const API_EC_PARAM_ALBUM_ID = 120;
504
505 /*
506 * USER PERMISSIONS ERRORS
507 */
508 const API_EC_PERMISSION = 200;
509 const API_EC_PERMISSION_USER = 210;
510 const API_EC_PERMISSION_ALBUM = 220;
511 const API_EC_PERMISSION_PHOTO = 221;
512
513 const FQL_EC_PARSER = 601;
514 const FQL_EC_UNKNOWN_FIELD = 602;
515 const FQL_EC_UNKNOWN_TABLE = 603;
516 const FQL_EC_NOT_INDEXABLE = 604;
517
518 public static $api_error_descriptions = array(
519 API_EC_SUCCESS => 'Success',
520 API_EC_UNKNOWN => 'An unknown error occurred',
521 API_EC_SERVICE => 'Service temporarily unavailable',
522 API_EC_METHOD => 'Unknown method',
523 API_EC_TOO_MANY_CALLS => 'Application request limit reached',
524 API_EC_BAD_IP => 'Unauthorized source IP address',
525 API_EC_PARAM => 'Invalid parameter',
526 API_EC_PARAM_API_KEY => 'Invalid API key',
527 API_EC_PARAM_SESSION_KEY => 'Session key invalid or no longer valid',
528 API_EC_PARAM_CALL_ID => 'Call_id must be greater than previous',
529 API_EC_PARAM_SIGNATURE => 'Incorrect signature',
530 API_EC_PARAM_USER_ID => 'Invalid user id',
531 API_EC_PARAM_USER_FIELD => 'Invalid user info field',
532 API_EC_PARAM_SOCIAL_FIELD => 'Invalid user field',
533 API_EC_PARAM_ALBUM_ID => 'Invalid album id',
534 API_EC_PERMISSION => 'Permissions error',
535 API_EC_PERMISSION_USER => 'User not visible',
536 API_EC_PERMISSION_ALBUM => 'Album not visible',
537 API_EC_PERMISSION_PHOTO => 'Photo not visible',
538 FQL_EC_PARSER => 'FQL: Parser Error',
539 FQL_EC_UNKNOWN_FIELD => 'FQL: Unknown Field',
540 FQL_EC_UNKNOWN_TABLE => 'FQL: Unknown Table',
541 FQL_EC_NOT_INDEXABLE => 'FQL: Statement not indexable',
542 FQL_EC_UNKNOWN_FUNCTION => 'FQL: Attempted to call unknown function',
543 FQL_EC_INVALID_PARAM => 'FQL: Invalid parameter passed in',
544 );
545 }
546
547 $profile_field_array = array(
548 "about_me",
549 "activities",
550 "affiliations",
551 "birthday",
552 "books",
553 "current_location",
554 "education_history",
555 "first_name",
556 "hometown_location",
557 "hs_info",
558 "interests",
559 "is_app_user",
560 "last_name",
561 "meeting_for",
562 "meeting_sex",
563 "movies",
564 "music",
565 "name",
566 "notes_count",
567 "pic",
568 "pic_big",
569 "pic_small",
570 "political",
571 "profile_update_time",
572 "quotes",
573 "relationship_status",
574 "religion",
575 "sex",
576 "significant_other_id",
577 "status",
578 "timezone",
579 "tv",
580 "wall_count",
581 "work_history");
582 ?>

Properties

Name Value
svn:executable *