]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/Facebook/facebook/facebookapi_php5_restlib.php
Merge branch 'inblob' of git@gitorious.org:~evan/statusnet/evans-mainline into inblob
[quix0rs-gnu-social.git] / plugins / Facebook / facebook / facebookapi_php5_restlib.php
1 <?php
2 // Copyright 2004-2009 Facebook. All Rights Reserved.
3 //
4 // +---------------------------------------------------------------------------+
5 // | Facebook Platform PHP5 client                                             |
6 // +---------------------------------------------------------------------------+
7 // | Copyright (c) 2007-2009 Facebook, Inc.                                    |
8 // | All rights reserved.                                                      |
9 // |                                                                           |
10 // | Redistribution and use in source and binary forms, with or without        |
11 // | modification, are permitted provided that the following conditions        |
12 // | are met:                                                                  |
13 // |                                                                           |
14 // | 1. Redistributions of source code must retain the above copyright         |
15 // |    notice, this list of conditions and the following disclaimer.          |
16 // | 2. Redistributions in binary form must reproduce the above copyright      |
17 // |    notice, this list of conditions and the following disclaimer in the    |
18 // |    documentation and/or other materials provided with the distribution.   |
19 // |                                                                           |
20 // | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR      |
21 // | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
22 // | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.   |
23 // | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,          |
24 // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  |
25 // | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26 // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     |
27 // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       |
28 // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  |
29 // | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.         |
30 // +---------------------------------------------------------------------------+
31 // | For help with this library, contact developers-help@facebook.com          |
32 // +---------------------------------------------------------------------------+
33 //
34
35 include_once 'jsonwrapper/jsonwrapper.php';
36
37 class FacebookRestClient {
38   public $secret;
39   public $session_key;
40   public $api_key;
41   // to save making the friends.get api call, this will get prepopulated on
42   // canvas pages
43   public $friends_list;
44   public $user;
45   // to save making the pages.isAppAdded api call, this will get prepopulated
46   // on canvas pages
47   public $added;
48   public $is_user;
49   // we don't pass friends list to iframes, but we want to make
50   // friends_get really simple in the canvas_user (non-logged in) case.
51   // So we use the canvas_user as default arg to friends_get
52   public $canvas_user;
53   public $batch_mode;
54   private $batch_queue;
55   private $pending_batch;
56   private $call_as_apikey;
57   private $use_curl_if_available;
58   private $format = null;
59   private $using_session_secret = false;
60   private $rawData = null;
61
62   const BATCH_MODE_DEFAULT = 0;
63   const BATCH_MODE_SERVER_PARALLEL = 0;
64   const BATCH_MODE_SERIAL_ONLY = 2;
65
66   /**
67    * Create the client.
68    * @param string $session_key if you haven't gotten a session key yet, leave
69    *                            this as null and then set it later by just
70    *                            directly accessing the $session_key member
71    *                            variable.
72    */
73   public function __construct($api_key, $secret, $session_key=null) {
74     $this->secret       = $secret;
75     $this->session_key  = $session_key;
76     $this->api_key      = $api_key;
77     $this->batch_mode = FacebookRestClient::BATCH_MODE_DEFAULT;
78     $this->last_call_id = 0;
79     $this->call_as_apikey = '';
80     $this->use_curl_if_available = true;
81     $this->server_addr =
82       Facebook::get_facebook_url('api') . '/restserver.php';
83     $this->photo_server_addr =
84       Facebook::get_facebook_url('api-photo') . '/restserver.php';
85
86     if (!empty($GLOBALS['facebook_config']['debug'])) {
87       $this->cur_id = 0;
88       ?>
89 <script type="text/javascript">
90 var types = ['params', 'xml', 'php', 'sxml'];
91 function getStyle(elem, style) {
92   if (elem.getStyle) {
93     return elem.getStyle(style);
94   } else {
95     return elem.style[style];
96   }
97 }
98 function setStyle(elem, style, value) {
99   if (elem.setStyle) {
100     elem.setStyle(style, value);
101   } else {
102     elem.style[style] = value;
103   }
104 }
105 function toggleDisplay(id, type) {
106   for (var i = 0; i < types.length; i++) {
107     var t = types[i];
108     var pre = document.getElementById(t + id);
109     if (pre) {
110       if (t != type || getStyle(pre, 'display') == 'block') {
111         setStyle(pre, 'display', 'none');
112       } else {
113         setStyle(pre, 'display', 'block');
114       }
115     }
116   }
117   return false;
118 }
119 </script>
120 <?php
121     }
122   }
123
124   /**
125    * Set the default user id for methods that allow the caller
126    * to pass an uid parameter to identify the target user
127    * instead of a session key. This currently applies to
128    * the user preferences methods.
129    *
130    * @param $uid int the user id
131    */
132   public function set_user($uid) {
133     $this->user = $uid;
134   }
135
136
137   /**
138    * Switch to use the session secret instead of the app secret,
139    * for desktop and unsecured environment
140    */
141   public function use_session_secret($session_secret) {
142     $this->secret = $session_secret;
143     $this->using_session_secret = true;
144   }
145
146   /**
147    * Normally, if the cURL library/PHP extension is available, it is used for
148    * HTTP transactions.  This allows that behavior to be overridden, falling
149    * back to a vanilla-PHP implementation even if cURL is installed.
150    *
151    * @param $use_curl_if_available bool whether or not to use cURL if available
152    */
153   public function set_use_curl_if_available($use_curl_if_available) {
154     $this->use_curl_if_available = $use_curl_if_available;
155   }
156
157   /**
158    * Start a batch operation.
159    */
160   public function begin_batch() {
161     if ($this->pending_batch()) {
162       $code = FacebookAPIErrorCodes::API_EC_BATCH_ALREADY_STARTED;
163       $description = FacebookAPIErrorCodes::$api_error_descriptions[$code];
164       throw new FacebookRestClientException($description, $code);
165     }
166
167     $this->batch_queue = array();
168     $this->pending_batch = true;
169   }
170
171   /*
172    * End current batch operation
173    */
174   public function end_batch() {
175     if (!$this->pending_batch()) {
176       $code = FacebookAPIErrorCodes::API_EC_BATCH_NOT_STARTED;
177       $description = FacebookAPIErrorCodes::$api_error_descriptions[$code];
178       throw new FacebookRestClientException($description, $code);
179     }
180
181     $this->pending_batch = false;
182
183     $this->execute_server_side_batch();
184     $this->batch_queue = null;
185   }
186
187   /**
188    * are we currently queueing up calls for a batch?
189    */
190   public function pending_batch() {
191     return $this->pending_batch;
192   }
193
194   private function execute_server_side_batch() {
195     $item_count = count($this->batch_queue);
196     $method_feed = array();
197     foreach ($this->batch_queue as $batch_item) {
198       $method = $batch_item['m'];
199       $params = $batch_item['p'];
200       list($get, $post) = $this->finalize_params($method, $params);
201       $method_feed[] = $this->create_url_string(array_merge($post, $get));
202     }
203
204     $serial_only =
205       ($this->batch_mode == FacebookRestClient::BATCH_MODE_SERIAL_ONLY);
206
207     $params = array('method_feed' => json_encode($method_feed),
208                     'serial_only' => $serial_only,
209                     'format' => $this->format);
210     $result = $this->call_method('facebook.batch.run', $params);
211
212     if (is_array($result) && isset($result['error_code'])) {
213       throw new FacebookRestClientException($result['error_msg'],
214                                             $result['error_code']);
215     }
216
217     for ($i = 0; $i < $item_count; $i++) {
218       $batch_item = $this->batch_queue[$i];
219       $batch_item['p']['format'] = $this->format;
220       $batch_item_result = $this->convert_result($result[$i],
221                                                  $batch_item['m'],
222                                                  $batch_item['p']);
223
224       if (is_array($batch_item_result) &&
225           isset($batch_item_result['error_code'])) {
226         throw new FacebookRestClientException($batch_item_result['error_msg'],
227                                               $batch_item_result['error_code']);
228       }
229       $batch_item['r'] = $batch_item_result;
230     }
231   }
232
233   public function begin_permissions_mode($permissions_apikey) {
234     $this->call_as_apikey = $permissions_apikey;
235   }
236
237   public function end_permissions_mode() {
238     $this->call_as_apikey = '';
239   }
240
241
242   /*
243    * If a page is loaded via HTTPS, then all images and static
244    * resources need to be printed with HTTPS urls to avoid
245    * mixed content warnings. If your page loads with an HTTPS
246    * url, then call set_use_ssl_resources to retrieve the correct
247    * urls.
248    */
249   public function set_use_ssl_resources($is_ssl = true) {
250     $this->use_ssl_resources = $is_ssl;
251   }
252
253   /**
254    * Returns public information for an application (as shown in the application
255    * directory) by either application ID, API key, or canvas page name.
256    *
257    * @param int $application_id              (Optional) app id
258    * @param string $application_api_key      (Optional) api key
259    * @param string $application_canvas_name  (Optional) canvas name
260    *
261    * Exactly one argument must be specified, otherwise it is an error.
262    *
263    * @return array  An array of public information about the application.
264    */
265   public function application_getPublicInfo($application_id=null,
266                                             $application_api_key=null,
267                                             $application_canvas_name=null) {
268     return $this->call_method('facebook.application.getPublicInfo',
269         array('application_id' => $application_id,
270               'application_api_key' => $application_api_key,
271               'application_canvas_name' => $application_canvas_name));
272   }
273
274   /**
275    * Creates an authentication token to be used as part of the desktop login
276    * flow.  For more information, please see
277    * http://wiki.developers.facebook.com/index.php/Auth.createToken.
278    *
279    * @return string  An authentication token.
280    */
281   public function auth_createToken() {
282     return $this->call_method('facebook.auth.createToken');
283   }
284
285   /**
286    * Returns the session information available after current user logs in.
287    *
288    * @param string $auth_token the token returned by auth_createToken or
289    *               passed back to your callback_url.
290    * @param bool $generate_session_secret whether the session returned should
291    *             include a session secret
292    * @param string $host_url the connect site URL for which the session is
293    *               being generated.  This parameter is optional, unless
294    *               you want Facebook to determine which of several base domains
295    *               to choose from.  If this third argument isn't provided but
296    *               there are several base domains, the first base domain is
297    *               chosen.
298    *
299    * @return array  An assoc array containing session_key, uid
300    */
301   public function auth_getSession($auth_token,
302                                   $generate_session_secret = false,
303                                   $host_url = null) {
304     if (!$this->pending_batch()) {
305       $result = $this->call_method(
306         'facebook.auth.getSession',
307         array('auth_token' => $auth_token,
308               'generate_session_secret' => $generate_session_secret,
309               'host_url' => $host_url));
310       $this->session_key = $result['session_key'];
311
312       if (!empty($result['secret']) && !$generate_session_secret) {
313         // desktop apps have a special secret
314         $this->secret = $result['secret'];
315       }
316
317       return $result;
318     }
319   }
320
321   /**
322    * Generates a session-specific secret. This is for integration with
323    * client-side API calls, such as the JS library.
324    *
325    * @return array  A session secret for the current promoted session
326    *
327    * @error API_EC_PARAM_SESSION_KEY
328    *        API_EC_PARAM_UNKNOWN
329    */
330   public function auth_promoteSession() {
331       return $this->call_method('facebook.auth.promoteSession');
332   }
333
334   /**
335    * Expires the session that is currently being used.  If this call is
336    * successful, no further calls to the API (which require a session) can be
337    * made until a valid session is created.
338    *
339    * @return bool  true if session expiration was successful, false otherwise
340    */
341   public function auth_expireSession() {
342       return $this->call_method('facebook.auth.expireSession');
343   }
344
345   /**
346    *  Revokes the given extended permission that the user granted at some
347    *  prior time (for instance, offline_access or email).  If no user is
348    *  provided, it will be revoked for the user of the current session.
349    *
350    *  @param  string  $perm  The permission to revoke
351    *  @param  int     $uid   The user for whom to revoke the permission.
352    */
353   public function auth_revokeExtendedPermission($perm, $uid=null) {
354     return $this->call_method('facebook.auth.revokeExtendedPermission',
355         array('perm' => $perm, 'uid' => $uid));
356   }
357
358   /**
359    * Revokes the user's agreement to the Facebook Terms of Service for your
360    * application.  If you call this method for one of your users, you will no
361    * longer be able to make API requests on their behalf until they again
362    * authorize your application.  Use with care.  Note that if this method is
363    * called without a user parameter, then it will revoke access for the
364    * current session's user.
365    *
366    * @param int $uid  (Optional) User to revoke
367    *
368    * @return bool  true if revocation succeeds, false otherwise
369    */
370   public function auth_revokeAuthorization($uid=null) {
371       return $this->call_method('facebook.auth.revokeAuthorization',
372           array('uid' => $uid));
373   }
374
375   /**
376    * Get public key that is needed to verify digital signature
377    * an app may pass to other apps. The public key is only used by
378    * other apps for verification purposes.
379    * @param  string  API key of an app
380    * @return string  The public key for the app.
381    */
382   public function auth_getAppPublicKey($target_app_key) {
383     return $this->call_method('facebook.auth.getAppPublicKey',
384           array('target_app_key' => $target_app_key));
385   }
386
387   /**
388    * Get a structure that can be passed to another app
389    * as proof of session. The other app can verify it using public
390    * key of this app.
391    *
392    * @return signed public session data structure.
393    */
394   public function auth_getSignedPublicSessionData() {
395     return $this->call_method('facebook.auth.getSignedPublicSessionData',
396                               array());
397   }
398
399   /**
400    * Returns the number of unconnected friends that exist in this application.
401    * This number is determined based on the accounts registered through
402    * connect.registerUsers() (see below).
403    */
404   public function connect_getUnconnectedFriendsCount() {
405     return $this->call_method('facebook.connect.getUnconnectedFriendsCount',
406         array());
407   }
408
409  /**
410   * This method is used to create an association between an external user
411   * account and a Facebook user account, as per Facebook Connect.
412   *
413   * This method takes an array of account data, including a required email_hash
414   * and optional account data. For each connected account, if the user exists,
415   * the information is added to the set of the user's connected accounts.
416   * If the user has already authorized the site, the connected account is added
417   * in the confirmed state. If the user has not yet authorized the site, the
418   * connected account is added in the pending state.
419   *
420   * This is designed to help Facebook Connect recognize when two Facebook
421   * friends are both members of a external site, but perhaps are not aware of
422   * it.  The Connect dialog (see fb:connect-form) is used when friends can be
423   * identified through these email hashes. See the following url for details:
424   *
425   *   http://wiki.developers.facebook.com/index.php/Connect.registerUsers
426   *
427   * @param mixed $accounts A (JSON-encoded) array of arrays, where each array
428   *                        has three properties:
429   *                        'email_hash'  (req) - public email hash of account
430   *                        'account_id'  (opt) - remote account id;
431   *                        'account_url' (opt) - url to remote account;
432   *
433   * @return array  The list of email hashes for the successfully registered
434   *                accounts.
435   */
436   public function connect_registerUsers($accounts) {
437     return $this->call_method('facebook.connect.registerUsers',
438         array('accounts' => $accounts));
439   }
440
441  /**
442   * Unregisters a set of accounts registered using connect.registerUsers.
443   *
444   * @param array $email_hashes  The (JSON-encoded) list of email hashes to be
445   *                             unregistered.
446   *
447   * @return array  The list of email hashes which have been successfully
448   *                unregistered.
449   */
450   public function connect_unregisterUsers($email_hashes) {
451     return $this->call_method('facebook.connect.unregisterUsers',
452         array('email_hashes' => $email_hashes));
453   }
454
455   /**
456    * Returns events according to the filters specified.
457    *
458    * @param int $uid            (Optional) User associated with events. A null
459    *                            parameter will default to the session user.
460    * @param array/string $eids  (Optional) Filter by these event
461    *                            ids. A null parameter will get all events for
462    *                            the user. (A csv list will work but is deprecated)
463    * @param int $start_time     (Optional) Filter with this unix time as lower
464    *                            bound.  A null or zero parameter indicates no
465    *                            lower bound.
466    * @param int $end_time       (Optional) Filter with this UTC as upper bound.
467    *                            A null or zero parameter indicates no upper
468    *                            bound.
469    * @param string $rsvp_status (Optional) Only show events where the given uid
470    *                            has this rsvp status.  This only works if you
471    *                            have specified a value for $uid.  Values are as
472    *                            in events.getMembers.  Null indicates to ignore
473    *                            rsvp status when filtering.
474    *
475    * @return array  The events matching the query.
476    */
477   public function &events_get($uid=null,
478                               $eids=null,
479                               $start_time=null,
480                               $end_time=null,
481                               $rsvp_status=null) {
482     return $this->call_method('facebook.events.get',
483         array('uid' => $uid,
484               'eids' => $eids,
485               'start_time' => $start_time,
486               'end_time' => $end_time,
487               'rsvp_status' => $rsvp_status));
488   }
489
490   /**
491    * Returns membership list data associated with an event.
492    *
493    * @param int $eid  event id
494    *
495    * @return array  An assoc array of four membership lists, with keys
496    *                'attending', 'unsure', 'declined', and 'not_replied'
497    */
498   public function &events_getMembers($eid) {
499     return $this->call_method('facebook.events.getMembers',
500       array('eid' => $eid));
501   }
502
503   /**
504    * RSVPs the current user to this event.
505    *
506    * @param int $eid             event id
507    * @param string $rsvp_status  'attending', 'unsure', or 'declined'
508    *
509    * @return bool  true if successful
510    */
511   public function &events_rsvp($eid, $rsvp_status) {
512     return $this->call_method('facebook.events.rsvp',
513         array(
514         'eid' => $eid,
515         'rsvp_status' => $rsvp_status));
516   }
517
518   /**
519    * Cancels an event. Only works for events where application is the admin.
520    *
521    * @param int $eid                event id
522    * @param string $cancel_message  (Optional) message to send to members of
523    *                                the event about why it is cancelled
524    *
525    * @return bool  true if successful
526    */
527   public function &events_cancel($eid, $cancel_message='') {
528     return $this->call_method('facebook.events.cancel',
529         array('eid' => $eid,
530               'cancel_message' => $cancel_message));
531   }
532
533   /**
534    * Creates an event on behalf of the user is there is a session, otherwise on
535    * behalf of app.  Successful creation guarantees app will be admin.
536    *
537    * @param assoc array $event_info  json encoded event information
538    * @param string $file             (Optional) filename of picture to set
539    *
540    * @return int  event id
541    */
542   public function events_create($event_info, $file = null) {
543     if ($file) {
544       return $this->call_upload_method('facebook.events.create',
545         array('event_info' => $event_info),
546         $file,
547         $this->photo_server_addr);
548     } else {
549       return $this->call_method('facebook.events.create',
550         array('event_info' => $event_info));
551     }
552   }
553
554   /**
555    * Invites users to an event. If a session user exists, the session user
556    * must have permissions to invite friends to the event and $uids must contain
557    * a list of friend ids. Otherwise, the event must have been
558    * created by the app and $uids must contain users of the app.
559    * This method requires the 'create_event' extended permission to
560    * invite people on behalf of a user.
561    *
562    * @param $eid   the event id
563    * @param $uids  an array of users to invite
564    * @param $personal_message  a string containing the user's message
565    *                           (text only)
566    *
567    */
568   public function events_invite($eid, $uids, $personal_message) {
569     return $this->call_method('facebook.events.invite',
570                               array('eid' => $eid,
571                                     'uids' => $uids,
572                                     'personal_message', $personal_message));
573   }
574
575   /**
576    * Edits an existing event. Only works for events where application is admin.
577    *
578    * @param int $eid                 event id
579    * @param assoc array $event_info  json encoded event information
580    * @param string $file             (Optional) filename of new picture to set
581    *
582    * @return bool  true if successful
583    */
584   public function events_edit($eid, $event_info, $file = null) {
585     if ($file) {
586       return $this->call_upload_method('facebook.events.edit',
587         array('eid' => $eid, 'event_info' => $event_info),
588         $file,
589         $this->photo_server_addr);
590     } else {
591       return $this->call_method('facebook.events.edit',
592         array('eid' => $eid,
593         'event_info' => $event_info));
594     }
595   }
596
597   /**
598    * Fetches and re-caches the image stored at the given URL, for use in images
599    * published to non-canvas pages via the API (for example, to user profiles
600    * via profile.setFBML, or to News Feed via feed.publishUserAction).
601    *
602    * @param string $url  The absolute URL from which to refresh the image.
603    *
604    * @return bool  true on success
605    */
606   public function &fbml_refreshImgSrc($url) {
607     return $this->call_method('facebook.fbml.refreshImgSrc',
608         array('url' => $url));
609   }
610
611   /**
612    * Fetches and re-caches the content stored at the given URL, for use in an
613    * fb:ref FBML tag.
614    *
615    * @param string $url  The absolute URL from which to fetch content. This URL
616    *                     should be used in a fb:ref FBML tag.
617    *
618    * @return bool  true on success
619    */
620   public function &fbml_refreshRefUrl($url) {
621     return $this->call_method('facebook.fbml.refreshRefUrl',
622         array('url' => $url));
623   }
624
625  /**
626    * Associates a given "handle" with FBML markup so that the handle can be
627    * used within the fb:ref FBML tag. A handle is unique within an application
628    * and allows an application to publish identical FBML to many user profiles
629    * and do subsequent updates without having to republish FBML on behalf of
630    * each user.
631    *
632    * @param string $handle  The handle to associate with the given FBML.
633    * @param string $fbml    The FBML to associate with the given handle.
634    *
635    * @return bool  true on success
636    */
637   public function &fbml_setRefHandle($handle, $fbml) {
638     return $this->call_method('facebook.fbml.setRefHandle',
639         array('handle' => $handle, 'fbml' => $fbml));
640   }
641
642   /**
643    * Register custom tags for the application. Custom tags can be used
644    * to extend the set of tags available to applications in FBML
645    * markup.
646    *
647    * Before you call this function,
648    * make sure you read the full documentation at
649    *
650    * http://wiki.developers.facebook.com/index.php/Fbml.RegisterCustomTags
651    *
652    * IMPORTANT: This function overwrites the values of
653    * existing tags if the names match. Use this function with care because
654    * it may break the FBML of any application that is using the
655    * existing version of the tags.
656    *
657    * @param mixed $tags an array of tag objects (the full description is on the
658    *   wiki page)
659    *
660    * @return int  the number of tags that were registered
661    */
662   public function &fbml_registerCustomTags($tags) {
663     $tags = json_encode($tags);
664     return $this->call_method('facebook.fbml.registerCustomTags',
665                               array('tags' => $tags));
666   }
667
668   /**
669    * Get the custom tags for an application. If $app_id
670    * is not specified, the calling app's tags are returned.
671    * If $app_id is different from the id of the calling app,
672    * only the app's public tags are returned.
673    * The return value is an array of the same type as
674    * the $tags parameter of fbml_registerCustomTags().
675    *
676    * @param int $app_id the application's id (optional)
677    *
678    * @return mixed  an array containing the custom tag  objects
679    */
680   public function &fbml_getCustomTags($app_id = null) {
681     return $this->call_method('facebook.fbml.getCustomTags',
682                               array('app_id' => $app_id));
683   }
684
685
686   /**
687    * Delete custom tags the application has registered. If
688    * $tag_names is null, all the application's custom tags will be
689    * deleted.
690    *
691    * IMPORTANT: If your application has registered public tags
692    * that other applications may be using, don't delete those tags!
693    * Doing so can break the FBML ofapplications that are using them.
694    *
695    * @param array $tag_names the names of the tags to delete (optinal)
696    * @return bool true on success
697    */
698   public function &fbml_deleteCustomTags($tag_names = null) {
699     return $this->call_method('facebook.fbml.deleteCustomTags',
700                               array('tag_names' => json_encode($tag_names)));
701   }
702
703   /**
704    * Gets the best translations for native strings submitted by an application
705    * for translation. If $locale is not specified, only native strings and their
706    * descriptions are returned. If $all is true, then unapproved translations
707    * are returned as well, otherwise only approved translations are returned.
708    *
709    * A mapping of locale codes -> language names is available at
710    * http://wiki.developers.facebook.com/index.php/Facebook_Locales
711    *
712    * @param string $locale the locale to get translations for, or 'all' for all
713    *                       locales, or 'en_US' for native strings
714    * @param bool   $all    whether to return all or only approved translations
715    *
716    * @return array (locale, array(native_strings, array('best translation
717    *                available given enough votes or manual approval', approval
718    *                                                                  status)))
719    * @error API_EC_PARAM
720    * @error API_EC_PARAM_BAD_LOCALE
721    */
722   public function &intl_getTranslations($locale = 'en_US', $all = false) {
723     return $this->call_method('facebook.intl.getTranslations',
724                               array('locale' => $locale,
725                                     'all'    => $all));
726   }
727
728   /**
729    * Lets you insert text strings in their native language into the Facebook
730    * Translations database so they can be translated.
731    *
732    * @param array $native_strings  An array of maps, where each map has a 'text'
733    *                               field and a 'description' field.
734    *
735    * @return int  Number of strings uploaded.
736    */
737   public function &intl_uploadNativeStrings($native_strings) {
738     return $this->call_method('facebook.intl.uploadNativeStrings',
739         array('native_strings' => json_encode($native_strings)));
740   }
741
742   /**
743    * This method is deprecated for calls made on behalf of users. This method
744    * works only for publishing stories on a Facebook Page that has installed
745    * your application. To publish stories to a user's profile, use
746    * feed.publishUserAction instead.
747    *
748    * For more details on this call, please visit the wiki page:
749    *
750    * http://wiki.developers.facebook.com/index.php/Feed.publishTemplatizedAction
751    */
752   public function &feed_publishTemplatizedAction($title_template,
753                                                  $title_data,
754                                                  $body_template,
755                                                  $body_data,
756                                                  $body_general,
757                                                  $image_1=null,
758                                                  $image_1_link=null,
759                                                  $image_2=null,
760                                                  $image_2_link=null,
761                                                  $image_3=null,
762                                                  $image_3_link=null,
763                                                  $image_4=null,
764                                                  $image_4_link=null,
765                                                  $target_ids='',
766                                                  $page_actor_id=null) {
767     return $this->call_method('facebook.feed.publishTemplatizedAction',
768       array('title_template' => $title_template,
769             'title_data' => $title_data,
770             'body_template' => $body_template,
771             'body_data' => $body_data,
772             'body_general' => $body_general,
773             'image_1' => $image_1,
774             'image_1_link' => $image_1_link,
775             'image_2' => $image_2,
776             'image_2_link' => $image_2_link,
777             'image_3' => $image_3,
778             'image_3_link' => $image_3_link,
779             'image_4' => $image_4,
780             'image_4_link' => $image_4_link,
781             'target_ids' => $target_ids,
782             'page_actor_id' => $page_actor_id));
783   }
784
785   /**
786    * Registers a template bundle.  Template bundles are somewhat involved, so
787    * it's recommended you check out the wiki for more details:
788    *
789    *  http://wiki.developers.facebook.com/index.php/Feed.registerTemplateBundle
790    *
791    * @return string  A template bundle id
792    */
793   public function &feed_registerTemplateBundle($one_line_story_templates,
794                                                $short_story_templates = array(),
795                                                $full_story_template = null,
796                                                $action_links = array()) {
797
798     $one_line_story_templates = json_encode($one_line_story_templates);
799
800     if (!empty($short_story_templates)) {
801       $short_story_templates = json_encode($short_story_templates);
802     }
803
804     if (isset($full_story_template)) {
805       $full_story_template = json_encode($full_story_template);
806     }
807
808     if (isset($action_links)) {
809       $action_links = json_encode($action_links);
810     }
811
812     return $this->call_method('facebook.feed.registerTemplateBundle',
813         array('one_line_story_templates' => $one_line_story_templates,
814               'short_story_templates' => $short_story_templates,
815               'full_story_template' => $full_story_template,
816               'action_links' => $action_links));
817   }
818
819   /**
820    * Retrieves the full list of active template bundles registered by the
821    * requesting application.
822    *
823    * @return array  An array of template bundles
824    */
825   public function &feed_getRegisteredTemplateBundles() {
826     return $this->call_method('facebook.feed.getRegisteredTemplateBundles',
827         array());
828   }
829
830   /**
831    * Retrieves information about a specified template bundle previously
832    * registered by the requesting application.
833    *
834    * @param string $template_bundle_id  The template bundle id
835    *
836    * @return array  Template bundle
837    */
838   public function &feed_getRegisteredTemplateBundleByID($template_bundle_id) {
839     return $this->call_method('facebook.feed.getRegisteredTemplateBundleByID',
840         array('template_bundle_id' => $template_bundle_id));
841   }
842
843   /**
844    * Deactivates a previously registered template bundle.
845    *
846    * @param string $template_bundle_id  The template bundle id
847    *
848    * @return bool  true on success
849    */
850   public function &feed_deactivateTemplateBundleByID($template_bundle_id) {
851     return $this->call_method('facebook.feed.deactivateTemplateBundleByID',
852         array('template_bundle_id' => $template_bundle_id));
853   }
854
855   const STORY_SIZE_ONE_LINE = 1;
856   const STORY_SIZE_SHORT = 2;
857   const STORY_SIZE_FULL = 4;
858
859   /**
860    * Publishes a story on behalf of the user owning the session, using the
861    * specified template bundle. This method requires an active session key in
862    * order to be called.
863    *
864    * The parameters to this method ($templata_data in particular) are somewhat
865    * involved.  It's recommended you visit the wiki for details:
866    *
867    *  http://wiki.developers.facebook.com/index.php/Feed.publishUserAction
868    *
869    * @param int $template_bundle_id  A template bundle id previously registered
870    * @param array $template_data     See wiki article for syntax
871    * @param array $target_ids        (Optional) An array of friend uids of the
872    *                                 user who shared in this action.
873    * @param string $body_general     (Optional) Additional markup that extends
874    *                                 the body of a short story.
875    * @param int $story_size          (Optional) A story size (see above)
876    * @param string $user_message     (Optional) A user message for a short
877    *                                 story.
878    *
879    * @return bool  true on success
880    */
881   public function &feed_publishUserAction(
882       $template_bundle_id, $template_data, $target_ids='', $body_general='',
883       $story_size=FacebookRestClient::STORY_SIZE_ONE_LINE,
884       $user_message='') {
885
886     if (is_array($template_data)) {
887       $template_data = json_encode($template_data);
888     } // allow client to either pass in JSON or an assoc that we JSON for them
889
890     if (is_array($target_ids)) {
891       $target_ids = json_encode($target_ids);
892       $target_ids = trim($target_ids, "[]"); // we don't want square brackets
893     }
894
895     return $this->call_method('facebook.feed.publishUserAction',
896         array('template_bundle_id' => $template_bundle_id,
897               'template_data' => $template_data,
898               'target_ids' => $target_ids,
899               'body_general' => $body_general,
900               'story_size' => $story_size,
901               'user_message' => $user_message));
902   }
903
904
905   /**
906    * Publish a post to the user's stream.
907    *
908    * @param $message        the user's message
909    * @param $attachment     the post's attachment (optional)
910    * @param $action links   the post's action links (optional)
911    * @param $target_id      the user on whose wall the post will be posted
912    *                        (optional)
913    * @param $uid            the actor (defaults to session user)
914    * @return string the post id
915    */
916   public function stream_publish(
917     $message, $attachment = null, $action_links = null, $target_id = null,
918     $uid = null) {
919
920     return $this->call_method(
921       'facebook.stream.publish',
922       array('message' => $message,
923             'attachment' => $attachment,
924             'action_links' => $action_links,
925             'target_id' => $target_id,
926             'uid' => $this->get_uid($uid)));
927   }
928
929   /**
930    * Remove a post from the user's stream.
931    * Currently, you may only remove stories you application created.
932    *
933    * @param $post_id  the post id
934    * @param $uid      the actor (defaults to session user)
935    * @return bool
936    */
937   public function stream_remove($post_id, $uid = null) {
938     return $this->call_method(
939       'facebook.stream.remove',
940       array('post_id' => $post_id,
941             'uid' => $this->get_uid($uid)));
942   }
943
944   /**
945    * Add a comment to a stream post
946    *
947    * @param $post_id  the post id
948    * @param $comment  the comment text
949    * @param $uid      the actor (defaults to session user)
950    * @return string the id of the created comment
951    */
952   public function stream_addComment($post_id, $comment, $uid = null) {
953     return $this->call_method(
954       'facebook.stream.addComment',
955       array('post_id' => $post_id,
956             'comment' => $comment,
957             'uid' => $this->get_uid($uid)));
958   }
959
960
961   /**
962    * Remove a comment from a stream post
963    *
964    * @param $comment_id  the comment id
965    * @param $uid      the actor (defaults to session user)
966    * @return bool
967    */
968   public function stream_removeComment($comment_id, $uid = null) {
969     return $this->call_method(
970       'facebook.stream.removeComment',
971       array('comment_id' => $comment_id,
972             'uid' => $this->get_uid($uid)));
973   }
974
975   /**
976    * Add a like to a stream post
977    *
978    * @param $post_id  the post id
979    * @param $uid      the actor (defaults to session user)
980    * @return bool
981    */
982   public function stream_addLike($post_id, $uid = null) {
983     return $this->call_method(
984       'facebook.stream.addLike',
985       array('post_id' => $post_id,
986             'uid' => $this->get_uid($uid)));
987   }
988
989   /**
990    * Remove a like from a stream post
991    *
992    * @param $post_id  the post id
993    * @param $uid      the actor (defaults to session user)
994    * @return bool
995    */
996   public function stream_removeLike($post_id, $uid = null) {
997     return $this->call_method(
998       'facebook.stream.removeLike',
999       array('post_id' => $post_id,
1000             'uid' => $this->get_uid($uid)));
1001   }
1002
1003   /**
1004    * For the current user, retrieves stories generated by the user's friends
1005    * while using this application.  This can be used to easily create a
1006    * "News Feed" like experience.
1007    *
1008    * @return array  An array of feed story objects.
1009    */
1010   public function &feed_getAppFriendStories() {
1011     return $this->call_method('facebook.feed.getAppFriendStories');
1012   }
1013
1014   /**
1015    * Makes an FQL query.  This is a generalized way of accessing all the data
1016    * in the API, as an alternative to most of the other method calls.  More
1017    * info at http://wiki.developers.facebook.com/index.php/FQL
1018    *
1019    * @param string $query  the query to evaluate
1020    *
1021    * @return array  generalized array representing the results
1022    */
1023   public function &fql_query($query) {
1024     return $this->call_method('facebook.fql.query',
1025       array('query' => $query));
1026   }
1027
1028   /**
1029    * Makes a set of FQL queries in parallel.  This method takes a dictionary
1030    * of FQL queries where the keys are names for the queries.  Results from
1031    * one query can be used within another query to fetch additional data.  More
1032    * info about FQL queries at http://wiki.developers.facebook.com/index.php/FQL
1033    *
1034    * @param string $queries  JSON-encoded dictionary of queries to evaluate
1035    *
1036    * @return array  generalized array representing the results
1037    */
1038   public function &fql_multiquery($queries) {
1039     return $this->call_method('facebook.fql.multiquery',
1040       array('queries' => $queries));
1041   }
1042
1043   /**
1044    * Returns whether or not pairs of users are friends.
1045    * Note that the Facebook friend relationship is symmetric.
1046    *
1047    * @param array/string $uids1  list of ids (id_1, id_2,...)
1048    *                       of some length X (csv is deprecated)
1049    * @param array/string $uids2  list of ids (id_A, id_B,...)
1050    *                       of SAME length X (csv is deprecated)
1051    *
1052    * @return array  An array with uid1, uid2, and bool if friends, e.g.:
1053    *   array(0 => array('uid1' => id_1, 'uid2' => id_A, 'are_friends' => 1),
1054    *         1 => array('uid1' => id_2, 'uid2' => id_B, 'are_friends' => 0)
1055    *         ...)
1056    * @error
1057    *    API_EC_PARAM_USER_ID_LIST
1058    */
1059   public function &friends_areFriends($uids1, $uids2) {
1060     return $this->call_method('facebook.friends.areFriends',
1061                  array('uids1' => $uids1,
1062                        'uids2' => $uids2));
1063   }
1064
1065   /**
1066    * Returns the friends of the current session user.
1067    *
1068    * @param int $flid  (Optional) Only return friends on this friend list.
1069    * @param int $uid   (Optional) Return friends for this user.
1070    *
1071    * @return array  An array of friends
1072    */
1073   public function &friends_get($flid=null, $uid = null) {
1074     if (isset($this->friends_list)) {
1075       return $this->friends_list;
1076     }
1077     $params = array();
1078     if (!$uid && isset($this->canvas_user)) {
1079       $uid = $this->canvas_user;
1080     }
1081     if ($uid) {
1082       $params['uid'] = $uid;
1083     }
1084     if ($flid) {
1085       $params['flid'] = $flid;
1086     }
1087     return $this->call_method('facebook.friends.get', $params);
1088
1089   }
1090
1091   /**
1092    * Returns the mutual friends between the target uid and a source uid or
1093    * the current session user.
1094    *
1095    * @param int $target_uid Target uid for which mutual friends will be found.
1096    * @param int $source_uid (optional) Source uid for which mutual friends will
1097    *                                   be found. If no source_uid is specified,
1098    *                                   source_id will default to the session
1099    *                                   user.
1100    * @return array  An array of friend uids
1101    */
1102   public function &friends_getMutualFriends($target_uid, $source_uid = null) {
1103     return $this->call_method('facebook.friends.getMutualFriends',
1104                               array("target_uid" => $target_uid,
1105                                     "source_uid" => $source_uid));
1106   }
1107
1108   /**
1109    * Returns the set of friend lists for the current session user.
1110    *
1111    * @return array  An array of friend list objects
1112    */
1113   public function &friends_getLists() {
1114     return $this->call_method('facebook.friends.getLists');
1115   }
1116
1117   /**
1118    * Returns the friends of the session user, who are also users
1119    * of the calling application.
1120    *
1121    * @return array  An array of friends also using the app
1122    */
1123   public function &friends_getAppUsers() {
1124     return $this->call_method('facebook.friends.getAppUsers');
1125   }
1126
1127   /**
1128    * Returns groups according to the filters specified.
1129    *
1130    * @param int $uid     (Optional) User associated with groups.  A null
1131    *                     parameter will default to the session user.
1132    * @param array/string $gids (Optional) Array of group ids to query. A null
1133    *                     parameter will get all groups for the user.
1134    *                     (csv is deprecated)
1135    *
1136    * @return array  An array of group objects
1137    */
1138   public function &groups_get($uid, $gids) {
1139     return $this->call_method('facebook.groups.get',
1140         array('uid' => $uid,
1141               'gids' => $gids));
1142   }
1143
1144   /**
1145    * Returns the membership list of a group.
1146    *
1147    * @param int $gid  Group id
1148    *
1149    * @return array  An array with four membership lists, with keys 'members',
1150    *                'admins', 'officers', and 'not_replied'
1151    */
1152   public function &groups_getMembers($gid) {
1153     return $this->call_method('facebook.groups.getMembers',
1154       array('gid' => $gid));
1155   }
1156
1157   /**
1158    * Returns cookies according to the filters specified.
1159    *
1160    * @param int $uid     User for which the cookies are needed.
1161    * @param string $name (Optional) A null parameter will get all cookies
1162    *                     for the user.
1163    *
1164    * @return array  Cookies!  Nom nom nom nom nom.
1165    */
1166   public function data_getCookies($uid, $name) {
1167     return $this->call_method('facebook.data.getCookies',
1168         array('uid' => $uid,
1169               'name' => $name));
1170   }
1171
1172   /**
1173    * Sets cookies according to the params specified.
1174    *
1175    * @param int $uid       User for which the cookies are needed.
1176    * @param string $name   Name of the cookie
1177    * @param string $value  (Optional) if expires specified and is in the past
1178    * @param int $expires   (Optional) Expiry time
1179    * @param string $path   (Optional) Url path to associate with (default is /)
1180    *
1181    * @return bool  true on success
1182    */
1183   public function data_setCookie($uid, $name, $value, $expires, $path) {
1184     return $this->call_method('facebook.data.setCookie',
1185         array('uid' => $uid,
1186               'name' => $name,
1187               'value' => $value,
1188               'expires' => $expires,
1189               'path' => $path));
1190   }
1191
1192   /**
1193    * Retrieves links posted by the given user.
1194    *
1195    * @param int    $uid      The user whose links you wish to retrieve
1196    * @param int    $limit    The maximimum number of links to retrieve
1197    * @param array $link_ids (Optional) Array of specific link
1198    *                          IDs to retrieve by this user
1199    *
1200    * @return array  An array of links.
1201    */
1202   public function &links_get($uid, $limit, $link_ids = null) {
1203     return $this->call_method('links.get',
1204         array('uid' => $uid,
1205               'limit' => $limit,
1206               'link_ids' => $link_ids));
1207   }
1208
1209   /**
1210    * Posts a link on Facebook.
1211    *
1212    * @param string $url     URL/link you wish to post
1213    * @param string $comment (Optional) A comment about this link
1214    * @param int    $uid     (Optional) User ID that is posting this link;
1215    *                        defaults to current session user
1216    *
1217    * @return bool
1218    */
1219   public function &links_post($url, $comment='', $uid = null) {
1220     return $this->call_method('links.post',
1221         array('uid' => $uid,
1222               'url' => $url,
1223               'comment' => $comment));
1224   }
1225
1226   /**
1227    * Permissions API
1228    */
1229
1230   /**
1231    * Checks API-access granted by self to the specified application.
1232    *
1233    * @param string $permissions_apikey  Other application key
1234    *
1235    * @return array  API methods/namespaces which are allowed access
1236    */
1237   public function permissions_checkGrantedApiAccess($permissions_apikey) {
1238     return $this->call_method('facebook.permissions.checkGrantedApiAccess',
1239         array('permissions_apikey' => $permissions_apikey));
1240   }
1241
1242   /**
1243    * Checks API-access granted to self by the specified application.
1244    *
1245    * @param string $permissions_apikey  Other application key
1246    *
1247    * @return array  API methods/namespaces which are allowed access
1248    */
1249   public function permissions_checkAvailableApiAccess($permissions_apikey) {
1250     return $this->call_method('facebook.permissions.checkAvailableApiAccess',
1251         array('permissions_apikey' => $permissions_apikey));
1252   }
1253
1254   /**
1255    * Grant API-access to the specified methods/namespaces to the specified
1256    * application.
1257    *
1258    * @param string $permissions_apikey  Other application key
1259    * @param array(string) $method_arr   (Optional) API methods/namespaces
1260    *                                    allowed
1261    *
1262    * @return array  API methods/namespaces which are allowed access
1263    */
1264   public function permissions_grantApiAccess($permissions_apikey, $method_arr) {
1265     return $this->call_method('facebook.permissions.grantApiAccess',
1266         array('permissions_apikey' => $permissions_apikey,
1267               'method_arr' => $method_arr));
1268   }
1269
1270   /**
1271    * Revoke API-access granted to the specified application.
1272    *
1273    * @param string $permissions_apikey  Other application key
1274    *
1275    * @return bool  true on success
1276    */
1277   public function permissions_revokeApiAccess($permissions_apikey) {
1278     return $this->call_method('facebook.permissions.revokeApiAccess',
1279         array('permissions_apikey' => $permissions_apikey));
1280   }
1281
1282   /**
1283    * Payments Order API
1284    */
1285
1286   /**
1287    * Set Payments properties for an app.
1288    *
1289    * @param  properties  a map from property names to  values
1290    * @return             true on success
1291    */
1292   public function payments_setProperties($properties) {
1293     return $this->call_method ('facebook.payments.setProperties',
1294         array('properties' => json_encode($properties)));
1295   }
1296
1297   public function payments_getOrderDetails($order_id) {
1298     return json_decode($this->call_method(
1299         'facebook.payments.getOrderDetails',
1300         array('order_id' => $order_id)), true);
1301   }
1302
1303   public function payments_updateOrder($order_id, $status,
1304                                          $params) {
1305     return $this->call_method('facebook.payments.updateOrder',
1306         array('order_id' => $order_id,
1307               'status' => $status,
1308               'params' => json_encode($params)));
1309   }
1310
1311   public function payments_getOrders($status, $start_time,
1312                                        $end_time, $test_mode=false) {
1313     return json_decode($this->call_method('facebook.payments.getOrders',
1314         array('status' => $status,
1315               'start_time' => $start_time,
1316               'end_time' => $end_time,
1317               'test_mode' => $test_mode)), true);
1318   }
1319
1320   /**
1321    * Gifts API
1322    */
1323
1324   /**
1325    * Get Gifts associated with an app
1326    *
1327    * @return             array of gifts
1328    */
1329   public function gifts_get() {
1330     return json_decode(
1331         $this->call_method('facebook.gifts.get',
1332                            array()),
1333         true
1334         );
1335   }
1336
1337   /*
1338    * Update gifts stored by an app
1339    *
1340    * @param array containing gift_id => gift_data to be updated
1341    * @return array containing gift_id => true/false indicating success
1342    *                                     in updating that gift
1343    */
1344   public function gifts_update($update_array) {
1345     return json_decode(
1346       $this->call_method('facebook.gifts.update',
1347                          array('update_str' => json_encode($update_array))
1348                         ),
1349       true
1350     );
1351   }
1352
1353   /**
1354    * Dashboard API
1355    */
1356
1357   /**
1358    * Set the news for the specified user.
1359    *
1360    * @param int    $uid     The user for whom you are setting news for
1361    * @param string $news    Text of news to display
1362    *
1363    * @return bool   Success
1364    */
1365   public function dashboard_setNews($uid, $news) {
1366     return $this->call_method('facebook.dashboard.setNews',
1367                               array('uid'  => $uid,
1368                                     'news' => $news)
1369                              );
1370   }
1371
1372   /**
1373    * Get the current news of the specified user.
1374    *
1375    * @param int    $uid     The user to get the news of
1376    *
1377    * @return string   The text of the current news for the user
1378    */
1379   public function dashboard_getNews($uid) {
1380     return json_decode(
1381       $this->call_method('facebook.dashboard.getNews',
1382                          array('uid' => $uid)
1383                         ), true);
1384   }
1385
1386   /**
1387    * Set the news for the specified user.
1388    *
1389    * @param int    $uid     The user you are clearing the news of
1390    *
1391    * @return bool   Success
1392    */
1393   public function dashboard_clearNews($uid) {
1394     return $this->call_method('facebook.dashboard.clearNews',
1395                               array('uid' => $uid)
1396                              );
1397   }
1398
1399
1400
1401   /**
1402    * Creates a note with the specified title and content.
1403    *
1404    * @param string $title   Title of the note.
1405    * @param string $content Content of the note.
1406    * @param int    $uid     (Optional) The user for whom you are creating a
1407    *                        note; defaults to current session user
1408    *
1409    * @return int   The ID of the note that was just created.
1410    */
1411   public function &notes_create($title, $content, $uid = null) {
1412     return $this->call_method('notes.create',
1413         array('uid' => $uid,
1414               'title' => $title,
1415               'content' => $content));
1416   }
1417
1418   /**
1419    * Deletes the specified note.
1420    *
1421    * @param int $note_id  ID of the note you wish to delete
1422    * @param int $uid      (Optional) Owner of the note you wish to delete;
1423    *                      defaults to current session user
1424    *
1425    * @return bool
1426    */
1427   public function &notes_delete($note_id, $uid = null) {
1428     return $this->call_method('notes.delete',
1429         array('uid' => $uid,
1430               'note_id' => $note_id));
1431   }
1432
1433   /**
1434    * Edits a note, replacing its title and contents with the title
1435    * and contents specified.
1436    *
1437    * @param int    $note_id  ID of the note you wish to edit
1438    * @param string $title    Replacement title for the note
1439    * @param string $content  Replacement content for the note
1440    * @param int    $uid      (Optional) Owner of the note you wish to edit;
1441    *                         defaults to current session user
1442    *
1443    * @return bool
1444    */
1445   public function &notes_edit($note_id, $title, $content, $uid = null) {
1446     return $this->call_method('notes.edit',
1447         array('uid' => $uid,
1448               'note_id' => $note_id,
1449               'title' => $title,
1450               'content' => $content));
1451   }
1452
1453   /**
1454    * Retrieves all notes by a user. If note_ids are specified,
1455    * retrieves only those specific notes by that user.
1456    *
1457    * @param int    $uid      User whose notes you wish to retrieve
1458    * @param array  $note_ids (Optional) List of specific note
1459    *                         IDs by this user to retrieve
1460    *
1461    * @return array A list of all of the given user's notes, or an empty list
1462    *               if the viewer lacks permissions or if there are no visible
1463    *               notes.
1464    */
1465   public function &notes_get($uid, $note_ids = null) {
1466     return $this->call_method('notes.get',
1467         array('uid' => $uid,
1468               'note_ids' => $note_ids));
1469   }
1470
1471
1472   /**
1473    * Returns the outstanding notifications for the session user.
1474    *
1475    * @return array An assoc array of notification count objects for
1476    *               'messages', 'pokes' and 'shares', a uid list of
1477    *               'friend_requests', a gid list of 'group_invites',
1478    *               and an eid list of 'event_invites'
1479    */
1480   public function &notifications_get() {
1481     return $this->call_method('facebook.notifications.get');
1482   }
1483
1484   /**
1485    * Sends a notification to the specified users.
1486    *
1487    * @return A comma separated list of successful recipients
1488    * @error
1489    *    API_EC_PARAM_USER_ID_LIST
1490    */
1491   public function &notifications_send($to_ids, $notification, $type) {
1492     return $this->call_method('facebook.notifications.send',
1493         array('to_ids' => $to_ids,
1494               'notification' => $notification,
1495               'type' => $type));
1496   }
1497
1498   /**
1499    * Sends an email to the specified user of the application.
1500    *
1501    * @param array/string $recipients array of ids of the recipients (csv is deprecated)
1502    * @param string $subject    subject of the email
1503    * @param string $text       (plain text) body of the email
1504    * @param string $fbml       fbml markup for an html version of the email
1505    *
1506    * @return string  A comma separated list of successful recipients
1507    * @error
1508    *    API_EC_PARAM_USER_ID_LIST
1509    */
1510   public function &notifications_sendEmail($recipients,
1511                                            $subject,
1512                                            $text,
1513                                            $fbml) {
1514     return $this->call_method('facebook.notifications.sendEmail',
1515         array('recipients' => $recipients,
1516               'subject' => $subject,
1517               'text' => $text,
1518               'fbml' => $fbml));
1519   }
1520
1521   /**
1522    * Returns the requested info fields for the requested set of pages.
1523    *
1524    * @param array/string $page_ids  an array of page ids (csv is deprecated)
1525    * @param array/string  $fields    an array of strings describing the
1526    *                           info fields desired (csv is deprecated)
1527    * @param int    $uid       (Optional) limit results to pages of which this
1528    *                          user is a fan.
1529    * @param string type       limits results to a particular type of page.
1530    *
1531    * @return array  An array of pages
1532    */
1533   public function &pages_getInfo($page_ids, $fields, $uid, $type) {
1534     return $this->call_method('facebook.pages.getInfo',
1535         array('page_ids' => $page_ids,
1536               'fields' => $fields,
1537               'uid' => $uid,
1538               'type' => $type));
1539   }
1540
1541   /**
1542    * Returns true if the given user is an admin for the passed page.
1543    *
1544    * @param int $page_id  target page id
1545    * @param int $uid      (Optional) user id (defaults to the logged-in user)
1546    *
1547    * @return bool  true on success
1548    */
1549   public function &pages_isAdmin($page_id, $uid = null) {
1550     return $this->call_method('facebook.pages.isAdmin',
1551         array('page_id' => $page_id,
1552               'uid' => $uid));
1553   }
1554
1555   /**
1556    * Returns whether or not the given page has added the application.
1557    *
1558    * @param int $page_id  target page id
1559    *
1560    * @return bool  true on success
1561    */
1562   public function &pages_isAppAdded($page_id) {
1563     return $this->call_method('facebook.pages.isAppAdded',
1564         array('page_id' => $page_id));
1565   }
1566
1567   /**
1568    * Returns true if logged in user is a fan for the passed page.
1569    *
1570    * @param int $page_id target page id
1571    * @param int $uid user to compare.  If empty, the logged in user.
1572    *
1573    * @return bool  true on success
1574    */
1575   public function &pages_isFan($page_id, $uid = null) {
1576     return $this->call_method('facebook.pages.isFan',
1577         array('page_id' => $page_id,
1578               'uid' => $uid));
1579   }
1580
1581   /**
1582    * Adds a tag with the given information to a photo. See the wiki for details:
1583    *
1584    *  http://wiki.developers.facebook.com/index.php/Photos.addTag
1585    *
1586    * @param int $pid          The ID of the photo to be tagged
1587    * @param int $tag_uid      The ID of the user being tagged. You must specify
1588    *                          either the $tag_uid or the $tag_text parameter
1589    *                          (unless $tags is specified).
1590    * @param string $tag_text  Some text identifying the person being tagged.
1591    *                          You must specify either the $tag_uid or $tag_text
1592    *                          parameter (unless $tags is specified).
1593    * @param float $x          The horizontal position of the tag, as a
1594    *                          percentage from 0 to 100, from the left of the
1595    *                          photo.
1596    * @param float $y          The vertical position of the tag, as a percentage
1597    *                          from 0 to 100, from the top of the photo.
1598    * @param array $tags       (Optional) An array of maps, where each map
1599    *                          can contain the tag_uid, tag_text, x, and y
1600    *                          parameters defined above.  If specified, the
1601    *                          individual arguments are ignored.
1602    * @param int $owner_uid    (Optional)  The user ID of the user whose photo
1603    *                          you are tagging. If this parameter is not
1604    *                          specified, then it defaults to the session user.
1605    *
1606    * @return bool  true on success
1607    */
1608   public function &photos_addTag($pid,
1609                                  $tag_uid,
1610                                  $tag_text,
1611                                  $x,
1612                                  $y,
1613                                  $tags,
1614                                  $owner_uid=0) {
1615     return $this->call_method('facebook.photos.addTag',
1616         array('pid' => $pid,
1617               'tag_uid' => $tag_uid,
1618               'tag_text' => $tag_text,
1619               'x' => $x,
1620               'y' => $y,
1621               'tags' => (is_array($tags)) ? json_encode($tags) : null,
1622               'owner_uid' => $this->get_uid($owner_uid)));
1623   }
1624
1625   /**
1626    * Creates and returns a new album owned by the specified user or the current
1627    * session user.
1628    *
1629    * @param string $name         The name of the album.
1630    * @param string $description  (Optional) A description of the album.
1631    * @param string $location     (Optional) A description of the location.
1632    * @param string $visible      (Optional) A privacy setting for the album.
1633    *                             One of 'friends', 'friends-of-friends',
1634    *                             'networks', or 'everyone'.  Default 'everyone'.
1635    * @param int $uid             (Optional) User id for creating the album; if
1636    *                             not specified, the session user is used.
1637    *
1638    * @return array  An album object
1639    */
1640   public function &photos_createAlbum($name,
1641                                       $description='',
1642                                       $location='',
1643                                       $visible='',
1644                                       $uid=0) {
1645     return $this->call_method('facebook.photos.createAlbum',
1646         array('name' => $name,
1647               'description' => $description,
1648               'location' => $location,
1649               'visible' => $visible,
1650               'uid' => $this->get_uid($uid)));
1651   }
1652
1653   /**
1654    * Returns photos according to the filters specified.
1655    *
1656    * @param int $subj_id  (Optional) Filter by uid of user tagged in the photos.
1657    * @param int $aid      (Optional) Filter by an album, as returned by
1658    *                      photos_getAlbums.
1659    * @param array/string $pids   (Optional) Restrict to an array of pids
1660    *                             (csv is deprecated)
1661    *
1662    * Note that at least one of these parameters needs to be specified, or an
1663    * error is returned.
1664    *
1665    * @return array  An array of photo objects.
1666    */
1667   public function &photos_get($subj_id, $aid, $pids) {
1668     return $this->call_method('facebook.photos.get',
1669       array('subj_id' => $subj_id, 'aid' => $aid, 'pids' => $pids));
1670   }
1671
1672   /**
1673    * Returns the albums created by the given user.
1674    *
1675    * @param int $uid      (Optional) The uid of the user whose albums you want.
1676    *                       A null will return the albums of the session user.
1677    * @param string $aids  (Optional) An array of aids to restrict
1678    *                       the query. (csv is deprecated)
1679    *
1680    * Note that at least one of the (uid, aids) parameters must be specified.
1681    *
1682    * @returns an array of album objects.
1683    */
1684   public function &photos_getAlbums($uid, $aids) {
1685     return $this->call_method('facebook.photos.getAlbums',
1686       array('uid' => $uid,
1687             'aids' => $aids));
1688   }
1689
1690   /**
1691    * Returns the tags on all photos specified.
1692    *
1693    * @param string $pids  A list of pids to query
1694    *
1695    * @return array  An array of photo tag objects, which include pid,
1696    *                subject uid, and two floating-point numbers (xcoord, ycoord)
1697    *                for tag pixel location.
1698    */
1699   public function &photos_getTags($pids) {
1700     return $this->call_method('facebook.photos.getTags',
1701       array('pids' => $pids));
1702   }
1703
1704   /**
1705    * Uploads a photo.
1706    *
1707    * @param string $file     The location of the photo on the local filesystem.
1708    * @param int $aid         (Optional) The album into which to upload the
1709    *                         photo.
1710    * @param string $caption  (Optional) A caption for the photo.
1711    * @param int uid          (Optional) The user ID of the user whose photo you
1712    *                         are uploading
1713    *
1714    * @return array  An array of user objects
1715    */
1716   public function photos_upload($file, $aid=null, $caption=null, $uid=null) {
1717     return $this->call_upload_method('facebook.photos.upload',
1718                                      array('aid' => $aid,
1719                                            'caption' => $caption,
1720                                            'uid' => $uid),
1721                                      $file);
1722   }
1723
1724
1725   /**
1726    * Uploads a video.
1727    *
1728    * @param  string $file        The location of the video on the local filesystem.
1729    * @param  string $title       (Optional) A title for the video. Titles over 65 characters in length will be truncated.
1730    * @param  string $description (Optional) A description for the video.
1731    *
1732    * @return array  An array with the video's ID, title, description, and a link to view it on Facebook.
1733    */
1734   public function video_upload($file, $title=null, $description=null) {
1735     return $this->call_upload_method('facebook.video.upload',
1736                                      array('title' => $title,
1737                                            'description' => $description),
1738                                      $file,
1739                                      Facebook::get_facebook_url('api-video') . '/restserver.php');
1740   }
1741
1742   /**
1743    * Returns an array with the video limitations imposed on the current session's
1744    * associated user. Maximum length is measured in seconds; maximum size is
1745    * measured in bytes.
1746    *
1747    * @return array  Array with "length" and "size" keys
1748    */
1749   public function &video_getUploadLimits() {
1750     return $this->call_method('facebook.video.getUploadLimits');
1751   }
1752
1753   /**
1754    * Returns the requested info fields for the requested set of users.
1755    *
1756    * @param array/string $uids    An array of user ids (csv is deprecated)
1757    * @param array/string $fields  An array of info field names desired (csv is deprecated)
1758    *
1759    * @return array  An array of user objects
1760    */
1761   public function &users_getInfo($uids, $fields) {
1762     return $this->call_method('facebook.users.getInfo',
1763                   array('uids' => $uids,
1764                         'fields' => $fields));
1765   }
1766
1767   /**
1768    * Returns the requested info fields for the requested set of users. A
1769    * session key must not be specified. Only data about users that have
1770    * authorized your application will be returned.
1771    *
1772    * Check the wiki for fields that can be queried through this API call.
1773    * Data returned from here should not be used for rendering to application
1774    * users, use users.getInfo instead, so that proper privacy rules will be
1775    * applied.
1776    *
1777    * @param array/string $uids    An array of user ids (csv is deprecated)
1778    * @param array/string $fields  An array of info field names desired (csv is deprecated)
1779    *
1780    * @return array  An array of user objects
1781    */
1782   public function &users_getStandardInfo($uids, $fields) {
1783     return $this->call_method('facebook.users.getStandardInfo',
1784                               array('uids' => $uids,
1785                                     'fields' => $fields));
1786   }
1787
1788   /**
1789    * Returns the user corresponding to the current session object.
1790    *
1791    * @return integer  User id
1792    */
1793   public function &users_getLoggedInUser() {
1794     return $this->call_method('facebook.users.getLoggedInUser');
1795   }
1796
1797   /**
1798    * Returns 1 if the user has the specified permission, 0 otherwise.
1799    * http://wiki.developers.facebook.com/index.php/Users.hasAppPermission
1800    *
1801    * @return integer  1 or 0
1802    */
1803   public function &users_hasAppPermission($ext_perm, $uid=null) {
1804     return $this->call_method('facebook.users.hasAppPermission',
1805         array('ext_perm' => $ext_perm, 'uid' => $uid));
1806   }
1807
1808   /**
1809    * Returns whether or not the user corresponding to the current
1810    * session object has the give the app basic authorization.
1811    *
1812    * @return boolean  true if the user has authorized the app
1813    */
1814   public function &users_isAppUser($uid=null) {
1815     if ($uid === null && isset($this->is_user)) {
1816       return $this->is_user;
1817     }
1818
1819     return $this->call_method('facebook.users.isAppUser', array('uid' => $uid));
1820   }
1821
1822   /**
1823    * Returns whether or not the user corresponding to the current
1824    * session object is verified by Facebook. See the documentation
1825    * for Users.isVerified for details.
1826    *
1827    * @return boolean  true if the user is verified
1828    */
1829   public function &users_isVerified() {
1830     return $this->call_method('facebook.users.isVerified');
1831   }
1832
1833   /**
1834    * Sets the users' current status message. Message does NOT contain the
1835    * word "is" , so make sure to include a verb.
1836    *
1837    * Example: setStatus("is loving the API!")
1838    * will produce the status "Luke is loving the API!"
1839    *
1840    * @param string $status                text-only message to set
1841    * @param int    $uid                   user to set for (defaults to the
1842    *                                      logged-in user)
1843    * @param bool   $clear                 whether or not to clear the status,
1844    *                                      instead of setting it
1845    * @param bool   $status_includes_verb  if true, the word "is" will *not* be
1846    *                                      prepended to the status message
1847    *
1848    * @return boolean
1849    */
1850   public function &users_setStatus($status,
1851                                    $uid = null,
1852                                    $clear = false,
1853                                    $status_includes_verb = true) {
1854     $args = array(
1855       'status' => $status,
1856       'uid' => $uid,
1857       'clear' => $clear,
1858       'status_includes_verb' => $status_includes_verb,
1859     );
1860     return $this->call_method('facebook.users.setStatus', $args);
1861   }
1862
1863   /**
1864    * Gets the comments for a particular xid. This is essentially a wrapper
1865    * around the comment FQL table.
1866    *
1867    * @param string $xid external id associated with the comments
1868    *
1869    * @return array of comment objects
1870    */
1871   public function &comments_get($xid) {
1872     $args = array('xid' => $xid);
1873     return $this->call_method('facebook.comments.get', $args);
1874   }
1875
1876   /**
1877    * Add a comment to a particular xid on behalf of a user. If called
1878    * without an app_secret (with session secret), this will only work
1879    * for the session user.
1880    *
1881    * @param string $xid   external id associated with the comments
1882    * @param string $text  text of the comment
1883    * @param int    $uid   user adding the comment (def: session user)
1884    * @param string $title optional title for the stream story
1885    * @param string $url   optional url for the stream story
1886    * @param bool   $publish_to_stream publish a feed story about this comment?
1887    *                      a link will be generated to title/url in the story
1888    *
1889    * @return string comment_id associated with the comment
1890    */
1891   public function &comments_add($xid, $text, $uid=0, $title='', $url='',
1892                                 $publish_to_stream=false) {
1893     $args = array(
1894       'xid'               => $xid,
1895       'uid'               => $this->get_uid($uid),
1896       'text'              => $text,
1897       'title'             => $title,
1898       'url'               => $url,
1899       'publish_to_stream' => $publish_to_stream);
1900
1901     return $this->call_method('facebook.comments.add', $args);
1902   }
1903
1904   /**
1905    * Remove a particular comment.
1906    *
1907    * @param string $xid        the external id associated with the comments
1908    * @param string $comment_id id of the comment to remove (returned by
1909    *                           comments.add and comments.get)
1910    *
1911    * @return boolean
1912    */
1913   public function &comments_remove($xid, $comment_id) {
1914     $args = array(
1915       'xid'        => $xid,
1916       'comment_id' => $comment_id);
1917     return $this->call_method('facebook.comments.remove', $args);
1918   }
1919
1920   /**
1921    * Gets the stream on behalf of a user using a set of users. This
1922    * call will return the latest $limit queries between $start_time
1923    * and $end_time.
1924    *
1925    * @param int    $viewer_id  user making the call (def: session)
1926    * @param array  $source_ids users/pages to look at (def: all connections)
1927    * @param int    $start_time start time to look for stories (def: 1 day ago)
1928    * @param int    $end_time   end time to look for stories (def: now)
1929    * @param int    $limit      number of stories to attempt to fetch (def: 30)
1930    * @param string $filter_key key returned by stream.getFilters to fetch
1931    * @param array  $metadata   metadata to include with the return, allows
1932    *                           requested metadata to be returned, such as
1933    *                           profiles, albums, photo_tags
1934    *
1935    * @return array(
1936    *           'posts'      => array of posts,
1937    *           // if requested, the following data may be returned
1938    *           'profiles'   => array of profile metadata of users/pages in posts
1939    *           'albums'     => array of album metadata in posts
1940    *           'photo_tags' => array of photo_tags for photos in posts
1941    *         )
1942    */
1943   public function &stream_get($viewer_id = null,
1944                               $source_ids = null,
1945                               $start_time = 0,
1946                               $end_time = 0,
1947                               $limit = 30,
1948                               $filter_key = '',
1949                               $exportable_only = false,
1950                               $metadata = null,
1951                               $post_ids = null) {
1952     $args = array(
1953       'viewer_id'  => $viewer_id,
1954       'source_ids' => $source_ids,
1955       'start_time' => $start_time,
1956       'end_time'   => $end_time,
1957       'limit'      => $limit,
1958       'filter_key' => $filter_key,
1959       'exportable_only' => $exportable_only,
1960       'metadata' => $metadata,
1961       'post_ids' => $post_ids);
1962     return $this->call_method('facebook.stream.get', $args);
1963   }
1964
1965   /**
1966    * Gets the filters (with relevant filter keys for stream.get) for a
1967    * particular user. These filters are typical things like news feed,
1968    * friend lists, networks. They can be used to filter the stream
1969    * without complex queries to determine which ids belong in which groups.
1970    *
1971    * @param int $uid user to get filters for
1972    *
1973    * @return array of stream filter objects
1974    */
1975   public function &stream_getFilters($uid = null) {
1976     $args = array('uid' => $uid);
1977     return $this->call_method('facebook.stream.getFilters', $args);
1978   }
1979
1980   /**
1981    * Gets the full comments given a post_id from stream.get or the
1982    * stream FQL table. Initially, only a set of preview comments are
1983    * returned because some posts can have many comments.
1984    *
1985    * @param string $post_id id of the post to get comments for
1986    *
1987    * @return array of comment objects
1988    */
1989   public function &stream_getComments($post_id) {
1990     $args = array('post_id' => $post_id);
1991     return $this->call_method('facebook.stream.getComments', $args);
1992   }
1993
1994   /**
1995    * Sets the FBML for the profile of the user attached to this session.
1996    *
1997    * @param   string   $markup           The FBML that describes the profile
1998    *                                     presence of this app for the user
1999    * @param   int      $uid              The user
2000    * @param   string   $profile          Profile FBML
2001    * @param   string   $profile_action   Profile action FBML (deprecated)
2002    * @param   string   $mobile_profile   Mobile profile FBML
2003    * @param   string   $profile_main     Main Tab profile FBML
2004    *
2005    * @return  array  A list of strings describing any compile errors for the
2006    *                 submitted FBML
2007    */
2008   function profile_setFBML($markup,
2009                            $uid=null,
2010                            $profile='',
2011                            $profile_action='',
2012                            $mobile_profile='',
2013                            $profile_main='') {
2014     return $this->call_method('facebook.profile.setFBML',
2015         array('markup' => $markup,
2016               'uid' => $uid,
2017               'profile' => $profile,
2018               'profile_action' => $profile_action,
2019               'mobile_profile' => $mobile_profile,
2020               'profile_main' => $profile_main));
2021   }
2022
2023   /**
2024    * Gets the FBML for the profile box that is currently set for a user's
2025    * profile (your application set the FBML previously by calling the
2026    * profile.setFBML method).
2027    *
2028    * @param int $uid   (Optional) User id to lookup; defaults to session.
2029    * @param int $type  (Optional) 1 for original style, 2 for profile_main boxes
2030    *
2031    * @return string  The FBML
2032    */
2033   public function &profile_getFBML($uid=null, $type=null) {
2034     return $this->call_method('facebook.profile.getFBML',
2035         array('uid' => $uid,
2036               'type' => $type));
2037   }
2038
2039   /**
2040    * Returns the specified user's application info section for the calling
2041    * application. These info sections have either been set via a previous
2042    * profile.setInfo call or by the user editing them directly.
2043    *
2044    * @param int $uid  (Optional) User id to lookup; defaults to session.
2045    *
2046    * @return array  Info fields for the current user.  See wiki for structure:
2047    *
2048    *  http://wiki.developers.facebook.com/index.php/Profile.getInfo
2049    *
2050    */
2051   public function &profile_getInfo($uid=null) {
2052     return $this->call_method('facebook.profile.getInfo',
2053         array('uid' => $uid));
2054   }
2055
2056   /**
2057    * Returns the options associated with the specified info field for an
2058    * application info section.
2059    *
2060    * @param string $field  The title of the field
2061    *
2062    * @return array  An array of info options.
2063    */
2064   public function &profile_getInfoOptions($field) {
2065     return $this->call_method('facebook.profile.getInfoOptions',
2066         array('field' => $field));
2067   }
2068
2069   /**
2070    * Configures an application info section that the specified user can install
2071    * on the Info tab of her profile.  For details on the structure of an info
2072    * field, please see:
2073    *
2074    *  http://wiki.developers.facebook.com/index.php/Profile.setInfo
2075    *
2076    * @param string $title       Title / header of the info section
2077    * @param int $type           1 for text-only, 5 for thumbnail views
2078    * @param array $info_fields  An array of info fields. See wiki for details.
2079    * @param int $uid            (Optional)
2080    *
2081    * @return bool  true on success
2082    */
2083   public function &profile_setInfo($title, $type, $info_fields, $uid=null) {
2084     return $this->call_method('facebook.profile.setInfo',
2085         array('uid' => $uid,
2086               'type' => $type,
2087               'title'   => $title,
2088               'info_fields' => json_encode($info_fields)));
2089   }
2090
2091   /**
2092    * Specifies the objects for a field for an application info section. These
2093    * options populate the typeahead for a thumbnail.
2094    *
2095    * @param string $field   The title of the field
2096    * @param array $options  An array of items for a thumbnail, including
2097    *                        'label', 'link', and optionally 'image',
2098    *                        'description' and 'sublabel'
2099    *
2100    * @return bool  true on success
2101    */
2102   public function profile_setInfoOptions($field, $options) {
2103     return $this->call_method('facebook.profile.setInfoOptions',
2104         array('field'   => $field,
2105               'options' => json_encode($options)));
2106   }
2107
2108   /////////////////////////////////////////////////////////////////////////////
2109   // Data Store API
2110
2111   /**
2112    * Set a user preference.
2113    *
2114    * @param  pref_id    preference identifier (0-200)
2115    * @param  value      preferece's value
2116    * @param  uid        the user id (defaults to current session user)
2117    * @error
2118    *    API_EC_DATA_DATABASE_ERROR
2119    *    API_EC_PARAM
2120    *    API_EC_DATA_QUOTA_EXCEEDED
2121    *    API_EC_DATA_UNKNOWN_ERROR
2122    *    API_EC_PERMISSION_OTHER_USER
2123    */
2124   public function &data_setUserPreference($pref_id, $value, $uid = null) {
2125     return $this->call_method('facebook.data.setUserPreference',
2126        array('pref_id' => $pref_id,
2127              'value' => $value,
2128              'uid' => $this->get_uid($uid)));
2129   }
2130
2131   /**
2132    * Set a user's all preferences for this application.
2133    *
2134    * @param  values     preferece values in an associative arrays
2135    * @param  replace    whether to replace all existing preferences or
2136    *                    merge into them.
2137    * @param  uid        the user id (defaults to current session user)
2138    * @error
2139    *    API_EC_DATA_DATABASE_ERROR
2140    *    API_EC_PARAM
2141    *    API_EC_DATA_QUOTA_EXCEEDED
2142    *    API_EC_DATA_UNKNOWN_ERROR
2143    *    API_EC_PERMISSION_OTHER_USER
2144    */
2145   public function &data_setUserPreferences($values,
2146                                            $replace = false,
2147                                            $uid = null) {
2148     return $this->call_method('facebook.data.setUserPreferences',
2149        array('values' => json_encode($values),
2150              'replace' => $replace,
2151              'uid' => $this->get_uid($uid)));
2152   }
2153
2154   /**
2155    * Get a user preference.
2156    *
2157    * @param  pref_id    preference identifier (0-200)
2158    * @param  uid        the user id (defaults to current session user)
2159    * @return            preference's value
2160    * @error
2161    *    API_EC_DATA_DATABASE_ERROR
2162    *    API_EC_PARAM
2163    *    API_EC_DATA_QUOTA_EXCEEDED
2164    *    API_EC_DATA_UNKNOWN_ERROR
2165    *    API_EC_PERMISSION_OTHER_USER
2166    */
2167   public function &data_getUserPreference($pref_id, $uid = null) {
2168     return $this->call_method('facebook.data.getUserPreference',
2169        array('pref_id' => $pref_id,
2170              'uid' => $this->get_uid($uid)));
2171   }
2172
2173   /**
2174    * Get a user preference.
2175    *
2176    * @param  uid        the user id (defaults to current session user)
2177    * @return            preference values
2178    * @error
2179    *    API_EC_DATA_DATABASE_ERROR
2180    *    API_EC_DATA_QUOTA_EXCEEDED
2181    *    API_EC_DATA_UNKNOWN_ERROR
2182    *    API_EC_PERMISSION_OTHER_USER
2183    */
2184   public function &data_getUserPreferences($uid = null) {
2185     return $this->call_method('facebook.data.getUserPreferences',
2186        array('uid' => $this->get_uid($uid)));
2187   }
2188
2189   /**
2190    * Create a new object type.
2191    *
2192    * @param  name       object type's name
2193    * @error
2194    *    API_EC_DATA_DATABASE_ERROR
2195    *    API_EC_DATA_OBJECT_ALREADY_EXISTS
2196    *    API_EC_PARAM
2197    *    API_EC_PERMISSION
2198    *    API_EC_DATA_INVALID_OPERATION
2199    *    API_EC_DATA_QUOTA_EXCEEDED
2200    *    API_EC_DATA_UNKNOWN_ERROR
2201    */
2202   public function &data_createObjectType($name) {
2203     return $this->call_method('facebook.data.createObjectType',
2204        array('name' => $name));
2205   }
2206
2207   /**
2208    * Delete an object type.
2209    *
2210    * @param  obj_type       object type's name
2211    * @error
2212    *    API_EC_DATA_DATABASE_ERROR
2213    *    API_EC_DATA_OBJECT_NOT_FOUND
2214    *    API_EC_PARAM
2215    *    API_EC_PERMISSION
2216    *    API_EC_DATA_INVALID_OPERATION
2217    *    API_EC_DATA_QUOTA_EXCEEDED
2218    *    API_EC_DATA_UNKNOWN_ERROR
2219    */
2220   public function &data_dropObjectType($obj_type) {
2221     return $this->call_method('facebook.data.dropObjectType',
2222        array('obj_type' => $obj_type));
2223   }
2224
2225   /**
2226    * Rename an object type.
2227    *
2228    * @param  obj_type       object type's name
2229    * @param  new_name       new object type's name
2230    * @error
2231    *    API_EC_DATA_DATABASE_ERROR
2232    *    API_EC_DATA_OBJECT_NOT_FOUND
2233    *    API_EC_DATA_OBJECT_ALREADY_EXISTS
2234    *    API_EC_PARAM
2235    *    API_EC_PERMISSION
2236    *    API_EC_DATA_INVALID_OPERATION
2237    *    API_EC_DATA_QUOTA_EXCEEDED
2238    *    API_EC_DATA_UNKNOWN_ERROR
2239    */
2240   public function &data_renameObjectType($obj_type, $new_name) {
2241     return $this->call_method('facebook.data.renameObjectType',
2242        array('obj_type' => $obj_type,
2243              'new_name' => $new_name));
2244   }
2245
2246   /**
2247    * Add a new property to an object type.
2248    *
2249    * @param  obj_type       object type's name
2250    * @param  prop_name      name of the property to add
2251    * @param  prop_type      1: integer; 2: string; 3: text blob
2252    * @error
2253    *    API_EC_DATA_DATABASE_ERROR
2254    *    API_EC_DATA_OBJECT_ALREADY_EXISTS
2255    *    API_EC_PARAM
2256    *    API_EC_PERMISSION
2257    *    API_EC_DATA_INVALID_OPERATION
2258    *    API_EC_DATA_QUOTA_EXCEEDED
2259    *    API_EC_DATA_UNKNOWN_ERROR
2260    */
2261   public function &data_defineObjectProperty($obj_type,
2262                                              $prop_name,
2263                                              $prop_type) {
2264     return $this->call_method('facebook.data.defineObjectProperty',
2265        array('obj_type' => $obj_type,
2266              'prop_name' => $prop_name,
2267              'prop_type' => $prop_type));
2268   }
2269
2270   /**
2271    * Remove a previously defined property from an object type.
2272    *
2273    * @param  obj_type      object type's name
2274    * @param  prop_name     name of the property to remove
2275    * @error
2276    *    API_EC_DATA_DATABASE_ERROR
2277    *    API_EC_DATA_OBJECT_NOT_FOUND
2278    *    API_EC_PARAM
2279    *    API_EC_PERMISSION
2280    *    API_EC_DATA_INVALID_OPERATION
2281    *    API_EC_DATA_QUOTA_EXCEEDED
2282    *    API_EC_DATA_UNKNOWN_ERROR
2283    */
2284   public function &data_undefineObjectProperty($obj_type, $prop_name) {
2285     return $this->call_method('facebook.data.undefineObjectProperty',
2286        array('obj_type' => $obj_type,
2287              'prop_name' => $prop_name));
2288   }
2289
2290   /**
2291    * Rename a previously defined property of an object type.
2292    *
2293    * @param  obj_type      object type's name
2294    * @param  prop_name     name of the property to rename
2295    * @param  new_name      new name to use
2296    * @error
2297    *    API_EC_DATA_DATABASE_ERROR
2298    *    API_EC_DATA_OBJECT_NOT_FOUND
2299    *    API_EC_DATA_OBJECT_ALREADY_EXISTS
2300    *    API_EC_PARAM
2301    *    API_EC_PERMISSION
2302    *    API_EC_DATA_INVALID_OPERATION
2303    *    API_EC_DATA_QUOTA_EXCEEDED
2304    *    API_EC_DATA_UNKNOWN_ERROR
2305    */
2306   public function &data_renameObjectProperty($obj_type, $prop_name,
2307                                             $new_name) {
2308     return $this->call_method('facebook.data.renameObjectProperty',
2309        array('obj_type' => $obj_type,
2310              'prop_name' => $prop_name,
2311              'new_name' => $new_name));
2312   }
2313
2314   /**
2315    * Retrieve a list of all object types that have defined for the application.
2316    *
2317    * @return               a list of object type names
2318    * @error
2319    *    API_EC_DATA_DATABASE_ERROR
2320    *    API_EC_PERMISSION
2321    *    API_EC_DATA_QUOTA_EXCEEDED
2322    *    API_EC_DATA_UNKNOWN_ERROR
2323    */
2324   public function &data_getObjectTypes() {
2325     return $this->call_method('facebook.data.getObjectTypes');
2326   }
2327
2328   /**
2329    * Get definitions of all properties of an object type.
2330    *
2331    * @param obj_type       object type's name
2332    * @return               pairs of property name and property types
2333    * @error
2334    *    API_EC_DATA_DATABASE_ERROR
2335    *    API_EC_PARAM
2336    *    API_EC_PERMISSION
2337    *    API_EC_DATA_OBJECT_NOT_FOUND
2338    *    API_EC_DATA_QUOTA_EXCEEDED
2339    *    API_EC_DATA_UNKNOWN_ERROR
2340    */
2341   public function &data_getObjectType($obj_type) {
2342     return $this->call_method('facebook.data.getObjectType',
2343        array('obj_type' => $obj_type));
2344   }
2345
2346   /**
2347    * Create a new object.
2348    *
2349    * @param  obj_type      object type's name
2350    * @param  properties    (optional) properties to set initially
2351    * @return               newly created object's id
2352    * @error
2353    *    API_EC_DATA_DATABASE_ERROR
2354    *    API_EC_PARAM
2355    *    API_EC_PERMISSION
2356    *    API_EC_DATA_INVALID_OPERATION
2357    *    API_EC_DATA_QUOTA_EXCEEDED
2358    *    API_EC_DATA_UNKNOWN_ERROR
2359    */
2360   public function &data_createObject($obj_type, $properties = null) {
2361     return $this->call_method('facebook.data.createObject',
2362        array('obj_type' => $obj_type,
2363              'properties' => json_encode($properties)));
2364   }
2365
2366   /**
2367    * Update an existing object.
2368    *
2369    * @param  obj_id        object's id
2370    * @param  properties    new properties
2371    * @param  replace       true for replacing existing properties;
2372    *                       false for merging
2373    * @error
2374    *    API_EC_DATA_DATABASE_ERROR
2375    *    API_EC_DATA_OBJECT_NOT_FOUND
2376    *    API_EC_PARAM
2377    *    API_EC_PERMISSION
2378    *    API_EC_DATA_INVALID_OPERATION
2379    *    API_EC_DATA_QUOTA_EXCEEDED
2380    *    API_EC_DATA_UNKNOWN_ERROR
2381    */
2382   public function &data_updateObject($obj_id, $properties, $replace = false) {
2383     return $this->call_method('facebook.data.updateObject',
2384        array('obj_id' => $obj_id,
2385              'properties' => json_encode($properties),
2386              'replace' => $replace));
2387   }
2388
2389   /**
2390    * Delete an existing object.
2391    *
2392    * @param  obj_id        object's id
2393    * @error
2394    *    API_EC_DATA_DATABASE_ERROR
2395    *    API_EC_DATA_OBJECT_NOT_FOUND
2396    *    API_EC_PARAM
2397    *    API_EC_PERMISSION
2398    *    API_EC_DATA_INVALID_OPERATION
2399    *    API_EC_DATA_QUOTA_EXCEEDED
2400    *    API_EC_DATA_UNKNOWN_ERROR
2401    */
2402   public function &data_deleteObject($obj_id) {
2403     return $this->call_method('facebook.data.deleteObject',
2404        array('obj_id' => $obj_id));
2405   }
2406
2407   /**
2408    * Delete a list of objects.
2409    *
2410    * @param  obj_ids       objects to delete
2411    * @error
2412    *    API_EC_DATA_DATABASE_ERROR
2413    *    API_EC_PARAM
2414    *    API_EC_PERMISSION
2415    *    API_EC_DATA_INVALID_OPERATION
2416    *    API_EC_DATA_QUOTA_EXCEEDED
2417    *    API_EC_DATA_UNKNOWN_ERROR
2418    */
2419   public function &data_deleteObjects($obj_ids) {
2420     return $this->call_method('facebook.data.deleteObjects',
2421        array('obj_ids' => json_encode($obj_ids)));
2422   }
2423
2424   /**
2425    * Get a single property value of an object.
2426    *
2427    * @param  obj_id        object's id
2428    * @param  prop_name     individual property's name
2429    * @return               individual property's value
2430    * @error
2431    *    API_EC_DATA_DATABASE_ERROR
2432    *    API_EC_DATA_OBJECT_NOT_FOUND
2433    *    API_EC_PARAM
2434    *    API_EC_PERMISSION
2435    *    API_EC_DATA_INVALID_OPERATION
2436    *    API_EC_DATA_QUOTA_EXCEEDED
2437    *    API_EC_DATA_UNKNOWN_ERROR
2438    */
2439   public function &data_getObjectProperty($obj_id, $prop_name) {
2440     return $this->call_method('facebook.data.getObjectProperty',
2441        array('obj_id' => $obj_id,
2442              'prop_name' => $prop_name));
2443   }
2444
2445   /**
2446    * Get properties of an object.
2447    *
2448    * @param  obj_id      object's id
2449    * @param  prop_names  (optional) properties to return; null for all.
2450    * @return             specified properties of an object
2451    * @error
2452    *    API_EC_DATA_DATABASE_ERROR
2453    *    API_EC_DATA_OBJECT_NOT_FOUND
2454    *    API_EC_PARAM
2455    *    API_EC_PERMISSION
2456    *    API_EC_DATA_INVALID_OPERATION
2457    *    API_EC_DATA_QUOTA_EXCEEDED
2458    *    API_EC_DATA_UNKNOWN_ERROR
2459    */
2460   public function &data_getObject($obj_id, $prop_names = null) {
2461     return $this->call_method('facebook.data.getObject',
2462        array('obj_id' => $obj_id,
2463              'prop_names' => json_encode($prop_names)));
2464   }
2465
2466   /**
2467    * Get properties of a list of objects.
2468    *
2469    * @param  obj_ids     object ids
2470    * @param  prop_names  (optional) properties to return; null for all.
2471    * @return             specified properties of an object
2472    * @error
2473    *    API_EC_DATA_DATABASE_ERROR
2474    *    API_EC_DATA_OBJECT_NOT_FOUND
2475    *    API_EC_PARAM
2476    *    API_EC_PERMISSION
2477    *    API_EC_DATA_INVALID_OPERATION
2478    *    API_EC_DATA_QUOTA_EXCEEDED
2479    *    API_EC_DATA_UNKNOWN_ERROR
2480    */
2481   public function &data_getObjects($obj_ids, $prop_names = null) {
2482     return $this->call_method('facebook.data.getObjects',
2483        array('obj_ids' => json_encode($obj_ids),
2484              'prop_names' => json_encode($prop_names)));
2485   }
2486
2487   /**
2488    * Set a single property value of an object.
2489    *
2490    * @param  obj_id        object's id
2491    * @param  prop_name     individual property's name
2492    * @param  prop_value    new value to set
2493    * @error
2494    *    API_EC_DATA_DATABASE_ERROR
2495    *    API_EC_DATA_OBJECT_NOT_FOUND
2496    *    API_EC_PARAM
2497    *    API_EC_PERMISSION
2498    *    API_EC_DATA_INVALID_OPERATION
2499    *    API_EC_DATA_QUOTA_EXCEEDED
2500    *    API_EC_DATA_UNKNOWN_ERROR
2501    */
2502   public function &data_setObjectProperty($obj_id, $prop_name,
2503                                          $prop_value) {
2504     return $this->call_method('facebook.data.setObjectProperty',
2505        array('obj_id' => $obj_id,
2506              'prop_name' => $prop_name,
2507              'prop_value' => $prop_value));
2508   }
2509
2510   /**
2511    * Read hash value by key.
2512    *
2513    * @param  obj_type      object type's name
2514    * @param  key           hash key
2515    * @param  prop_name     (optional) individual property's name
2516    * @return               hash value
2517    * @error
2518    *    API_EC_DATA_DATABASE_ERROR
2519    *    API_EC_PARAM
2520    *    API_EC_PERMISSION
2521    *    API_EC_DATA_INVALID_OPERATION
2522    *    API_EC_DATA_QUOTA_EXCEEDED
2523    *    API_EC_DATA_UNKNOWN_ERROR
2524    */
2525   public function &data_getHashValue($obj_type, $key, $prop_name = null) {
2526     return $this->call_method('facebook.data.getHashValue',
2527        array('obj_type' => $obj_type,
2528              'key' => $key,
2529              'prop_name' => $prop_name));
2530   }
2531
2532   /**
2533    * Write hash value by key.
2534    *
2535    * @param  obj_type      object type's name
2536    * @param  key           hash key
2537    * @param  value         hash value
2538    * @param  prop_name     (optional) individual property's name
2539    * @error
2540    *    API_EC_DATA_DATABASE_ERROR
2541    *    API_EC_PARAM
2542    *    API_EC_PERMISSION
2543    *    API_EC_DATA_INVALID_OPERATION
2544    *    API_EC_DATA_QUOTA_EXCEEDED
2545    *    API_EC_DATA_UNKNOWN_ERROR
2546    */
2547   public function &data_setHashValue($obj_type,
2548                                      $key,
2549                                      $value,
2550                                      $prop_name = null) {
2551     return $this->call_method('facebook.data.setHashValue',
2552        array('obj_type' => $obj_type,
2553              'key' => $key,
2554              'value' => $value,
2555              'prop_name' => $prop_name));
2556   }
2557
2558   /**
2559    * Increase a hash value by specified increment atomically.
2560    *
2561    * @param  obj_type      object type's name
2562    * @param  key           hash key
2563    * @param  prop_name     individual property's name
2564    * @param  increment     (optional) default is 1
2565    * @return               incremented hash value
2566    * @error
2567    *    API_EC_DATA_DATABASE_ERROR
2568    *    API_EC_PARAM
2569    *    API_EC_PERMISSION
2570    *    API_EC_DATA_INVALID_OPERATION
2571    *    API_EC_DATA_QUOTA_EXCEEDED
2572    *    API_EC_DATA_UNKNOWN_ERROR
2573    */
2574   public function &data_incHashValue($obj_type,
2575                                      $key,
2576                                      $prop_name,
2577                                      $increment = 1) {
2578     return $this->call_method('facebook.data.incHashValue',
2579        array('obj_type' => $obj_type,
2580              'key' => $key,
2581              'prop_name' => $prop_name,
2582              'increment' => $increment));
2583   }
2584
2585   /**
2586    * Remove a hash key and its values.
2587    *
2588    * @param  obj_type    object type's name
2589    * @param  key         hash key
2590    * @error
2591    *    API_EC_DATA_DATABASE_ERROR
2592    *    API_EC_PARAM
2593    *    API_EC_PERMISSION
2594    *    API_EC_DATA_INVALID_OPERATION
2595    *    API_EC_DATA_QUOTA_EXCEEDED
2596    *    API_EC_DATA_UNKNOWN_ERROR
2597    */
2598   public function &data_removeHashKey($obj_type, $key) {
2599     return $this->call_method('facebook.data.removeHashKey',
2600        array('obj_type' => $obj_type,
2601              'key' => $key));
2602   }
2603
2604   /**
2605    * Remove hash keys and their values.
2606    *
2607    * @param  obj_type    object type's name
2608    * @param  keys        hash keys
2609    * @error
2610    *    API_EC_DATA_DATABASE_ERROR
2611    *    API_EC_PARAM
2612    *    API_EC_PERMISSION
2613    *    API_EC_DATA_INVALID_OPERATION
2614    *    API_EC_DATA_QUOTA_EXCEEDED
2615    *    API_EC_DATA_UNKNOWN_ERROR
2616    */
2617   public function &data_removeHashKeys($obj_type, $keys) {
2618     return $this->call_method('facebook.data.removeHashKeys',
2619        array('obj_type' => $obj_type,
2620              'keys' => json_encode($keys)));
2621   }
2622
2623   /**
2624    * Define an object association.
2625    *
2626    * @param  name        name of this association
2627    * @param  assoc_type  1: one-way 2: two-way symmetric 3: two-way asymmetric
2628    * @param  assoc_info1 needed info about first object type
2629    * @param  assoc_info2 needed info about second object type
2630    * @param  inverse     (optional) name of reverse association
2631    * @error
2632    *    API_EC_DATA_DATABASE_ERROR
2633    *    API_EC_DATA_OBJECT_ALREADY_EXISTS
2634    *    API_EC_PARAM
2635    *    API_EC_PERMISSION
2636    *    API_EC_DATA_INVALID_OPERATION
2637    *    API_EC_DATA_QUOTA_EXCEEDED
2638    *    API_EC_DATA_UNKNOWN_ERROR
2639    */
2640   public function &data_defineAssociation($name, $assoc_type, $assoc_info1,
2641                                          $assoc_info2, $inverse = null) {
2642     return $this->call_method('facebook.data.defineAssociation',
2643        array('name' => $name,
2644              'assoc_type' => $assoc_type,
2645              'assoc_info1' => json_encode($assoc_info1),
2646              'assoc_info2' => json_encode($assoc_info2),
2647              'inverse' => $inverse));
2648   }
2649
2650   /**
2651    * Undefine an object association.
2652    *
2653    * @param  name        name of this association
2654    * @error
2655    *    API_EC_DATA_DATABASE_ERROR
2656    *    API_EC_DATA_OBJECT_NOT_FOUND
2657    *    API_EC_PARAM
2658    *    API_EC_PERMISSION
2659    *    API_EC_DATA_INVALID_OPERATION
2660    *    API_EC_DATA_QUOTA_EXCEEDED
2661    *    API_EC_DATA_UNKNOWN_ERROR
2662    */
2663   public function &data_undefineAssociation($name) {
2664     return $this->call_method('facebook.data.undefineAssociation',
2665        array('name' => $name));
2666   }
2667
2668   /**
2669    * Rename an object association or aliases.
2670    *
2671    * @param  name        name of this association
2672    * @param  new_name    (optional) new name of this association
2673    * @param  new_alias1  (optional) new alias for object type 1
2674    * @param  new_alias2  (optional) new alias for object type 2
2675    * @error
2676    *    API_EC_DATA_DATABASE_ERROR
2677    *    API_EC_DATA_OBJECT_ALREADY_EXISTS
2678    *    API_EC_DATA_OBJECT_NOT_FOUND
2679    *    API_EC_PARAM
2680    *    API_EC_PERMISSION
2681    *    API_EC_DATA_INVALID_OPERATION
2682    *    API_EC_DATA_QUOTA_EXCEEDED
2683    *    API_EC_DATA_UNKNOWN_ERROR
2684    */
2685   public function &data_renameAssociation($name, $new_name, $new_alias1 = null,
2686                                          $new_alias2 = null) {
2687     return $this->call_method('facebook.data.renameAssociation',
2688        array('name' => $name,
2689              'new_name' => $new_name,
2690              'new_alias1' => $new_alias1,
2691              'new_alias2' => $new_alias2));
2692   }
2693
2694   /**
2695    * Get definition of an object association.
2696    *
2697    * @param  name        name of this association
2698    * @return             specified association
2699    * @error
2700    *    API_EC_DATA_DATABASE_ERROR
2701    *    API_EC_DATA_OBJECT_NOT_FOUND
2702    *    API_EC_PARAM
2703    *    API_EC_PERMISSION
2704    *    API_EC_DATA_QUOTA_EXCEEDED
2705    *    API_EC_DATA_UNKNOWN_ERROR
2706    */
2707   public function &data_getAssociationDefinition($name) {
2708     return $this->call_method('facebook.data.getAssociationDefinition',
2709        array('name' => $name));
2710   }
2711
2712   /**
2713    * Get definition of all associations.
2714    *
2715    * @return             all defined associations
2716    * @error
2717    *    API_EC_DATA_DATABASE_ERROR
2718    *    API_EC_PERMISSION
2719    *    API_EC_DATA_QUOTA_EXCEEDED
2720    *    API_EC_DATA_UNKNOWN_ERROR
2721    */
2722   public function &data_getAssociationDefinitions() {
2723     return $this->call_method('facebook.data.getAssociationDefinitions',
2724        array());
2725   }
2726
2727   /**
2728    * Create or modify an association between two objects.
2729    *
2730    * @param  name        name of association
2731    * @param  obj_id1     id of first object
2732    * @param  obj_id2     id of second object
2733    * @param  data        (optional) extra string data to store
2734    * @param  assoc_time  (optional) extra time data; default to creation time
2735    * @error
2736    *    API_EC_DATA_DATABASE_ERROR
2737    *    API_EC_PARAM
2738    *    API_EC_PERMISSION
2739    *    API_EC_DATA_INVALID_OPERATION
2740    *    API_EC_DATA_QUOTA_EXCEEDED
2741    *    API_EC_DATA_UNKNOWN_ERROR
2742    */
2743   public function &data_setAssociation($name, $obj_id1, $obj_id2, $data = null,
2744                                       $assoc_time = null) {
2745     return $this->call_method('facebook.data.setAssociation',
2746        array('name' => $name,
2747              'obj_id1' => $obj_id1,
2748              'obj_id2' => $obj_id2,
2749              'data' => $data,
2750              'assoc_time' => $assoc_time));
2751   }
2752
2753   /**
2754    * Create or modify associations between objects.
2755    *
2756    * @param  assocs      associations to set
2757    * @param  name        (optional) name of association
2758    * @error
2759    *    API_EC_DATA_DATABASE_ERROR
2760    *    API_EC_PARAM
2761    *    API_EC_PERMISSION
2762    *    API_EC_DATA_INVALID_OPERATION
2763    *    API_EC_DATA_QUOTA_EXCEEDED
2764    *    API_EC_DATA_UNKNOWN_ERROR
2765    */
2766   public function &data_setAssociations($assocs, $name = null) {
2767     return $this->call_method('facebook.data.setAssociations',
2768        array('assocs' => json_encode($assocs),
2769              'name' => $name));
2770   }
2771
2772   /**
2773    * Remove an association between two objects.
2774    *
2775    * @param  name        name of association
2776    * @param  obj_id1     id of first object
2777    * @param  obj_id2     id of second object
2778    * @error
2779    *    API_EC_DATA_DATABASE_ERROR
2780    *    API_EC_DATA_OBJECT_NOT_FOUND
2781    *    API_EC_PARAM
2782    *    API_EC_PERMISSION
2783    *    API_EC_DATA_QUOTA_EXCEEDED
2784    *    API_EC_DATA_UNKNOWN_ERROR
2785    */
2786   public function &data_removeAssociation($name, $obj_id1, $obj_id2) {
2787     return $this->call_method('facebook.data.removeAssociation',
2788        array('name' => $name,
2789              'obj_id1' => $obj_id1,
2790              'obj_id2' => $obj_id2));
2791   }
2792
2793   /**
2794    * Remove associations between objects by specifying pairs of object ids.
2795    *
2796    * @param  assocs      associations to remove
2797    * @param  name        (optional) name of association
2798    * @error
2799    *    API_EC_DATA_DATABASE_ERROR
2800    *    API_EC_DATA_OBJECT_NOT_FOUND
2801    *    API_EC_PARAM
2802    *    API_EC_PERMISSION
2803    *    API_EC_DATA_QUOTA_EXCEEDED
2804    *    API_EC_DATA_UNKNOWN_ERROR
2805    */
2806   public function &data_removeAssociations($assocs, $name = null) {
2807     return $this->call_method('facebook.data.removeAssociations',
2808        array('assocs' => json_encode($assocs),
2809              'name' => $name));
2810   }
2811
2812   /**
2813    * Remove associations between objects by specifying one object id.
2814    *
2815    * @param  name        name of association
2816    * @param  obj_id      who's association to remove
2817    * @error
2818    *    API_EC_DATA_DATABASE_ERROR
2819    *    API_EC_DATA_OBJECT_NOT_FOUND
2820    *    API_EC_PARAM
2821    *    API_EC_PERMISSION
2822    *    API_EC_DATA_INVALID_OPERATION
2823    *    API_EC_DATA_QUOTA_EXCEEDED
2824    *    API_EC_DATA_UNKNOWN_ERROR
2825    */
2826   public function &data_removeAssociatedObjects($name, $obj_id) {
2827     return $this->call_method('facebook.data.removeAssociatedObjects',
2828        array('name' => $name,
2829              'obj_id' => $obj_id));
2830   }
2831
2832   /**
2833    * Retrieve a list of associated objects.
2834    *
2835    * @param  name        name of association
2836    * @param  obj_id      who's association to retrieve
2837    * @param  no_data     only return object ids
2838    * @return             associated objects
2839    * @error
2840    *    API_EC_DATA_DATABASE_ERROR
2841    *    API_EC_DATA_OBJECT_NOT_FOUND
2842    *    API_EC_PARAM
2843    *    API_EC_PERMISSION
2844    *    API_EC_DATA_INVALID_OPERATION
2845    *    API_EC_DATA_QUOTA_EXCEEDED
2846    *    API_EC_DATA_UNKNOWN_ERROR
2847    */
2848   public function &data_getAssociatedObjects($name, $obj_id, $no_data = true) {
2849     return $this->call_method('facebook.data.getAssociatedObjects',
2850        array('name' => $name,
2851              'obj_id' => $obj_id,
2852              'no_data' => $no_data));
2853   }
2854
2855   /**
2856    * Count associated objects.
2857    *
2858    * @param  name        name of association
2859    * @param  obj_id      who's association to retrieve
2860    * @return             associated object's count
2861    * @error
2862    *    API_EC_DATA_DATABASE_ERROR
2863    *    API_EC_DATA_OBJECT_NOT_FOUND
2864    *    API_EC_PARAM
2865    *    API_EC_PERMISSION
2866    *    API_EC_DATA_INVALID_OPERATION
2867    *    API_EC_DATA_QUOTA_EXCEEDED
2868    *    API_EC_DATA_UNKNOWN_ERROR
2869    */
2870   public function &data_getAssociatedObjectCount($name, $obj_id) {
2871     return $this->call_method('facebook.data.getAssociatedObjectCount',
2872        array('name' => $name,
2873              'obj_id' => $obj_id));
2874   }
2875
2876   /**
2877    * Get a list of associated object counts.
2878    *
2879    * @param  name        name of association
2880    * @param  obj_ids     whose association to retrieve
2881    * @return             associated object counts
2882    * @error
2883    *    API_EC_DATA_DATABASE_ERROR
2884    *    API_EC_DATA_OBJECT_NOT_FOUND
2885    *    API_EC_PARAM
2886    *    API_EC_PERMISSION
2887    *    API_EC_DATA_INVALID_OPERATION
2888    *    API_EC_DATA_QUOTA_EXCEEDED
2889    *    API_EC_DATA_UNKNOWN_ERROR
2890    */
2891   public function &data_getAssociatedObjectCounts($name, $obj_ids) {
2892     return $this->call_method('facebook.data.getAssociatedObjectCounts',
2893        array('name' => $name,
2894              'obj_ids' => json_encode($obj_ids)));
2895   }
2896
2897   /**
2898    * Find all associations between two objects.
2899    *
2900    * @param  obj_id1     id of first object
2901    * @param  obj_id2     id of second object
2902    * @param  no_data     only return association names without data
2903    * @return             all associations between objects
2904    * @error
2905    *    API_EC_DATA_DATABASE_ERROR
2906    *    API_EC_PARAM
2907    *    API_EC_PERMISSION
2908    *    API_EC_DATA_QUOTA_EXCEEDED
2909    *    API_EC_DATA_UNKNOWN_ERROR
2910    */
2911   public function &data_getAssociations($obj_id1, $obj_id2, $no_data = true) {
2912     return $this->call_method('facebook.data.getAssociations',
2913        array('obj_id1' => $obj_id1,
2914              'obj_id2' => $obj_id2,
2915              'no_data' => $no_data));
2916   }
2917
2918   /**
2919    * Get the properties that you have set for an app.
2920    *
2921    * @param properties  List of properties names to fetch
2922    *
2923    * @return array  A map from property name to value
2924    */
2925   public function admin_getAppProperties($properties) {
2926     return json_decode(
2927         $this->call_method('facebook.admin.getAppProperties',
2928             array('properties' => json_encode($properties))), true);
2929   }
2930
2931   /**
2932    * Set properties for an app.
2933    *
2934    * @param properties  A map from property names to values
2935    *
2936    * @return bool  true on success
2937    */
2938   public function admin_setAppProperties($properties) {
2939     return $this->call_method('facebook.admin.setAppProperties',
2940        array('properties' => json_encode($properties)));
2941   }
2942
2943   /**
2944    * Sets href and text for a Live Stream Box xid's via link
2945    *
2946    * @param  string  $xid       xid of the Live Stream
2947    * @param  string  $via_href  Href for the via link
2948    * @param  string  $via_text  Text for the via link
2949    *
2950    * @return boolWhether the set was successful
2951    */
2952   public function admin_setLiveStreamViaLink($xid, $via_href, $via_text) {
2953     return $this->call_method('facebook.admin.setLiveStreamViaLink',
2954                               array('xid'      => $xid,
2955                                     'via_href' => $via_href,
2956                                     'via_text' => $via_text));
2957   }
2958
2959   /**
2960    * Gets href and text for a Live Stream Box xid's via link
2961    *
2962    * @param  string  $xid  xid of the Live Stream
2963    *
2964    * @return Array  Associative array with keys 'via_href' and 'via_text'
2965    *                False if there was an error.
2966    */
2967   public function admin_getLiveStreamViaLink($xid) {
2968     return $this->call_method('facebook.admin.getLiveStreamViaLink',
2969                               array('xid' => $xid));
2970   }
2971
2972   /**
2973    * Returns the allocation limit value for a specified integration point name
2974    * Integration point names are defined in lib/api/karma/constants.php in the
2975    * limit_map.
2976    *
2977    * @param string $integration_point_name  Name of an integration point
2978    *                                        (see developer wiki for list).
2979    * @param int    $uid                     Specific user to check the limit.
2980    *
2981    * @return int  Integration point allocation value
2982    */
2983   public function &admin_getAllocation($integration_point_name, $uid=null) {
2984     return $this->call_method('facebook.admin.getAllocation',
2985         array('integration_point_name' => $integration_point_name,
2986               'uid' => $uid));
2987   }
2988
2989   /**
2990    * Returns values for the specified metrics for the current application, in
2991    * the given time range.  The metrics are collected for fixed-length periods,
2992    * and the times represent midnight at the end of each period.
2993    *
2994    * @param start_time  unix time for the start of the range
2995    * @param end_time    unix time for the end of the range
2996    * @param period      number of seconds in the desired period
2997    * @param metrics     list of metrics to look up
2998    *
2999    * @return array  A map of the names and values for those metrics
3000    */
3001   public function &admin_getMetrics($start_time, $end_time, $period, $metrics) {
3002     return $this->call_method('admin.getMetrics',
3003         array('start_time' => $start_time,
3004               'end_time' => $end_time,
3005               'period' => $period,
3006               'metrics' => json_encode($metrics)));
3007   }
3008
3009   /**
3010    * Sets application restriction info.
3011    *
3012    * Applications can restrict themselves to only a limited user demographic
3013    * based on users' age and/or location or based on static predefined types
3014    * specified by facebook for specifying diff age restriction for diff
3015    * locations.
3016    *
3017    * @param array $restriction_info  The age restriction settings to set.
3018    *
3019    * @return bool  true on success
3020    */
3021   public function admin_setRestrictionInfo($restriction_info = null) {
3022     $restriction_str = null;
3023     if (!empty($restriction_info)) {
3024       $restriction_str = json_encode($restriction_info);
3025     }
3026     return $this->call_method('admin.setRestrictionInfo',
3027         array('restriction_str' => $restriction_str));
3028   }
3029
3030   /**
3031    * Gets application restriction info.
3032    *
3033    * Applications can restrict themselves to only a limited user demographic
3034    * based on users' age and/or location or based on static predefined types
3035    * specified by facebook for specifying diff age restriction for diff
3036    * locations.
3037    *
3038    * @return array  The age restriction settings for this application.
3039    */
3040   public function admin_getRestrictionInfo() {
3041     return json_decode(
3042         $this->call_method('admin.getRestrictionInfo'),
3043         true);
3044   }
3045
3046
3047   /**
3048    * Bans a list of users from the app. Banned users can't
3049    * access the app's canvas page and forums.
3050    *
3051    * @param array $uids an array of user ids
3052    * @return bool true on success
3053    */
3054   public function admin_banUsers($uids) {
3055     return $this->call_method(
3056       'admin.banUsers', array('uids' => json_encode($uids)));
3057   }
3058
3059   /**
3060    * Unban users that have been previously banned with
3061    * admin_banUsers().
3062    *
3063    * @param array $uids an array of user ids
3064    * @return bool true on success
3065    */
3066   public function admin_unbanUsers($uids) {
3067     return $this->call_method(
3068       'admin.unbanUsers', array('uids' => json_encode($uids)));
3069   }
3070
3071   /**
3072    * Gets the list of users that have been banned from the application.
3073    * $uids is an optional parameter that filters the result with the list
3074    * of provided user ids. If $uids is provided,
3075    * only banned user ids that are contained in $uids are returned.
3076    *
3077    * @param array $uids an array of user ids to filter by
3078    * @return bool true on success
3079    */
3080
3081   public function admin_getBannedUsers($uids = null) {
3082     return $this->call_method(
3083       'admin.getBannedUsers',
3084       array('uids' => $uids ? json_encode($uids) : null));
3085   }
3086
3087
3088   /* UTILITY FUNCTIONS */
3089
3090   /**
3091    * Calls the specified normal POST method with the specified parameters.
3092    *
3093    * @param string $method  Name of the Facebook method to invoke
3094    * @param array $params   A map of param names => param values
3095    *
3096    * @return mixed  Result of method call; this returns a reference to support
3097    *                'delayed returns' when in a batch context.
3098    *     See: http://wiki.developers.facebook.com/index.php/Using_batching_API
3099    */
3100   public function &call_method($method, $params = array()) {
3101     if ($this->format) {
3102       $params['format'] = $this->format;
3103     }
3104     if (!$this->pending_batch()) {
3105       if ($this->call_as_apikey) {
3106         $params['call_as_apikey'] = $this->call_as_apikey;
3107       }
3108       $data = $this->post_request($method, $params);
3109       $this->rawData = $data;
3110       $result = $this->convert_result($data, $method, $params);
3111       if (is_array($result) && isset($result['error_code'])) {
3112         throw new FacebookRestClientException($result['error_msg'],
3113                                               $result['error_code']);
3114       }
3115     }
3116     else {
3117       $result = null;
3118       $batch_item = array('m' => $method, 'p' => $params, 'r' => & $result);
3119       $this->batch_queue[] = $batch_item;
3120     }
3121
3122     return $result;
3123   }
3124
3125   protected function convert_result($data, $method, $params) {
3126     $is_xml = (empty($params['format']) ||
3127                strtolower($params['format']) != 'json');
3128     return ($is_xml) ? $this->convert_xml_to_result($data, $method, $params)
3129                      : json_decode($data, true);
3130   }
3131
3132   /**
3133    * Change the response format
3134    *
3135    * @param string $format The response format (json, xml)
3136    */
3137   public function setFormat($format) {
3138     $this->format = $format;
3139     return $this;
3140   }
3141
3142   /**
3143    * get the current response serialization format
3144    *
3145    * @return string 'xml', 'json', or null (which means 'xml')
3146    */
3147   public function getFormat() {
3148     return $this->format;
3149   }
3150
3151   /**
3152    * Returns the raw JSON or XML output returned by the server in the most
3153    * recent API call.
3154    *
3155    * @return string
3156    */
3157    public function getRawData() {
3158      return $this->rawData;
3159    }
3160
3161   /**
3162    * Calls the specified file-upload POST method with the specified parameters
3163    *
3164    * @param string $method Name of the Facebook method to invoke
3165    * @param array  $params A map of param names => param values
3166    * @param string $file   A path to the file to upload (required)
3167    *
3168    * @return array A dictionary representing the response.
3169    */
3170   public function call_upload_method($method, $params, $file, $server_addr = null) {
3171     if (!$this->pending_batch()) {
3172       if (!file_exists($file)) {
3173         $code =
3174           FacebookAPIErrorCodes::API_EC_PARAM;
3175         $description = FacebookAPIErrorCodes::$api_error_descriptions[$code];
3176         throw new FacebookRestClientException($description, $code);
3177       }
3178
3179       if ($this->format) {
3180         $params['format'] = $this->format;
3181       }
3182       $data = $this->post_upload_request($method,
3183                                          $params,
3184                                          $file,
3185                                          $server_addr);
3186       $result = $this->convert_result($data, $method, $params);
3187
3188       if (is_array($result) && isset($result['error_code'])) {
3189         throw new FacebookRestClientException($result['error_msg'],
3190                                               $result['error_code']);
3191       }
3192     }
3193     else {
3194       $code =
3195         FacebookAPIErrorCodes::API_EC_BATCH_METHOD_NOT_ALLOWED_IN_BATCH_MODE;
3196       $description = FacebookAPIErrorCodes::$api_error_descriptions[$code];
3197       throw new FacebookRestClientException($description, $code);
3198     }
3199
3200     return $result;
3201   }
3202
3203   protected function convert_xml_to_result($xml, $method, $params) {
3204     $sxml = simplexml_load_string($xml);
3205     $result = self::convert_simplexml_to_array($sxml);
3206
3207     if (!empty($GLOBALS['facebook_config']['debug'])) {
3208       // output the raw xml and its corresponding php object, for debugging:
3209       print '<div style="margin: 10px 30px; padding: 5px; border: 2px solid black; background: gray; color: white; font-size: 12px; font-weight: bold;">';
3210       $this->cur_id++;
3211       print $this->cur_id . ': Called ' . $method . ', show ' .
3212             '<a href=# onclick="return toggleDisplay(' . $this->cur_id . ', \'params\');">Params</a> | '.
3213             '<a href=# onclick="return toggleDisplay(' . $this->cur_id . ', \'xml\');">XML</a> | '.
3214             '<a href=# onclick="return toggleDisplay(' . $this->cur_id . ', \'sxml\');">SXML</a> | '.
3215             '<a href=# onclick="return toggleDisplay(' . $this->cur_id . ', \'php\');">PHP</a>';
3216       print '<pre id="params'.$this->cur_id.'" style="display: none; overflow: auto;">'.print_r($params, true).'</pre>';
3217       print '<pre id="xml'.$this->cur_id.'" style="display: none; overflow: auto;">'.htmlspecialchars($xml).'</pre>';
3218       print '<pre id="php'.$this->cur_id.'" style="display: none; overflow: auto;">'.print_r($result, true).'</pre>';
3219       print '<pre id="sxml'.$this->cur_id.'" style="display: none; overflow: auto;">'.print_r($sxml, true).'</pre>';
3220       print '</div>';
3221     }
3222     return $result;
3223   }
3224
3225   protected function finalize_params($method, $params) {
3226     list($get, $post) = $this->add_standard_params($method, $params);
3227     // we need to do this before signing the params
3228     $this->convert_array_values_to_json($post);
3229     $post['sig'] = Facebook::generate_sig(array_merge($get, $post),
3230                                           $this->secret);
3231     return array($get, $post);
3232   }
3233
3234   private function convert_array_values_to_json(&$params) {
3235     foreach ($params as $key => &$val) {
3236       if (is_array($val)) {
3237         $val = json_encode($val);
3238       }
3239     }
3240   }
3241
3242   /**
3243    * Add the generally required params to our request.
3244    * Params method, api_key, and v should be sent over as get.
3245    */
3246   private function add_standard_params($method, $params) {
3247     $post = $params;
3248     $get = array();
3249     if ($this->call_as_apikey) {
3250       $get['call_as_apikey'] = $this->call_as_apikey;
3251     }
3252     if ($this->using_session_secret) {
3253       $get['ss'] = '1';
3254     }
3255
3256     $get['method'] = $method;
3257     $get['session_key'] = $this->session_key;
3258     $get['api_key'] = $this->api_key;
3259     $post['call_id'] = microtime(true);
3260     if ($post['call_id'] <= $this->last_call_id) {
3261       $post['call_id'] = $this->last_call_id + 0.001;
3262     }
3263     $this->last_call_id = $post['call_id'];
3264     if (isset($post['v'])) {
3265       $get['v'] = $post['v'];
3266       unset($post['v']);
3267     } else {
3268       $get['v'] = '1.0';
3269     }
3270     if (isset($this->use_ssl_resources) &&
3271         $this->use_ssl_resources) {
3272       $post['return_ssl_resources'] = true;
3273     }
3274     return array($get, $post);
3275   }
3276
3277   private function create_url_string($params) {
3278     $post_params = array();
3279     foreach ($params as $key => &$val) {
3280       $post_params[] = $key.'='.urlencode($val);
3281     }
3282     return implode('&', $post_params);
3283   }
3284
3285   private function run_multipart_http_transaction($method, $params, $file, $server_addr) {
3286
3287     // the format of this message is specified in RFC1867/RFC1341.
3288     // we add twenty pseudo-random digits to the end of the boundary string.
3289     $boundary = '--------------------------FbMuLtIpArT' .
3290                 sprintf("%010d", mt_rand()) .
3291                 sprintf("%010d", mt_rand());
3292     $content_type = 'multipart/form-data; boundary=' . $boundary;
3293     // within the message, we prepend two extra hyphens.
3294     $delimiter = '--' . $boundary;
3295     $close_delimiter = $delimiter . '--';
3296     $content_lines = array();
3297     foreach ($params as $key => &$val) {
3298       $content_lines[] = $delimiter;
3299       $content_lines[] = 'Content-Disposition: form-data; name="' . $key . '"';
3300       $content_lines[] = '';
3301       $content_lines[] = $val;
3302     }
3303     // now add the file data
3304     $content_lines[] = $delimiter;
3305     $content_lines[] =
3306       'Content-Disposition: form-data; filename="' . $file . '"';
3307     $content_lines[] = 'Content-Type: application/octet-stream';
3308     $content_lines[] = '';
3309     $content_lines[] = file_get_contents($file);
3310     $content_lines[] = $close_delimiter;
3311     $content_lines[] = '';
3312     $content = implode("\r\n", $content_lines);
3313     return $this->run_http_post_transaction($content_type, $content, $server_addr);
3314   }
3315
3316   public function post_request($method, $params) {
3317     list($get, $post) = $this->finalize_params($method, $params);
3318     $post_string = $this->create_url_string($post);
3319     $get_string = $this->create_url_string($get);
3320     $url_with_get = $this->server_addr . '?' . $get_string;
3321     if ($this->use_curl_if_available && function_exists('curl_init')) {
3322       $useragent = 'Facebook API PHP5 Client 1.1 (curl) ' . phpversion();
3323       $ch = curl_init();
3324       curl_setopt($ch, CURLOPT_URL, $url_with_get);
3325       curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);
3326       curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
3327       curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
3328       curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
3329       curl_setopt($ch, CURLOPT_TIMEOUT, 30);
3330       $result = $this->curl_exec($ch);
3331       curl_close($ch);
3332     } else {
3333       $content_type = 'application/x-www-form-urlencoded';
3334       $content = $post_string;
3335       $result = $this->run_http_post_transaction($content_type,
3336                                                  $content,
3337                                                  $url_with_get);
3338     }
3339     return $result;
3340   }
3341
3342   /**
3343    * execute a curl transaction -- this exists mostly so subclasses can add
3344    * extra options and/or process the response, if they wish.
3345    *
3346    * @param resource $ch a curl handle
3347    */
3348   protected function curl_exec($ch) {
3349       $result = curl_exec($ch);
3350       return $result;
3351   }
3352
3353   protected function post_upload_request($method, $params, $file, $server_addr = null) {
3354     $server_addr = $server_addr ? $server_addr : $this->server_addr;
3355     list($get, $post) = $this->finalize_params($method, $params);
3356     $get_string = $this->create_url_string($get);
3357     $url_with_get = $server_addr . '?' . $get_string;
3358     if ($this->use_curl_if_available && function_exists('curl_init')) {
3359       // prepending '@' causes cURL to upload the file; the key is ignored.
3360       $post['_file'] = '@' . $file;
3361       $useragent = 'Facebook API PHP5 Client 1.1 (curl) ' . phpversion();
3362       $ch = curl_init();
3363       curl_setopt($ch, CURLOPT_URL, $url_with_get);
3364       // this has to come before the POSTFIELDS set!
3365       curl_setopt($ch, CURLOPT_POST, 1);
3366       // passing an array gets curl to use the multipart/form-data content type
3367       curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
3368       curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
3369       curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
3370       $result = $this->curl_exec($ch);
3371       curl_close($ch);
3372     } else {
3373       $result = $this->run_multipart_http_transaction($method, $post,
3374                                                       $file, $url_with_get);
3375     }
3376     return $result;
3377   }
3378
3379   private function run_http_post_transaction($content_type, $content, $server_addr) {
3380
3381     $user_agent = 'Facebook API PHP5 Client 1.1 (non-curl) ' . phpversion();
3382     $content_length = strlen($content);
3383     $context =
3384       array('http' =>
3385               array('method' => 'POST',
3386                     'user_agent' => $user_agent,
3387                     'header' => 'Content-Type: ' . $content_type . "\r\n" .
3388                                 'Content-Length: ' . $content_length,
3389                     'content' => $content));
3390     $context_id = stream_context_create($context);
3391     $sock = fopen($server_addr, 'r', false, $context_id);
3392
3393     $result = '';
3394     if ($sock) {
3395       while (!feof($sock)) {
3396         $result .= fgets($sock, 4096);
3397       }
3398       fclose($sock);
3399     }
3400     return $result;
3401   }
3402
3403   public static function convert_simplexml_to_array($sxml) {
3404     $arr = array();
3405     if ($sxml) {
3406       foreach ($sxml as $k => $v) {
3407         if ($sxml['list']) {
3408           $arr[] = self::convert_simplexml_to_array($v);
3409         } else {
3410           $arr[$k] = self::convert_simplexml_to_array($v);
3411         }
3412       }
3413     }
3414     if (sizeof($arr) > 0) {
3415       return $arr;
3416     } else {
3417       return (string)$sxml;
3418     }
3419   }
3420
3421   protected function get_uid($uid) {
3422     return $uid ? $uid : $this->user;
3423   }
3424 }
3425
3426
3427 class FacebookRestClientException extends Exception {
3428 }
3429
3430 // Supporting methods and values------
3431
3432 /**
3433  * Error codes and descriptions for the Facebook API.
3434  */
3435
3436 class FacebookAPIErrorCodes {
3437
3438   const API_EC_SUCCESS = 0;
3439
3440   /*
3441    * GENERAL ERRORS
3442    */
3443   const API_EC_UNKNOWN = 1;
3444   const API_EC_SERVICE = 2;
3445   const API_EC_METHOD = 3;
3446   const API_EC_TOO_MANY_CALLS = 4;
3447   const API_EC_BAD_IP = 5;
3448   const API_EC_HOST_API = 6;
3449   const API_EC_HOST_UP = 7;
3450   const API_EC_SECURE = 8;
3451   const API_EC_RATE = 9;
3452   const API_EC_PERMISSION_DENIED = 10;
3453   const API_EC_DEPRECATED = 11;
3454   const API_EC_VERSION = 12;
3455   const API_EC_INTERNAL_FQL_ERROR = 13;
3456   const API_EC_HOST_PUP = 14;
3457   const API_EC_SESSION_SECRET_NOT_ALLOWED = 15;
3458   const API_EC_HOST_READONLY = 16;
3459
3460   /*
3461    * PARAMETER ERRORS
3462    */
3463   const API_EC_PARAM = 100;
3464   const API_EC_PARAM_API_KEY = 101;
3465   const API_EC_PARAM_SESSION_KEY = 102;
3466   const API_EC_PARAM_CALL_ID = 103;
3467   const API_EC_PARAM_SIGNATURE = 104;
3468   const API_EC_PARAM_TOO_MANY = 105;
3469   const API_EC_PARAM_USER_ID = 110;
3470   const API_EC_PARAM_USER_FIELD = 111;
3471   const API_EC_PARAM_SOCIAL_FIELD = 112;
3472   const API_EC_PARAM_EMAIL = 113;
3473   const API_EC_PARAM_USER_ID_LIST = 114;
3474   const API_EC_PARAM_FIELD_LIST = 115;
3475   const API_EC_PARAM_ALBUM_ID = 120;
3476   const API_EC_PARAM_PHOTO_ID = 121;
3477   const API_EC_PARAM_FEED_PRIORITY = 130;
3478   const API_EC_PARAM_CATEGORY = 140;
3479   const API_EC_PARAM_SUBCATEGORY = 141;
3480   const API_EC_PARAM_TITLE = 142;
3481   const API_EC_PARAM_DESCRIPTION = 143;
3482   const API_EC_PARAM_BAD_JSON = 144;
3483   const API_EC_PARAM_BAD_EID = 150;
3484   const API_EC_PARAM_UNKNOWN_CITY = 151;
3485   const API_EC_PARAM_BAD_PAGE_TYPE = 152;
3486   const API_EC_PARAM_BAD_LOCALE = 170;
3487   const API_EC_PARAM_BLOCKED_NOTIFICATION = 180;
3488
3489   /*
3490    * USER PERMISSIONS ERRORS
3491    */
3492   const API_EC_PERMISSION = 200;
3493   const API_EC_PERMISSION_USER = 210;
3494   const API_EC_PERMISSION_NO_DEVELOPERS = 211;
3495   const API_EC_PERMISSION_OFFLINE_ACCESS = 212;
3496   const API_EC_PERMISSION_ALBUM = 220;
3497   const API_EC_PERMISSION_PHOTO = 221;
3498   const API_EC_PERMISSION_MESSAGE = 230;
3499   const API_EC_PERMISSION_OTHER_USER = 240;
3500   const API_EC_PERMISSION_STATUS_UPDATE = 250;
3501   const API_EC_PERMISSION_PHOTO_UPLOAD = 260;
3502   const API_EC_PERMISSION_VIDEO_UPLOAD = 261;
3503   const API_EC_PERMISSION_SMS = 270;
3504   const API_EC_PERMISSION_CREATE_LISTING = 280;
3505   const API_EC_PERMISSION_CREATE_NOTE = 281;
3506   const API_EC_PERMISSION_SHARE_ITEM = 282;
3507   const API_EC_PERMISSION_EVENT = 290;
3508   const API_EC_PERMISSION_LARGE_FBML_TEMPLATE = 291;
3509   const API_EC_PERMISSION_LIVEMESSAGE = 292;
3510   const API_EC_PERMISSION_CREATE_EVENT = 296;
3511   const API_EC_PERMISSION_RSVP_EVENT = 299;
3512
3513   /*
3514    * DATA EDIT ERRORS
3515    */
3516   const API_EC_EDIT = 300;
3517   const API_EC_EDIT_USER_DATA = 310;
3518   const API_EC_EDIT_PHOTO = 320;
3519   const API_EC_EDIT_ALBUM_SIZE = 321;
3520   const API_EC_EDIT_PHOTO_TAG_SUBJECT = 322;
3521   const API_EC_EDIT_PHOTO_TAG_PHOTO = 323;
3522   const API_EC_EDIT_PHOTO_FILE = 324;
3523   const API_EC_EDIT_PHOTO_PENDING_LIMIT = 325;
3524   const API_EC_EDIT_PHOTO_TAG_LIMIT = 326;
3525   const API_EC_EDIT_ALBUM_REORDER_PHOTO_NOT_IN_ALBUM = 327;
3526   const API_EC_EDIT_ALBUM_REORDER_TOO_FEW_PHOTOS = 328;
3527
3528   const API_EC_MALFORMED_MARKUP = 329;
3529   const API_EC_EDIT_MARKUP = 330;
3530
3531   const API_EC_EDIT_FEED_TOO_MANY_USER_CALLS = 340;
3532   const API_EC_EDIT_FEED_TOO_MANY_USER_ACTION_CALLS = 341;
3533   const API_EC_EDIT_FEED_TITLE_LINK = 342;
3534   const API_EC_EDIT_FEED_TITLE_LENGTH = 343;
3535   const API_EC_EDIT_FEED_TITLE_NAME = 344;
3536   const API_EC_EDIT_FEED_TITLE_BLANK = 345;
3537   const API_EC_EDIT_FEED_BODY_LENGTH = 346;
3538   const API_EC_EDIT_FEED_PHOTO_SRC = 347;
3539   const API_EC_EDIT_FEED_PHOTO_LINK = 348;
3540
3541   const API_EC_EDIT_VIDEO_SIZE = 350;
3542   const API_EC_EDIT_VIDEO_INVALID_FILE = 351;
3543   const API_EC_EDIT_VIDEO_INVALID_TYPE = 352;
3544   const API_EC_EDIT_VIDEO_FILE = 353;
3545
3546   const API_EC_EDIT_FEED_TITLE_ARRAY = 360;
3547   const API_EC_EDIT_FEED_TITLE_PARAMS = 361;
3548   const API_EC_EDIT_FEED_BODY_ARRAY = 362;
3549   const API_EC_EDIT_FEED_BODY_PARAMS = 363;
3550   const API_EC_EDIT_FEED_PHOTO = 364;
3551   const API_EC_EDIT_FEED_TEMPLATE = 365;
3552   const API_EC_EDIT_FEED_TARGET = 366;
3553   const API_EC_EDIT_FEED_MARKUP = 367;
3554
3555   /**
3556    * SESSION ERRORS
3557    */
3558   const API_EC_SESSION_TIMED_OUT = 450;
3559   const API_EC_SESSION_METHOD = 451;
3560   const API_EC_SESSION_INVALID = 452;
3561   const API_EC_SESSION_REQUIRED = 453;
3562   const API_EC_SESSION_REQUIRED_FOR_SECRET = 454;
3563   const API_EC_SESSION_CANNOT_USE_SESSION_SECRET = 455;
3564
3565
3566   /**
3567    * FQL ERRORS
3568    */
3569   const FQL_EC_UNKNOWN_ERROR = 600;
3570   const FQL_EC_PARSER = 601; // backwards compatibility
3571   const FQL_EC_PARSER_ERROR = 601;
3572   const FQL_EC_UNKNOWN_FIELD = 602;
3573   const FQL_EC_UNKNOWN_TABLE = 603;
3574   const FQL_EC_NOT_INDEXABLE = 604; // backwards compatibility
3575   const FQL_EC_NO_INDEX = 604;
3576   const FQL_EC_UNKNOWN_FUNCTION = 605;
3577   const FQL_EC_INVALID_PARAM = 606;
3578   const FQL_EC_INVALID_FIELD = 607;
3579   const FQL_EC_INVALID_SESSION = 608;
3580   const FQL_EC_UNSUPPORTED_APP_TYPE = 609;
3581   const FQL_EC_SESSION_SECRET_NOT_ALLOWED = 610;
3582   const FQL_EC_DEPRECATED_TABLE = 611;
3583   const FQL_EC_EXTENDED_PERMISSION = 612;
3584   const FQL_EC_RATE_LIMIT_EXCEEDED = 613;
3585   const FQL_EC_UNRESOLVED_DEPENDENCY = 614;
3586   const FQL_EC_INVALID_SEARCH = 615;
3587   const FQL_EC_CONTAINS_ERROR = 616;
3588
3589   const API_EC_REF_SET_FAILED = 700;
3590
3591   /**
3592    * DATA STORE API ERRORS
3593    */
3594   const API_EC_DATA_UNKNOWN_ERROR = 800;
3595   const API_EC_DATA_INVALID_OPERATION = 801;
3596   const API_EC_DATA_QUOTA_EXCEEDED = 802;
3597   const API_EC_DATA_OBJECT_NOT_FOUND = 803;
3598   const API_EC_DATA_OBJECT_ALREADY_EXISTS = 804;
3599   const API_EC_DATA_DATABASE_ERROR = 805;
3600   const API_EC_DATA_CREATE_TEMPLATE_ERROR = 806;
3601   const API_EC_DATA_TEMPLATE_EXISTS_ERROR = 807;
3602   const API_EC_DATA_TEMPLATE_HANDLE_TOO_LONG = 808;
3603   const API_EC_DATA_TEMPLATE_HANDLE_ALREADY_IN_USE = 809;
3604   const API_EC_DATA_TOO_MANY_TEMPLATE_BUNDLES = 810;
3605   const API_EC_DATA_MALFORMED_ACTION_LINK = 811;
3606   const API_EC_DATA_TEMPLATE_USES_RESERVED_TOKEN = 812;
3607
3608   /*
3609    * APPLICATION INFO ERRORS
3610    */
3611   const API_EC_NO_SUCH_APP = 900;
3612
3613   /*
3614    * BATCH ERRORS
3615    */
3616   const API_EC_BATCH_TOO_MANY_ITEMS = 950;
3617   const API_EC_BATCH_ALREADY_STARTED = 951;
3618   const API_EC_BATCH_NOT_STARTED = 952;
3619   const API_EC_BATCH_METHOD_NOT_ALLOWED_IN_BATCH_MODE = 953;
3620
3621   /*
3622    * EVENT API ERRORS
3623    */
3624   const API_EC_EVENT_INVALID_TIME = 1000;
3625   const API_EC_EVENT_NAME_LOCKED  = 1001;
3626
3627   /*
3628    * INFO BOX ERRORS
3629    */
3630   const API_EC_INFO_NO_INFORMATION = 1050;
3631   const API_EC_INFO_SET_FAILED = 1051;
3632
3633   /*
3634    * LIVEMESSAGE API ERRORS
3635    */
3636   const API_EC_LIVEMESSAGE_SEND_FAILED = 1100;
3637   const API_EC_LIVEMESSAGE_EVENT_NAME_TOO_LONG = 1101;
3638   const API_EC_LIVEMESSAGE_MESSAGE_TOO_LONG = 1102;
3639
3640   /*
3641    * PAYMENTS API ERRORS
3642    */
3643   const API_EC_PAYMENTS_UNKNOWN = 1150;
3644   const API_EC_PAYMENTS_APP_INVALID = 1151;
3645   const API_EC_PAYMENTS_DATABASE = 1152;
3646   const API_EC_PAYMENTS_PERMISSION_DENIED = 1153;
3647   const API_EC_PAYMENTS_APP_NO_RESPONSE = 1154;
3648   const API_EC_PAYMENTS_APP_ERROR_RESPONSE = 1155;
3649   const API_EC_PAYMENTS_INVALID_ORDER = 1156;
3650   const API_EC_PAYMENTS_INVALID_PARAM = 1157;
3651   const API_EC_PAYMENTS_INVALID_OPERATION = 1158;
3652   const API_EC_PAYMENTS_PAYMENT_FAILED = 1159;
3653   const API_EC_PAYMENTS_DISABLED = 1160;
3654
3655   /*
3656    * CONNECT SESSION ERRORS
3657    */
3658   const API_EC_CONNECT_FEED_DISABLED = 1300;
3659
3660   /*
3661    * Platform tag bundles errors
3662    */
3663   const API_EC_TAG_BUNDLE_QUOTA = 1400;
3664
3665   /*
3666    * SHARE
3667    */
3668   const API_EC_SHARE_BAD_URL = 1500;
3669
3670   /*
3671    * NOTES
3672    */
3673   const API_EC_NOTE_CANNOT_MODIFY = 1600;
3674
3675   /*
3676    * COMMENTS
3677    */
3678   const API_EC_COMMENTS_UNKNOWN = 1700;
3679   const API_EC_COMMENTS_POST_TOO_LONG = 1701;
3680   const API_EC_COMMENTS_DB_DOWN = 1702;
3681   const API_EC_COMMENTS_INVALID_XID = 1703;
3682   const API_EC_COMMENTS_INVALID_UID = 1704;
3683   const API_EC_COMMENTS_INVALID_POST = 1705;
3684   const API_EC_COMMENTS_INVALID_REMOVE = 1706;
3685
3686   /*
3687    * GIFTS
3688    */
3689   const API_EC_GIFTS_UNKNOWN = 1900;
3690
3691   /*
3692    * APPLICATION MORATORIUM ERRORS
3693    */
3694   const API_EC_DISABLED_ALL = 2000;
3695   const API_EC_DISABLED_STATUS = 2001;
3696   const API_EC_DISABLED_FEED_STORIES = 2002;
3697   const API_EC_DISABLED_NOTIFICATIONS = 2003;
3698   const API_EC_DISABLED_REQUESTS = 2004;
3699   const API_EC_DISABLED_EMAIL = 2005;
3700
3701   /**
3702    * This array is no longer maintained; to view the description of an error
3703    * code, please look at the message element of the API response or visit
3704    * the developer wiki at http://wiki.developers.facebook.com/.
3705    */
3706   public static $api_error_descriptions = array(
3707       self::API_EC_SUCCESS           => 'Success',
3708       self::API_EC_UNKNOWN           => 'An unknown error occurred',
3709       self::API_EC_SERVICE           => 'Service temporarily unavailable',
3710       self::API_EC_METHOD            => 'Unknown method',
3711       self::API_EC_TOO_MANY_CALLS    => 'Application request limit reached',
3712       self::API_EC_BAD_IP            => 'Unauthorized source IP address',
3713       self::API_EC_PARAM             => 'Invalid parameter',
3714       self::API_EC_PARAM_API_KEY     => 'Invalid API key',
3715       self::API_EC_PARAM_SESSION_KEY => 'Session key invalid or no longer valid',
3716       self::API_EC_PARAM_CALL_ID     => 'Call_id must be greater than previous',
3717       self::API_EC_PARAM_SIGNATURE   => 'Incorrect signature',
3718       self::API_EC_PARAM_USER_ID     => 'Invalid user id',
3719       self::API_EC_PARAM_USER_FIELD  => 'Invalid user info field',
3720       self::API_EC_PARAM_SOCIAL_FIELD => 'Invalid user field',
3721       self::API_EC_PARAM_USER_ID_LIST => 'Invalid user id list',
3722       self::API_EC_PARAM_FIELD_LIST => 'Invalid field list',
3723       self::API_EC_PARAM_ALBUM_ID    => 'Invalid album id',
3724       self::API_EC_PARAM_BAD_EID     => 'Invalid eid',
3725       self::API_EC_PARAM_UNKNOWN_CITY => 'Unknown city',
3726       self::API_EC_PERMISSION        => 'Permissions error',
3727       self::API_EC_PERMISSION_USER   => 'User not visible',
3728       self::API_EC_PERMISSION_NO_DEVELOPERS  => 'Application has no developers',
3729       self::API_EC_PERMISSION_ALBUM  => 'Album not visible',
3730       self::API_EC_PERMISSION_PHOTO  => 'Photo not visible',
3731       self::API_EC_PERMISSION_EVENT  => 'Creating and modifying events required the extended permission create_event',
3732       self::API_EC_PERMISSION_RSVP_EVENT => 'RSVPing to events required the extended permission rsvp_event',
3733       self::API_EC_EDIT_ALBUM_SIZE   => 'Album is full',
3734       self::FQL_EC_PARSER            => 'FQL: Parser Error',
3735       self::FQL_EC_UNKNOWN_FIELD     => 'FQL: Unknown Field',
3736       self::FQL_EC_UNKNOWN_TABLE     => 'FQL: Unknown Table',
3737       self::FQL_EC_NOT_INDEXABLE     => 'FQL: Statement not indexable',
3738       self::FQL_EC_UNKNOWN_FUNCTION  => 'FQL: Attempted to call unknown function',
3739       self::FQL_EC_INVALID_PARAM     => 'FQL: Invalid parameter passed in',
3740       self::API_EC_DATA_UNKNOWN_ERROR => 'Unknown data store API error',
3741       self::API_EC_DATA_INVALID_OPERATION => 'Invalid operation',
3742       self::API_EC_DATA_QUOTA_EXCEEDED => 'Data store allowable quota was exceeded',
3743       self::API_EC_DATA_OBJECT_NOT_FOUND => 'Specified object cannot be found',
3744       self::API_EC_DATA_OBJECT_ALREADY_EXISTS => 'Specified object already exists',
3745       self::API_EC_DATA_DATABASE_ERROR => 'A database error occurred. Please try again',
3746       self::API_EC_BATCH_ALREADY_STARTED => 'begin_batch already called, please make sure to call end_batch first',
3747       self::API_EC_BATCH_NOT_STARTED => 'end_batch called before begin_batch',
3748       self::API_EC_BATCH_METHOD_NOT_ALLOWED_IN_BATCH_MODE => 'This method is not allowed in batch mode'
3749   );
3750 }