summaryrefslogtreecommitdiff
path: root/plugins/Facebook
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Facebook')
-rw-r--r--plugins/Facebook/FacebookPlugin.php15
-rw-r--r--plugins/Facebook/facebook/facebook.php23
-rw-r--r--plugins/Facebook/facebook/facebook_desktop.php2
-rw-r--r--plugins/Facebook/facebook/facebook_mobile.php260
-rwxr-xr-xplugins/Facebook/facebook/facebookapi_php5_restlib.php382
-rw-r--r--plugins/Facebook/facebookaction.php96
-rw-r--r--plugins/Facebook/facebooknoticeform.php206
-rw-r--r--plugins/Facebook/facebookutil.php16
8 files changed, 766 insertions, 234 deletions
diff --git a/plugins/Facebook/FacebookPlugin.php b/plugins/Facebook/FacebookPlugin.php
index 39b2ef287..de91bf24a 100644
--- a/plugins/Facebook/FacebookPlugin.php
+++ b/plugins/Facebook/FacebookPlugin.php
@@ -32,6 +32,7 @@ if (!defined('STATUSNET')) {
}
define("FACEBOOK_CONNECT_SERVICE", 3);
+define('FACEBOOKPLUGIN_VERSION', '0.9');
require_once INSTALLDIR . '/plugins/Facebook/facebookutil.php';
@@ -554,4 +555,18 @@ class FacebookPlugin extends Plugin
return true;
}
+ function onPluginVersion(&$versions)
+ {
+ $versions[] = array('name' => 'Facebook',
+ 'version' => FACEBOOKPLUGIN_VERSION,
+ 'author' => 'Zach Copley',
+ 'homepage' => 'http://status.net/wiki/Plugin:Facebook',
+ 'rawdescription' =>
+ _m('The Facebook plugin allows you to integrate ' .
+ 'your StatusNet instance with ' .
+ '<a href="http://facebook.com/">Facebook</a> ' .
+ 'and Facebook Connect.'));
+ return true;
+ }
+
}
diff --git a/plugins/Facebook/facebook/facebook.php b/plugins/Facebook/facebook/facebook.php
index 016e8e8e0..440706cbc 100644
--- a/plugins/Facebook/facebook/facebook.php
+++ b/plugins/Facebook/facebook/facebook.php
@@ -82,7 +82,8 @@ class Facebook {
if (isset($this->fb_params['friends'])) {
- $this->api_client->friends_list = explode(',', $this->fb_params['friends']);
+ $this->api_client->friends_list =
+ array_filter(explode(',', $this->fb_params['friends']));
}
if (isset($this->fb_params['added'])) {
$this->api_client->added = $this->fb_params['added'];
@@ -215,11 +216,15 @@ class Facebook {
// Invalidate the session currently being used, and clear any state associated
// with it. Note that the user will still remain logged into Facebook.
public function expire_session() {
- if ($this->api_client->auth_expireSession()) {
+ try {
+ if ($this->api_client->auth_expireSession()) {
+ $this->clear_cookie_state();
+ return true;
+ } else {
+ return false;
+ }
+ } catch (Exception $e) {
$this->clear_cookie_state();
- return true;
- } else {
- return false;
}
}
@@ -249,10 +254,14 @@ class Facebook {
if (!$this->in_fb_canvas() && isset($_COOKIE[$this->api_key . '_user'])) {
$cookies = array('user', 'session_key', 'expires', 'ss');
foreach ($cookies as $name) {
- setcookie($this->api_key . '_' . $name, false, time() - 3600);
+ setcookie($this->api_key . '_' . $name,
+ false,
+ time() - 3600,
+ '',
+ $this->base_domain);
unset($_COOKIE[$this->api_key . '_' . $name]);
}
- setcookie($this->api_key, false, time() - 3600);
+ setcookie($this->api_key, false, time() - 3600, '', $this->base_domain);
unset($_COOKIE[$this->api_key]);
}
diff --git a/plugins/Facebook/facebook/facebook_desktop.php b/plugins/Facebook/facebook/facebook_desktop.php
index e79a2ca34..ed4762215 100644
--- a/plugins/Facebook/facebook/facebook_desktop.php
+++ b/plugins/Facebook/facebook/facebook_desktop.php
@@ -60,7 +60,7 @@ class FacebookDesktop extends Facebook {
public function set_session_secret($session_secret) {
$this->secret = $session_secret;
- $this->api_client->secret = $session_secret;
+ $this->api_client->use_session_secret($session_secret);
}
public function require_login() {
diff --git a/plugins/Facebook/facebook/facebook_mobile.php b/plugins/Facebook/facebook/facebook_mobile.php
new file mode 100644
index 000000000..5ee7f4ed5
--- /dev/null
+++ b/plugins/Facebook/facebook/facebook_mobile.php
@@ -0,0 +1,260 @@
+<?php
+// Copyright 2004-2009 Facebook. All Rights Reserved.
+//
+// +---------------------------------------------------------------------------+
+// | Facebook Platform PHP5 client |
+// +---------------------------------------------------------------------------+
+// | Copyright (c) 2007 Facebook, Inc. |
+// | All rights reserved. |
+// | |
+// | Redistribution and use in source and binary forms, with or without |
+// | modification, are permitted provided that the following conditions |
+// | are met: |
+// | |
+// | 1. Redistributions of source code must retain the above copyright |
+// | notice, this list of conditions and the following disclaimer. |
+// | 2. Redistributions in binary form must reproduce the above copyright |
+// | notice, this list of conditions and the following disclaimer in the |
+// | documentation and/or other materials provided with the distribution. |
+// | |
+// | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
+// | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
+// | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
+// | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
+// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
+// | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
+// | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+// +---------------------------------------------------------------------------+
+// | For help with this library, contact developers-help@facebook.com |
+// +---------------------------------------------------------------------------+
+//
+/**
+ * This class extends and modifies the "Facebook" class to better suit wap
+ * apps. Since there is no javascript support, we need to use server redirect
+ * to implement Facebook connect functionalities such as authenticate,
+ * authorize, feed form etc.. This library provide many helper functions for
+ * wap developer to locate the right wap url. The url here is targed at
+ * facebook wap site or wap-friendly url.
+ */
+class FacebookMobile extends Facebook {
+ // the application secret, which differs from the session secret
+
+ public function __construct($api_key, $secret, $generate_session_secret=false) {
+ parent::__construct($api_key, $secret, $generate_session_secret);
+ }
+
+ public function redirect($url) {
+ header('Location: '. $url);
+ }
+
+ public function get_m_url($action, $params) {
+ $page = parent::get_facebook_url('m'). '/' .$action;
+ foreach($params as $key => $val) {
+ if (!$val) {
+ unset($params[$key]);
+ }
+ }
+ return $page . '?' . http_build_query($params);
+ }
+
+ public function get_www_url($action, $params) {
+ $page = parent::get_facebook_url('www'). '/' .$action;
+ foreach($params as $key => $val) {
+ if (!$val) {
+ unset($params[$key]);
+ }
+ }
+ return $page . '?' . http_build_query($params);
+ }
+
+ public function get_add_url($next=null) {
+
+ return $this->get_m_url('add.php', array('api_key' => $this->api_key,
+ 'next' => $next));
+ }
+
+ public function get_tos_url($next=null, $cancel = null, $canvas=null) {
+ return $this->get_m_url('tos.php', array('api_key' => $this->api_key,
+ 'v' => '1.0',
+ 'next' => $next,
+ 'canvas' => $canvas,
+ 'cancel' => $cancel));
+ }
+
+ public function get_logout_url($next=null) {
+ $params = array('api_key' => $this->api_key,
+ 'session_key' => $this->api_client->session_key,
+ );
+
+ if ($next) {
+ $params['connect_next'] = 1;
+ $params['next'] = $next;
+ }
+
+ return $this->get_m_url('logout.php', $params);
+ }
+ public function get_register_url($next=null, $cancel_url=null) {
+ return $this->get_m_url('r.php',
+ array('fbconnect' => 1,
+ 'api_key' => $this->api_key,
+ 'next' => $next ? $next : parent::current_url(),
+ 'cancel_url' => $cancel_url ? $cancel_url : parent::current_url()));
+ }
+ /**
+ * These set of fbconnect style url redirect back to the application current
+ * page when the action is done. Developer can also use the non fbconnect
+ * style url and provide their own redirect link by giving the right parameter
+ * to $next and/or $cancel_url
+ */
+ public function get_fbconnect_register_url() {
+ return $this->get_register_url(parent::current_url(), parent::current_url());
+ }
+ public function get_fbconnect_tos_url() {
+ return $this->get_tos_url(parent::current_url(), parent::current_url(), $this->in_frame());
+ }
+
+ public function get_fbconnect_logout_url() {
+ return $this->get_logout_url(parent::current_url());
+ }
+
+ public function logout_user() {
+ $this->user = null;
+ }
+
+ public function get_prompt_permissions_url($ext_perm,
+ $next=null,
+ $cancel_url=null) {
+
+ return $this->get_www_url('connect/prompt_permissions.php',
+ array('api_key' => $this->api_key,
+ 'ext_perm' => $ext_perm,
+ 'next' => $next ? $next : parent::current_url(),
+ 'cancel' => $cancel_url ? $cancel_url : parent::current_url(),
+ 'display' => 'wap'));
+
+ }
+
+ /**
+ * support both prompt_permissions.php and authorize.php for now.
+ * authorized.php is to be deprecate though.
+ */
+ public function get_extended_permission_url($ext_perm,
+ $next=null,
+ $cancel_url=null) {
+ $next = $next ? $next : parent::current_url();
+ $cancel_url = $cancel_url ? $cancel_url : parent::current_url();
+
+ return $this->get_m_url('authorize.php',
+ array('api_key' => $this->api_key,
+ 'ext_perm' => $ext_perm,
+ 'next' => $next,
+ 'cancel_url' => $cancel_url));
+
+ }
+
+ public function render_prompt_feed_url($action_links=NULL,
+ $target_id=NULL,
+ $message='',
+ $user_message_prompt='',
+ $caption=NULL,
+ $callback ='',
+ $cancel='',
+ $attachment=NULL,
+ $preview=true) {
+
+ $params = array('api_key' => $this->api_key,
+ 'session_key' => $this->api_client->session_key,
+ );
+ if (!empty($attachment)) {
+ $params['attachment'] = urlencode(json_encode($attachment));
+ } else {
+ $attachment = new stdClass();
+ $app_display_info = $this->api_client->admin_getAppProperties(array('application_name',
+ 'callback_url',
+ 'description',
+ 'logo_url'));
+ $app_display_info = $app_display_info;
+ $attachment->name = $app_display_info['application_name'];
+ $attachment->caption = !empty($caption) ? $caption : 'Just see what\'s new!';
+ $attachment->description = $app_display_info['description'];
+ $attachment->href = $app_display_info['callback_url'];
+ if (!empty($app_display_info['logo_url'])) {
+ $logo = new stdClass();
+ $logo->type = 'image';
+ $logo->src = $app_display_info['logo_url'];
+ $logo->href = $app_display_info['callback_url'];
+ $attachment->media = array($logo);
+ }
+ $params['attachment'] = urlencode(json_encode($attachment));
+ }
+ $params['preview'] = $preview;
+ $params['message'] = $message;
+ $params['user_message_prompt'] = $user_message_prompt;
+ if (!empty($callback)) {
+ $params['callback'] = $callback;
+ } else {
+ $params['callback'] = $this->current_url();
+ }
+ if (!empty($cancel)) {
+ $params['cancel'] = $cancel;
+ } else {
+ $params['cancel'] = $this->current_url();
+ }
+
+ if (!empty($target_id)) {
+ $params['target_id'] = $target_id;
+ }
+ if (!empty($action_links)) {
+ $params['action_links'] = urlencode(json_encode($action_links));
+ }
+
+ $params['display'] = 'wap';
+ header('Location: '. $this->get_www_url('connect/prompt_feed.php', $params));
+ }
+
+//use template_id
+ public function render_feed_form_url($template_id=NULL,
+ $template_data=NULL,
+ $user_message=NULL,
+ $body_general=NULL,
+ $user_message_prompt=NULL,
+ $target_id=NULL,
+ $callback=NULL,
+ $cancel=NULL,
+ $preview=true) {
+
+ $params = array('api_key' => $this->api_key);
+ $params['preview'] = $preview;
+ if (isset($template_id) && $template_id) {
+ $params['template_id'] = $template_id;
+ }
+ $params['message'] = $user_message ? $user_message['value'] : '';
+ if (isset($body_general) && $body_general) {
+ $params['body_general'] = $body_general;
+ }
+ if (isset($user_message_prompt) && $user_message_prompt) {
+ $params['user_message_prompt'] = $user_message_prompt;
+ }
+ if (isset($callback) && $callback) {
+ $params['callback'] = $callback;
+ } else {
+ $params['callback'] = $this->current_url();
+ }
+ if (isset($cancel) && $cancel) {
+ $params['cancel'] = $cancel;
+ } else {
+ $params['cancel'] = $this->current_url();
+ }
+ if (isset($template_data) && $template_data) {
+ $params['template_data'] = $template_data;
+ }
+ if (isset($target_id) && $target_id) {
+ $params['to_ids'] = $target_id;
+ }
+ $params['display'] = 'wap';
+ header('Location: '. $this->get_www_url('connect/prompt_feed.php', $params));
+ }
+}
diff --git a/plugins/Facebook/facebook/facebookapi_php5_restlib.php b/plugins/Facebook/facebook/facebookapi_php5_restlib.php
index 55cb7fb86..fa1088cd0 100755
--- a/plugins/Facebook/facebook/facebookapi_php5_restlib.php
+++ b/plugins/Facebook/facebook/facebookapi_php5_restlib.php
@@ -56,6 +56,8 @@ class FacebookRestClient {
private $call_as_apikey;
private $use_curl_if_available;
private $format = null;
+ private $using_session_secret = false;
+ private $rawData = null;
const BATCH_MODE_DEFAULT = 0;
const BATCH_MODE_SERVER_PARALLEL = 0;
@@ -76,7 +78,10 @@ class FacebookRestClient {
$this->last_call_id = 0;
$this->call_as_apikey = '';
$this->use_curl_if_available = true;
- $this->server_addr = Facebook::get_facebook_url('api') . '/restserver.php';
+ $this->server_addr =
+ Facebook::get_facebook_url('api') . '/restserver.php';
+ $this->photo_server_addr =
+ Facebook::get_facebook_url('api-photo') . '/restserver.php';
if (!empty($GLOBALS['facebook_config']['debug'])) {
$this->cur_id = 0;
@@ -128,6 +133,16 @@ function toggleDisplay(id, type) {
$this->user = $uid;
}
+
+ /**
+ * Switch to use the session secret instead of the app secret,
+ * for desktop and unsecured environment
+ */
+ public function use_session_secret($session_secret) {
+ $this->secret = $session_secret;
+ $this->using_session_secret = true;
+ }
+
/**
* Normally, if the cURL library/PHP extension is available, it is used for
* HTTP transactions. This allows that behavior to be overridden, falling
@@ -270,25 +285,35 @@ function toggleDisplay(id, type) {
/**
* Returns the session information available after current user logs in.
*
- * @param string $auth_token the token returned by
- * auth_createToken or passed back to
- * your callback_url.
- * @param bool $generate_session_secret whether the session returned should
- * include a session secret
+ * @param string $auth_token the token returned by auth_createToken or
+ * passed back to your callback_url.
+ * @param bool $generate_session_secret whether the session returned should
+ * include a session secret
+ * @param string $host_url the connect site URL for which the session is
+ * being generated. This parameter is optional, unless
+ * you want Facebook to determine which of several base domains
+ * to choose from. If this third argument isn't provided but
+ * there are several base domains, the first base domain is
+ * chosen.
*
* @return array An assoc array containing session_key, uid
*/
- public function auth_getSession($auth_token, $generate_session_secret=false) {
+ public function auth_getSession($auth_token,
+ $generate_session_secret = false,
+ $host_url = null) {
if (!$this->pending_batch()) {
- $result = $this->call_method('facebook.auth.getSession',
- array('auth_token' => $auth_token,
- 'generate_session_secret' => $generate_session_secret));
+ $result = $this->call_method(
+ 'facebook.auth.getSession',
+ array('auth_token' => $auth_token,
+ 'generate_session_secret' => $generate_session_secret,
+ 'host_url' => $host_url));
$this->session_key = $result['session_key'];
- if (!empty($result['secret']) && !$generate_session_secret) {
- // desktop apps have a special secret
- $this->secret = $result['secret'];
- }
+ if (!empty($result['secret']) && !$generate_session_secret) {
+ // desktop apps have a special secret
+ $this->secret = $result['secret'];
+ }
+
return $result;
}
}
@@ -519,7 +544,7 @@ function toggleDisplay(id, type) {
return $this->call_upload_method('facebook.events.create',
array('event_info' => $event_info),
$file,
- Facebook::get_facebook_url('api-photo') . '/restserver.php');
+ $this->photo_server_addr);
} else {
return $this->call_method('facebook.events.create',
array('event_info' => $event_info));
@@ -527,6 +552,27 @@ function toggleDisplay(id, type) {
}
/**
+ * Invites users to an event. If a session user exists, the session user
+ * must have permissions to invite friends to the event and $uids must contain
+ * a list of friend ids. Otherwise, the event must have been
+ * created by the app and $uids must contain users of the app.
+ * This method requires the 'create_event' extended permission to
+ * invite people on behalf of a user.
+ *
+ * @param $eid the event id
+ * @param $uids an array of users to invite
+ * @param $personal_message a string containing the user's message
+ * (text only)
+ *
+ */
+ public function events_invite($eid, $uids, $personal_message) {
+ return $this->call_method('facebook.events.invite',
+ array('eid' => $eid,
+ 'uids' => $uids,
+ 'personal_message', $personal_message));
+ }
+
+ /**
* Edits an existing event. Only works for events where application is admin.
*
* @param int $eid event id
@@ -540,7 +586,7 @@ function toggleDisplay(id, type) {
return $this->call_upload_method('facebook.events.edit',
array('eid' => $eid, 'event_info' => $event_info),
$file,
- Facebook::get_facebook_url('api-photo') . '/restserver.php');
+ $this->photo_server_addr);
} else {
return $this->call_method('facebook.events.edit',
array('eid' => $eid,
@@ -576,21 +622,7 @@ function toggleDisplay(id, type) {
array('url' => $url));
}
- /**
- * Lets you insert text strings in their native language into the Facebook
- * Translations database so they can be translated.
- *
- * @param array $native_strings An array of maps, where each map has a 'text'
- * field and a 'description' field.
- *
- * @return int Number of strings uploaded.
- */
- public function &fbml_uploadNativeStrings($native_strings) {
- return $this->call_method('facebook.fbml.uploadNativeStrings',
- array('native_strings' => json_encode($native_strings)));
- }
-
- /**
+ /**
* Associates a given "handle" with FBML markup so that the handle can be
* used within the fb:ref FBML tag. A handle is unique within an application
* and allows an application to publish identical FBML to many user profiles
@@ -668,7 +700,44 @@ function toggleDisplay(id, type) {
array('tag_names' => json_encode($tag_names)));
}
+ /**
+ * Gets the best translations for native strings submitted by an application
+ * for translation. If $locale is not specified, only native strings and their
+ * descriptions are returned. If $all is true, then unapproved translations
+ * are returned as well, otherwise only approved translations are returned.
+ *
+ * A mapping of locale codes -> language names is available at
+ * http://wiki.developers.facebook.com/index.php/Facebook_Locales
+ *
+ * @param string $locale the locale to get translations for, or 'all' for all
+ * locales, or 'en_US' for native strings
+ * @param bool $all whether to return all or only approved translations
+ *
+ * @return array (locale, array(native_strings, array('best translation
+ * available given enough votes or manual approval', approval
+ * status)))
+ * @error API_EC_PARAM
+ * @error API_EC_PARAM_BAD_LOCALE
+ */
+ public function &intl_getTranslations($locale = 'en_US', $all = false) {
+ return $this->call_method('facebook.intl.getTranslations',
+ array('locale' => $locale,
+ 'all' => $all));
+ }
+ /**
+ * Lets you insert text strings in their native language into the Facebook
+ * Translations database so they can be translated.
+ *
+ * @param array $native_strings An array of maps, where each map has a 'text'
+ * field and a 'description' field.
+ *
+ * @return int Number of strings uploaded.
+ */
+ public function &intl_uploadNativeStrings($native_strings) {
+ return $this->call_method('facebook.intl.uploadNativeStrings',
+ array('native_strings' => json_encode($native_strings)));
+ }
/**
* This method is deprecated for calls made on behalf of users. This method
@@ -1249,6 +1318,87 @@ function toggleDisplay(id, type) {
}
/**
+ * Gifts API
+ */
+
+ /**
+ * Get Gifts associated with an app
+ *
+ * @return array of gifts
+ */
+ public function gifts_get() {
+ return json_decode(
+ $this->call_method('facebook.gifts.get',
+ array()),
+ true
+ );
+ }
+
+ /*
+ * Update gifts stored by an app
+ *
+ * @param array containing gift_id => gift_data to be updated
+ * @return array containing gift_id => true/false indicating success
+ * in updating that gift
+ */
+ public function gifts_update($update_array) {
+ return json_decode(
+ $this->call_method('facebook.gifts.update',
+ array('update_str' => json_encode($update_array))
+ ),
+ true
+ );
+ }
+
+ /**
+ * Dashboard API
+ */
+
+ /**
+ * Set the news for the specified user.
+ *
+ * @param int $uid The user for whom you are setting news for
+ * @param string $news Text of news to display
+ *
+ * @return bool Success
+ */
+ public function dashboard_setNews($uid, $news) {
+ return $this->call_method('facebook.dashboard.setNews',
+ array('uid' => $uid,
+ 'news' => $news)
+ );
+ }
+
+ /**
+ * Get the current news of the specified user.
+ *
+ * @param int $uid The user to get the news of
+ *
+ * @return string The text of the current news for the user
+ */
+ public function dashboard_getNews($uid) {
+ return json_decode(
+ $this->call_method('facebook.dashboard.getNews',
+ array('uid' => $uid)
+ ), true);
+ }
+
+ /**
+ * Set the news for the specified user.
+ *
+ * @param int $uid The user you are clearing the news of
+ *
+ * @return bool Success
+ */
+ public function dashboard_clearNews($uid) {
+ return $this->call_method('facebook.dashboard.clearNews',
+ array('uid' => $uid)
+ );
+ }
+
+
+
+ /**
* Creates a note with the specified title and content.
*
* @param string $title Title of the note.
@@ -1795,14 +1945,20 @@ function toggleDisplay(id, type) {
$start_time = 0,
$end_time = 0,
$limit = 30,
- $filter_key = '') {
+ $filter_key = '',
+ $exportable_only = false,
+ $metadata = null,
+ $post_ids = null) {
$args = array(
'viewer_id' => $viewer_id,
'source_ids' => $source_ids,
'start_time' => $start_time,
'end_time' => $end_time,
'limit' => $limit,
- 'filter_key' => $filter_key);
+ 'filter_key' => $filter_key,
+ 'exportable_only' => $exportable_only,
+ 'metadata' => $metadata,
+ 'post_ids' => $post_ids);
return $this->call_method('facebook.stream.get', $args);
}
@@ -1949,97 +2105,6 @@ function toggleDisplay(id, type) {
'options' => json_encode($options)));
}
- /**
- * Get all the marketplace categories.
- *
- * @return array A list of category names
- */
- function marketplace_getCategories() {
- return $this->call_method('facebook.marketplace.getCategories',
- array());
- }
-
- /**
- * Get all the marketplace subcategories for a particular category.
- *
- * @param category The category for which we are pulling subcategories
- *
- * @return array A list of subcategory names
- */
- function marketplace_getSubCategories($category) {
- return $this->call_method('facebook.marketplace.getSubCategories',
- array('category' => $category));
- }
-
- /**
- * Get listings by either listing_id or user.
- *
- * @param listing_ids An array of listing_ids (optional)
- * @param uids An array of user ids (optional)
- *
- * @return array The data for matched listings
- */
- function marketplace_getListings($listing_ids, $uids) {
- return $this->call_method('facebook.marketplace.getListings',
- array('listing_ids' => $listing_ids, 'uids' => $uids));
- }
-
- /**
- * Search for Marketplace listings. All arguments are optional, though at
- * least one must be filled out to retrieve results.
- *
- * @param category The category in which to search (optional)
- * @param subcategory The subcategory in which to search (optional)
- * @param query A query string (optional)
- *
- * @return array The data for matched listings
- */
- function marketplace_search($category, $subcategory, $query) {
- return $this->call_method('facebook.marketplace.search',
- array('category' => $category,
- 'subcategory' => $subcategory,
- 'query' => $query));
- }
-
- /**
- * Remove a listing from Marketplace.
- *
- * @param listing_id The id of the listing to be removed
- * @param status 'SUCCESS', 'NOT_SUCCESS', or 'DEFAULT'
- *
- * @return bool True on success
- */
- function marketplace_removeListing($listing_id,
- $status='DEFAULT',
- $uid=null) {
- return $this->call_method('facebook.marketplace.removeListing',
- array('listing_id' => $listing_id,
- 'status' => $status,
- 'uid' => $uid));
- }
-
- /**
- * Create/modify a Marketplace listing for the loggedinuser.
- *
- * @param int listing_id The id of a listing to be modified, 0
- * for a new listing.
- * @param show_on_profile bool Should we show this listing on the
- * user's profile
- * @param listing_attrs array An array of the listing data
- *
- * @return int The listing_id (unchanged if modifying an existing listing).
- */
- function marketplace_createListing($listing_id,
- $show_on_profile,
- $attrs,
- $uid=null) {
- return $this->call_method('facebook.marketplace.createListing',
- array('listing_id' => $listing_id,
- 'show_on_profile' => $show_on_profile,
- 'listing_attrs' => json_encode($attrs),
- 'uid' => $uid));
- }
-
/////////////////////////////////////////////////////////////////////////////
// Data Store API
@@ -2876,6 +2941,35 @@ function toggleDisplay(id, type) {
}
/**
+ * Sets href and text for a Live Stream Box xid's via link
+ *
+ * @param string $xid xid of the Live Stream
+ * @param string $via_href Href for the via link
+ * @param string $via_text Text for the via link
+ *
+ * @return boolWhether the set was successful
+ */
+ public function admin_setLiveStreamViaLink($xid, $via_href, $via_text) {
+ return $this->call_method('facebook.admin.setLiveStreamViaLink',
+ array('xid' => $xid,
+ 'via_href' => $via_href,
+ 'via_text' => $via_text));
+ }
+
+ /**
+ * Gets href and text for a Live Stream Box xid's via link
+ *
+ * @param string $xid xid of the Live Stream
+ *
+ * @return Array Associative array with keys 'via_href' and 'via_text'
+ * False if there was an error.
+ */
+ public function admin_getLiveStreamViaLink($xid) {
+ return $this->call_method('facebook.admin.getLiveStreamViaLink',
+ array('xid' => $xid));
+ }
+
+ /**
* Returns the allocation limit value for a specified integration point name
* Integration point names are defined in lib/api/karma/constants.php in the
* limit_map.
@@ -3012,6 +3106,7 @@ function toggleDisplay(id, type) {
$params['call_as_apikey'] = $this->call_as_apikey;
}
$data = $this->post_request($method, $params);
+ $this->rawData = $data;
$result = $this->convert_result($data, $method, $params);
if (is_array($result) && isset($result['error_code'])) {
throw new FacebookRestClientException($result['error_msg'],
@@ -3054,6 +3149,16 @@ function toggleDisplay(id, type) {
}
/**
+ * Returns the raw JSON or XML output returned by the server in the most
+ * recent API call.
+ *
+ * @return string
+ */
+ public function getRawData() {
+ return $this->rawData;
+ }
+
+ /**
* Calls the specified file-upload POST method with the specified parameters
*
* @param string $method Name of the Facebook method to invoke
@@ -3144,6 +3249,10 @@ function toggleDisplay(id, type) {
if ($this->call_as_apikey) {
$get['call_as_apikey'] = $this->call_as_apikey;
}
+ if ($this->using_session_secret) {
+ $get['ss'] = '1';
+ }
+
$get['method'] = $method;
$get['session_key'] = $this->session_key;
$get['api_key'] = $this->api_key;
@@ -3241,7 +3350,7 @@ function toggleDisplay(id, type) {
return $result;
}
- private function post_upload_request($method, $params, $file, $server_addr = null) {
+ protected function post_upload_request($method, $params, $file, $server_addr = null) {
$server_addr = $server_addr ? $server_addr : $this->server_addr;
list($get, $post) = $this->finalize_params($method, $params);
$get_string = $this->create_url_string($get);
@@ -3345,6 +3454,8 @@ class FacebookAPIErrorCodes {
const API_EC_VERSION = 12;
const API_EC_INTERNAL_FQL_ERROR = 13;
const API_EC_HOST_PUP = 14;
+ const API_EC_SESSION_SECRET_NOT_ALLOWED = 15;
+ const API_EC_HOST_READONLY = 16;
/*
* PARAMETER ERRORS
@@ -3372,6 +3483,8 @@ class FacebookAPIErrorCodes {
const API_EC_PARAM_BAD_EID = 150;
const API_EC_PARAM_UNKNOWN_CITY = 151;
const API_EC_PARAM_BAD_PAGE_TYPE = 152;
+ const API_EC_PARAM_BAD_LOCALE = 170;
+ const API_EC_PARAM_BLOCKED_NOTIFICATION = 180;
/*
* USER PERMISSIONS ERRORS
@@ -3394,6 +3507,7 @@ class FacebookAPIErrorCodes {
const API_EC_PERMISSION_EVENT = 290;
const API_EC_PERMISSION_LARGE_FBML_TEMPLATE = 291;
const API_EC_PERMISSION_LIVEMESSAGE = 292;
+ const API_EC_PERMISSION_CREATE_EVENT = 296;
const API_EC_PERMISSION_RSVP_EVENT = 299;
/*
@@ -3469,6 +3583,8 @@ class FacebookAPIErrorCodes {
const FQL_EC_EXTENDED_PERMISSION = 612;
const FQL_EC_RATE_LIMIT_EXCEEDED = 613;
const FQL_EC_UNRESOLVED_DEPENDENCY = 614;
+ const FQL_EC_INVALID_SEARCH = 615;
+ const FQL_EC_CONTAINS_ERROR = 616;
const API_EC_REF_SET_FAILED = 700;
@@ -3506,6 +3622,7 @@ class FacebookAPIErrorCodes {
* EVENT API ERRORS
*/
const API_EC_EVENT_INVALID_TIME = 1000;
+ const API_EC_EVENT_NAME_LOCKED = 1001;
/*
* INFO BOX ERRORS
@@ -3566,6 +3683,21 @@ class FacebookAPIErrorCodes {
const API_EC_COMMENTS_INVALID_POST = 1705;
const API_EC_COMMENTS_INVALID_REMOVE = 1706;
+ /*
+ * GIFTS
+ */
+ const API_EC_GIFTS_UNKNOWN = 1900;
+
+ /*
+ * APPLICATION MORATORIUM ERRORS
+ */
+ const API_EC_DISABLED_ALL = 2000;
+ const API_EC_DISABLED_STATUS = 2001;
+ const API_EC_DISABLED_FEED_STORIES = 2002;
+ const API_EC_DISABLED_NOTIFICATIONS = 2003;
+ const API_EC_DISABLED_REQUESTS = 2004;
+ const API_EC_DISABLED_EMAIL = 2005;
+
/**
* This array is no longer maintained; to view the description of an error
* code, please look at the message element of the API response or visit
diff --git a/plugins/Facebook/facebookaction.php b/plugins/Facebook/facebookaction.php
index 24bf215fd..bf9c037a5 100644
--- a/plugins/Facebook/facebookaction.php
+++ b/plugins/Facebook/facebookaction.php
@@ -32,7 +32,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
}
require_once INSTALLDIR . '/plugins/Facebook/facebookutil.php';
-require_once INSTALLDIR . '/lib/noticeform.php';
+require_once INSTALLDIR . '/plugins/Facebook/facebooknoticeform.php';
class FacebookAction extends Action
{
@@ -294,63 +294,7 @@ class FacebookAction extends Action
$app_props = $this->facebook->api_client->Admin_getAppProperties(array('icon_url'));
$icon_url = $app_props['icon_url'];
- $style = '<style>
- .entry-title *,
- .entry-content * {
- font-size:14px;
- font-family:"Lucida Sans Unicode", "Lucida Grande", sans-serif;
- }
- .entry-title a,
- .entry-content a {
- color:#002E6E;
- }
-
- .entry-title .vcard .photo {
- float:left;
- display:inline;
- margin-right:11px;
- margin-bottom:11px
- }
- .entry-title {
- margin-bottom:11px;
- }
- .entry-title p.entry-content {
- display:inline;
- margin-left:5px;
- }
-
- div.entry-content {
- clear:both;
- }
- div.entry-content dl,
- div.entry-content dt,
- div.entry-content dd {
- display:inline;
- text-transform:lowercase;
- }
-
- div.entry-content dd,
- div.entry-content .device dt {
- margin-left:0;
- margin-right:5px;
- }
- div.entry-content dl.timestamp dt,
- div.entry-content dl.response dt {
- display:none;
- }
- div.entry-content dd a {
- display:inline-block;
- }
-
- #facebook_statusnet_app {
- text-indent:-9999px;
- height:16px;
- width:16px;
- display:block;
- background:url('.$icon_url.') no-repeat 0 0;
- float:right;
- }
- </style>';
+ $style = '<style> .entry-title *, .entry-content * { font-size:14px; font-family:"Lucida Sans Unicode", "Lucida Grande", sans-serif; } .entry-title a, .entry-content a { color:#002E6E; } .entry-title .vcard .photo { float:left; display:inline; margin-right:11px; margin-bottom:11px } .entry-title { margin-bottom:11px; } .entry-title p.entry-content { display:inline; margin-left:5px; } div.entry-content { clear:both; } div.entry-content dl, div.entry-content dt, div.entry-content dd { display:inline; text-transform:lowercase; } div.entry-content dd, div.entry-content .device dt { margin-left:0; margin-right:5px; } div.entry-content dl.timestamp dt, div.entry-content dl.response dt { display:none; } div.entry-content dd a { display:inline-block; } #facebook_statusnet_app { text-indent:-9999px; height:16px; width:16px; display:block; background:url('.$icon_url.') no-repeat 0 0; float:right; } </style>';
$this->xw->openMemory();
@@ -455,42 +399,6 @@ class FacebookAction extends Action
common_broadcast_notice($notice);
- // Also update the user's Facebook status
- facebookBroadcastNotice($notice);
-
- }
-
-}
-
-class FacebookNoticeForm extends NoticeForm
-{
-
- var $post_action = null;
-
- /**
- * Constructor
- *
- * @param HTMLOutputter $out output channel
- * @param string $action action to return to, if any
- * @param string $content content to pre-fill
- */
-
- function __construct($out=null, $action=null, $content=null,
- $post_action=null, $user=null)
- {
- parent::__construct($out, $action, $content, $user);
- $this->post_action = $post_action;
- }
-
- /**
- * Action of the form
- *
- * @return string URL of the action
- */
-
- function action()
- {
- return $this->post_action;
}
}
diff --git a/plugins/Facebook/facebooknoticeform.php b/plugins/Facebook/facebooknoticeform.php
new file mode 100644
index 000000000..5989147f4
--- /dev/null
+++ b/plugins/Facebook/facebooknoticeform.php
@@ -0,0 +1,206 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Form for posting a notice from within the Facebook App.
+ *
+ * This is a stripped down version of the normal NoticeForm (sans
+ * location stuff and media upload stuff). I'm not sure we can share the
+ * location (from FB) and they don't allow posting multipart form data
+ * to Facebook canvas pages, so that won't work anyway. --Zach
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Form
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Sarven Capadisli <csarven@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/form.php';
+
+/**
+ * Form for posting a notice from within the Facebook app
+ *
+ * @category Form
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Sarven Capadisli <csarven@status.net>
+ * @author Zach Copey <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ *
+ * @see HTMLOutputter
+ */
+
+class FacebookNoticeForm extends Form
+{
+ /**
+ * Current action, used for returning to this page.
+ */
+
+ var $action = null;
+
+ /**
+ * Pre-filled content of the form
+ */
+
+ var $content = null;
+
+ /**
+ * The current user
+ */
+
+ var $user = null;
+
+ /**
+ * The notice being replied to
+ */
+
+ var $inreplyto = null;
+
+ /**
+ * Constructor
+ *
+ * @param HTMLOutputter $out output channel
+ * @param string $action action to return to, if any
+ * @param string $content content to pre-fill
+ */
+
+ function __construct($out=null, $action=null, $content=null, $post_action=null, $user=null, $inreplyto=null)
+ {
+ parent::__construct($out);
+
+ $this->action = $action;
+ $this->post_action = $post_action;
+ $this->content = $content;
+ $this->inreplyto = $inreplyto;
+
+ if ($user) {
+ $this->user = $user;
+ } else {
+ $this->user = common_current_user();
+ }
+
+ // Note: Facebook doesn't allow multipart/form-data posting to
+ // canvas pages, so don't try to set it--no file uploads, at
+ // least not this way. It can be done using multiple servers
+ // and iFrames, but it's a pretty hacky process.
+ }
+
+ /**
+ * ID of the form
+ *
+ * @return string ID of the form
+ */
+
+ function id()
+ {
+ return 'form_notice';
+ }
+
+ /**
+ * Class of the form
+ *
+ * @return string class of the form
+ */
+
+ function formClass()
+ {
+ return 'form_notice';
+ }
+
+ /**
+ * Action of the form
+ *
+ * @return string URL of the action
+ */
+
+ function action()
+ {
+ return $this->post_action;
+ }
+
+ /**
+ * Legend of the Form
+ *
+ * @return void
+ */
+ function formLegend()
+ {
+ $this->out->element('legend', null, _('Send a notice'));
+ }
+
+ /**
+ * Data elements
+ *
+ * @return void
+ */
+
+ function formData()
+ {
+ if (Event::handle('StartShowNoticeFormData', array($this))) {
+ $this->out->element('label', array('for' => 'notice_data-text'),
+ sprintf(_('What\'s up, %s?'), $this->user->nickname));
+ // XXX: vary by defined max size
+ $this->out->element('textarea', array('id' => 'notice_data-text',
+ 'cols' => 35,
+ 'rows' => 4,
+ 'name' => 'status_textarea'),
+ ($this->content) ? $this->content : '');
+
+ $contentLimit = Notice::maxContent();
+
+ if ($contentLimit > 0) {
+ $this->out->elementStart('dl', 'form_note');
+ $this->out->element('dt', null, _('Available characters'));
+ $this->out->element('dd', array('id' => 'notice_text-count'),
+ $contentLimit);
+ $this->out->elementEnd('dl');
+ }
+
+ if ($this->action) {
+ $this->out->hidden('notice_return-to', $this->action, 'returnto');
+ }
+ $this->out->hidden('notice_in-reply-to', $this->inreplyto, 'inreplyto');
+
+ Event::handle('StartShowNoticeFormData', array($this));
+ }
+ }
+
+ /**
+ * Action elements
+ *
+ * @return void
+ */
+
+ function formActions()
+ {
+ $this->out->element('input', array('id' => 'notice_action-submit',
+ 'class' => 'submit',
+ 'name' => 'status_submit',
+ 'type' => 'submit',
+ 'value' => _('Send')));
+ }
+}
diff --git a/plugins/Facebook/facebookutil.php b/plugins/Facebook/facebookutil.php
index 2ec6db6b8..ac532e18b 100644
--- a/plugins/Facebook/facebookutil.php
+++ b/plugins/Facebook/facebookutil.php
@@ -138,21 +138,23 @@ function facebookBroadcastNotice($notice)
$code = $e->getCode();
- common_log(LOG_WARNING, 'Facebook returned error code ' .
- $code . ': ' . $e->getMessage());
- common_log(LOG_WARNING,
- 'Unable to update Facebook status for ' .
- "$user->nickname (user id: $user->id)!");
+ $msg = "Facebook returned error code $code: " .
+ $e->getMessage() . ' - ' .
+ "Unable to update Facebook status (notice $notice->id) " .
+ "for $user->nickname (user id: $user->id)!";
- if ($code == 200 || $code == 250) {
+ common_log(LOG_WARNING, $msg);
+ if ($code == 100 || $code == 200 || $code == 250) {
+
+ // 100 The account is 'inactive' (probably - this is not well documented)
// 200 The application does not have permission to operate on the passed in uid parameter.
// 250 Updating status requires the extended permission status_update or publish_stream.
// see: http://wiki.developers.facebook.com/index.php/Users.setStatus#Example_Return_XML
remove_facebook_app($flink);
- } else {
+ } else {
// Try sending again later.