fb.module in Drupal for Facebook 6.2
Same filename and directory in other branches
File
fb.moduleView source
<?php
// hook_fb
define('FB_HOOK', 'fb');
// Paths.
define('FB_PATH_ADMIN', 'admin/build/fb');
define('FB_PATH_ADMIN_ARGS', 3);
// args in path.
define('FB_PATH_ADMIN_APPS', 'admin/build/fb/app');
define('FB_PATH_ADMIN_APPS_ARGS', 4);
// permissions
define('FB_PERM_ADMINISTER', 'administer fb apps');
// Ops for hook_fb.
define('FB_OP_GET_APP', 'get_app');
// Load data from a known app
define('FB_OP_GET_ALL_APPS', 'get_all_apps');
// Load data about all apps
define('FB_OP_CURRENT_APP', 'current_app');
// determine active app in canvas page or facebook connect
define('FB_OP_INITIALIZE', 'init');
//
define('FB_OP_POST_INIT', 'post init');
//
define('FB_OP_EXIT', 'exit');
// End an FB callback
define('FB_OP_GET_FBU', 'get_fbu');
// Query the local user's FB account
define('FB_OP_GET_USER_SESSION', 'get_user_sess');
define('FB_OP_PRE_USER', 'pre_user');
// Before account creation, fb_user.module
define('FB_OP_POST_USER', 'post_user');
// After account creation, fb_user.module
define('FB_OP_APP_IS_AUTHORIZED', 'app_authorized');
// Invoked if user has authorized an app. Triggers creation of user accounts or authmap entries
define('FB_OP_CONNECT_JS_INIT', 'fb_connect_js_init');
// A chance to customize fbConnect javascript
define('FB_OP_CANVAS_FBJS_INIT', 'fb_canvas_js_init');
// A chance to customize FBJS.
define('FB_OP_CANVAS_EXIT', 'fb_op_canvas_exit');
// hook_exit for canvas pages.
// node_access realms (belongs here?)
define('FB_GRANT_REALM_FRIEND', 'fb_friend');
define('FB_GRANT_REALM_GROUP', 'fb_group');
// When initializing Facebook API, which user to log in as:
define('FB_FBU_NO_SESSION', 'fbu_no_session');
// http://wiki.developers.facebook.com/index.php/Category:Sessionless_API
// NOTE: on Connect Pages, using anything other than FB_FBU_CURRENT will cause cookies to be set which cause problems on subsequent pages. So only use something other than FB_FBU_CURRENT if you absolutely must!
define('FB_FBU_CURRENT', 'fbu_current');
// Canvas pages and Connect pages
define('FB_FBU_ANY', 'fbu_any');
// Use current user on canvas page, fall back to infinite session otherwise.
//// Constants for internal use
define('FB_APP_CURRENT', '000_app_current');
// Canvas pages only. 000 makes it appear first in options list
/**
* Implementation of hook_init
*
* Determines whether we are servicing a Facebook App request.
*
* We invoke our hook, first to determine which application is being invoked.
* (Because we support more than one in the same Drupal instance.) Then, we
* notify interested modules in various events.
*
*/
function fb_init() {
// Globals provided for internal use and convenience to third-parties.
global $_fb;
global $_fb_app;
// http://drupal.org/node/329810
if (!function_exists('arg')) {
// Ensure arg function is defined.
drupal_bootstrap(DRUPAL_BOOTSTRAP_PATH);
}
// Perform sanity check, help users who skip the README.
if (!function_exists('fb_settings')) {
// Avoid fatal errors caused by settings not included.
module_load_include('inc', 'fb', 'fb_settings');
if (user_access('access administration pages')) {
drupal_set_message(t('!drupal_for_facebook has been enabled, but not properly installed. Please read the !readme.', array(
'!drupal_for_facebook' => l(t('Drupal for Facebook'), 'http://drupal.org/project/fb'),
// This link should work with clean URLs
// disabled.
'!readme' => '<a href=' . base_path() . drupal_get_path('module', 'fb') . '/README.txt>README.txt</a>',
)), 'error');
}
}
// Ask other modules for app details.
$_fb_app = fb_invoke(FB_OP_CURRENT_APP);
// DEPRECATED global $fb_app has been renamed to $_fb_app.
$GLOBALS['fb_app'] = $_fb_app;
// For compatibility with old third-party modules.
if ($_fb_app) {
// we are in a callback
// For canvas and connect pages, use current user.
$_fb = fb_api_init($_fb_app, FB_FBU_CURRENT);
// DEPRECATED global $fb has been renamed to $_fb.
$GLOBALS['fb'] = $_fb;
// For compatibility with old third-party modul
if ($_fb) {
// Give other modules a chance to initialize, require login, etc...
fb_invoke(FB_OP_INITIALIZE, array(
'fb_app' => $_fb_app,
'fb' => $_fb,
));
// See if the facebook user id is known
if ($fbu = $_fb
->get_loggedin_user()) {
fb_invoke(FB_OP_APP_IS_AUTHORIZED, array(
'fb_app' => $_fb_app,
'fb' => $_fb,
'fbu' => $fbu,
));
}
}
else {
watchdog('fb', "URL indicates a facebook app, but could not initialize Facebook", array(), WATCHDOG_ERROR);
}
}
fb_invoke(FB_OP_POST_INIT, array(
'fb_app' => $_fb_app,
'fb' => $_fb,
));
}
/**
* Include the necessary facebook-platform code and initialize the API object.
*
* @param fbu To log into facebook as a particular user, pass the facebook id.
* This is useful during cron jobs, for example, but rarely if ever needed on
* a canvas page. If no valid session key is known for the user, this call
* will still return a facebook reference.
*
* If FB_FBU_ANY is passed in, we will log in as the canvas page user if
* already logged in. Otherwise we try the infinite session, if configured.
*
* Future calls into the the facebook api could fail for various reasons. For
* one, we may fail to log in as the specified user. This call does not
* actually contact facebook to test the connection, it just sets things up so
* that when the connection is needed, it might work. Even if the connection
* is established, the user may not have sufficient permission to whatever you
* are asking facebook to do.
*
*/
function fb_api_init($fb_app, $fbu = FB_FBU_CURRENT) {
//dpm(func_get_args(), "fb_api_init");
//$trace = debug_backtrace();
//dpm($trace, "fb_api_init call stack");
static $cache = array();
// This helps with uncaught exceptions. However, it should be configurable
// or at least not overwrite previously declared handler.
set_exception_handler('fb_handle_exception');
if (!count($cache) && !class_exists('Facebook')) {
$filename = variable_get('fb_api_file', 'facebook-platform/php/facebook.php');
if (!(include $filename)) {
$message = t('Failed to find the Facebook client libraries at %filename. Read the !readme and follow the instructions carefully.', array(
'!drupal_for_facebook' => l(t('Drupal for Facebook'), 'http://drupal.org/project/fb'),
// This link should work with clean URLs disabled.
'!readme' => '<a href=' . base_path() . '/' . drupal_get_path('module', 'fb') . '/README.txt>README.txt</a>',
'%filename' => $filename,
));
drupal_set_message($message, 'error');
watchdog('fb', $message);
return NULL;
}
}
// This global comes from facebook's client API.
$GLOBAL['facebook_config']['debug'] = variable_get('fb_debug', FALSE);
// set TRUE for debug output from FB API
if (!isset($cache[$fb_app->apikey])) {
$cache[$fb_app->apikey] = array();
}
$fbu_orig = $fbu;
// Avoid E_NOTICE errors and keep code below clean.
if (isset($GLOBALS['_fb'])) {
$global_fb = $GLOBALS['_fb'];
}
else {
$global_fb = (object) array(
'api_key' => NULL,
);
}
// Determine the actual facebook user id to use.
if ($global_fb->api_key == $fb_app->apikey && ($fbu == FB_FBU_CURRENT || $fbu == FB_FBU_ANY || $fbu == $GLOBALS['_fb']
->get_loggedin_user())) {
return $GLOBALS['_fb'];
}
elseif ($global_fb->api_key == $fb_app->apikey && $fbu == FB_FBU_CURRENT) {
// No current user to use, probably anonymous canvas page.
return $GLOBALS['_fb'];
}
elseif (is_numeric($fbu)) {
// FB user id passed in. If we happen to have valid session info for
// them, we can log in as them.
$data = fb_invoke(FB_OP_GET_USER_SESSION, array(
'fb_app' => $fb_app,
'fbu' => $fbu,
), array());
if (count($data) && $data[0] && $data[1]) {
$fbu = $data[0];
$session = $data[1];
}
}
if (!isset($cache[$fb_app->apikey][$fbu])) {
try {
// We don't have a cached resource for this app/user combo, so we're going to create one.
$fb = new Facebook($fb_app->apikey, $fb_app->secret);
// If we learned the session, above, use it
if ($fbu && isset($session)) {
$fb
->set_user($fbu, $session);
}
elseif ($fbu && $fbu == $fb
->get_loggedin_user()) {
// Canvas page or Connect page, current user is logged in already.
// Nothing to do here.
}
elseif ($fbu == FB_FBU_NO_SESSION) {
$fb
->set_user(NULL, NULL);
}
// Cache the result, in case we're called again.
$cache[$fb_app->apikey][$fbu] = $fb;
// Note that facebook api has not actually logged into facebook yet.
// We won't really know if our session is valid until later.
// get_loggedin_user does not really test it.
if ($fbu_orig != FB_FBU_NO_SESSION && $fbu_orig != FB_FBU_CURRENT && !$fb
->get_loggedin_user()) {
// An FBU other than CURRENT was specified, but we failed to log in.
watchdog('fb', 'Failed to log into facebook app %app as user %user', array(
'%app' => $fb_app->title,
'%user' => $fbu_orig,
), WATCHDOG_ERROR);
}
} catch (Exception $e) {
fb_log_exception($e, t('Failed to construct Facebook client API.'));
}
}
$fb = $cache[$fb_app->apikey][$fbu];
return $fb;
}
/**
* Wrapper function for fb_api_init. This helps for functions that should
* work whether or not we are on a canvas page. For canvas pages, the active
* fb object is used. For non-canvas pages, it will initialize the API using
* an infinite session, if configured.
*
* @param $fb_app Note this is ignored on canvas pages.
*
* This is for internal use. Third party modules use fb_api_init().
*/
function _fb_api_init($fb_app = NULL) {
$fb = $GLOBALS['_fb'];
// Default to active app on canvas pages
if (!$fb && $fb_app) {
// Otherwise, log into facebook api.
$fb = fb_api_init($fb_app, FB_FBU_ANY);
}
if (!$fb) {
watchdog('fb', '%function unable to initialize Facebook API.', array(
'%function' => '_fb_api_init()',
), WATCHDOG_ERROR);
return;
}
else {
return $fb;
}
}
/**
* Sometimes calls to fb_api_init succeed, but calls to the client api
* will fail because cookies are obsolete or what have you. This
* function makes a call to facebook to test the session. Expensive,
* so use only when necessary.
*/
function fb_api_check_session($fb) {
// TODO: caching
$success = FALSE;
try {
$is_user = $fb->api_client
->users_isAppUser();
// Does not matter what is returned, as long as exception is not thrown.
$success = TRUE;
} catch (Exception $e) {
$success = FALSE;
}
return $success;
}
/**
* Returns the facebook user id currently visiting a canvas page, or if set_user has been called.
* Unlike fb_get_fbu(), works only on canvas pages or when infinite session has been initialized.
*/
function fb_facebook_user($fb = NULL) {
if (!isset($fb)) {
$fb = $GLOBALS['_fb'];
}
if (!$fb) {
return;
}
$fbu = $fb
->get_loggedin_user();
if (isset($fb->api_client->error_code)) {
if (fb_verbose()) {
watchdog('fb', 'Failed to get Facebook user id. detail: !detail', array(
'!detail' => print_r($_REQUEST, 1),
), WATCHDOG_ERROR);
}
}
return $fbu;
}
/**
* Determine whether current page is FBML canvas page.
*/
function fb_is_fbml_canvas() {
if (function_exists('fb_canvas_is_fbml')) {
// More complex logic if fb_canvas.module enabled.
return fb_canvas_is_fbml();
}
else {
if (isset($GLOBALS['_fb'])) {
return $GLOBALS['_fb']
->in_fb_canvas();
}
}
}
/**
* Determine whether current page is iframe canvas page.
*/
function fb_is_iframe_canvas() {
if (function_exists('fb_canvas_is_iframe')) {
// More complex logic if fb_canvas.module enabled.
return fb_canvas_is_iframe();
}
else {
if (isset($GLOBALS['_fb'])) {
return $GLOBALS['_fb']
->in_frame();
}
}
}
function fb_is_connect() {
// fb_settings.inc sets this global.
if (isset($GLOBALS['_fb_connect_apikey'])) {
return $GLOBALS['_fb_connect_apikey'];
}
elseif (function_exists('fb_connect_get_app')) {
$fb_app = fb_connect_get_app();
if (isset($fb_app)) {
return $fb_app->apikey;
}
}
}
/**
* Helper tells other modules when to load admin hooks.
*/
function fb_is_fb_admin_page() {
if (arg(0) == 'admin' && (arg(1) == 'fb' || arg(2) == 'fb')) {
// Keep consistant titles across tabs served by multiple modules.
if ($label = arg(FB_PATH_ADMIN_APPS_ARGS)) {
drupal_set_title($label);
}
else {
drupal_set_title(t('Drupal for Facebook'));
}
return TRUE;
}
}
/**
* Determine whether we are rendering a profile tab.
*/
function fb_is_profile_tab() {
if (isset($_REQUEST['fb_sig_in_profile_tab'])) {
return $_REQUEST['fb_sig_in_profile_tab'];
}
}
function fb_get_profile_id() {
if (isset($_REQUEST['fb_sig_profile_id'])) {
return $_REQUEST['fb_sig_profile_id'];
}
}
/**
* Facebook provides a method, users_isAppUser(), which is buggy and
* unreliable. So we need to implement our own.
*/
function fb_is_app_user($fb) {
if ($fb->api_client->added || $fb->api_client->is_user) {
return TRUE;
}
else {
return $fb->api_client->users_isAppUser;
}
}
/**
* Given a local user id, find the facebook id.
*/
function fb_get_fbu($uid, $fb_app = NULL) {
// default to current app (only set if we're in a FB callback)
if (!$fb_app) {
$fb_app = $GLOBALS['_fb_app'];
}
// Accept either a user object or uid passed in.
if (is_object($uid) && $uid->uid && isset($uid->fbu) && $uid->fbu) {
return $uid->fbu;
}
elseif (is_object($uid)) {
$uid = $uid->uid;
}
if ($uid) {
// User management is handled by another module. Use our hook to ask for mapping.
$fbu = fb_invoke(FB_OP_GET_FBU, array(
'fb_app' => $fb_app,
'uid' => $uid,
'fb' => $GLOBALS['_fb'],
));
}
return $fbu;
}
/**
* Convenience function to learn the fbu associated with a user, node or comment.
* Used in theming (X)FBML tags.
*/
function fb_get_object_fbu($object) {
static $cache;
if (!isset($cache)) {
$cache = array();
}
if (isset($object->uid) && isset($cache[$object->uid])) {
$fbu = $cache[$object->uid];
return $fbu;
}
elseif (isset($object->fbu)) {
// Explicitly set.
$fbu = $object->fbu;
}
elseif ($pos = strpos($object->name, '@facebook')) {
// Naming convention.
$fbu = substr($object->name, 0, $pos);
}
elseif ($object->uid > 0) {
// Experimental. This can be expensive on pages with many comments or nodes!
//$fbu = fb_get_fbu($object->uid);
}
if (isset($fbu) && is_numeric($fbu)) {
if (isset($object->uid) && $object->uid > 0) {
$cache[$object->uid] = $fbu;
}
return $fbu;
}
}
/**
* Convenience method to get app info based on apikey or nid.
*/
function fb_get_app($search_data) {
// $search_data can be an apikey, or an array of other search params.
if (!is_array($search_data)) {
$search_data = array(
'apikey' => $search_data,
);
}
$fb_app = fb_invoke(FB_OP_GET_APP, $search_data);
return $fb_app;
}
/**
* Convenience method for other modules to attach data to the fb_app
* object.
*
* It is assumed the fb_app implementation will fill in the data
* field. We really should clean up the separation between modules,
* or merge fb_app.module into this one.
*/
function fb_get_app_data(&$fb_app) {
if (!isset($fb_app->fb_app_data)) {
$fb_app->fb_app_data = isset($fb_app->data) ? unserialize($fb_app->data) : array();
}
return $fb_app->fb_app_data;
}
/**
* Will return a human-readable name if the fb_app module supports it, or
* fb_admin_get_app_properties($fb_app) has been called. However we don't
* take the relatively expensive step of calling that ourselves.
*/
function fb_get_app_title($fb_app) {
if (isset($fb_app->title)) {
return $fb_app->title;
}
elseif (isset($fb_app->application_name)) {
return $fb_app->application_name;
}
else {
return $fb_app->label;
}
}
/**
* Convenience method to return array of all know fb_apps.
*/
function fb_get_all_apps() {
$apps = fb_invoke(FB_OP_GET_ALL_APPS, NULL, array());
return $apps;
}
/**
* A convenience method for returning a list of facebook friends.
*
* This should work efficiently in canvas pages for finding friends of
* the current user. In other cases it tries to work, but will be an
* expensive operation and only succeed when the user is logged in via
* Connect, or has created an infinite session.
*
* @return: an array of facebook ids
*/
function fb_get_friends($fbu, $fb_app = NULL) {
static $cache = array();
if (!$fb_app) {
$fb_app = $GLOBALS['_fb_app'];
}
// Facebook only allows us to query the current user's friends, so let's try
// to log in as that user. It will only actually work if they are the
// current user of a canvas page, or they've signed up for an infinite
// session.
$fb = fb_api_init($fb_app, $fbu);
if (!$fb || !$fbu) {
return;
}
if (!isset($cache[$fbu])) {
if ($fb === $GLOBALS['_fb'] && $fbu == fb_facebook_user($fb)) {
$items = $fb->api_client
->friends_get();
}
// friends_get does not work in cron call, so we double check.
if (!$items || !count($items)) {
$logged_in = fb_facebook_user($fb);
$query = "SELECT uid2 FROM friend WHERE uid1={$fbu}";
// FQL, no {curly_brackets}!
$result = $fb->api_client
->fql_query($query);
fb_report_errors($fb);
$items = array();
if (is_array($result)) {
foreach ($result as $data) {
$items[] = $data['uid2'];
}
}
}
// Facebook's API has the annoying habit of returning an item even if user
// has no friends. We need to clean that up.
if (!$items[0]) {
unset($items[0]);
}
$cache[$fbu] = $items;
}
return $cache[$fbu];
}
// Return array of facebook gids
function fb_get_groups($fbu, $fb_app = NULL) {
$items = array();
$groups = fb_get_groups_data($fbu);
if ($groups && count($groups)) {
foreach ($groups as $data) {
$items[] = $data['gid'];
}
}
return $items;
}
function fb_get_groups_data($fbu, $fb_app = NULL) {
static $cache = array();
$fb = _fb_api_init($fb_app);
if (!$fb || !$fbu) {
return;
}
if (!isset($cache[$fbu])) {
$cache[$fbu] = $fb->api_client
->groups_get($fbu, NULL);
}
return $cache[$fbu];
}
// deprecated since creation of fb_user module, but cron hook still uses this.
function fb_user_load($fbu = NULL) {
global $user;
if (!$fbu) {
// default to current logged in user
$fbu = fb_facebook_user();
}
if ($fbu && $user->fbu == $fbu) {
return $user;
}
if ($fbu) {
$account = user_external_load("{$fbu}-{$fb_app->apikey}@facebook.com");
if (!$account) {
$account = user_external_load("{$fbu}@facebook.com");
}
if (!$account) {
$account = user_load(array(
'uid' => variable_get('fb_facebook_user', 2),
));
}
if (!$account) {
watchdog('fb', 'Failed to load user from facebook fbu=%fbu', array(
'%fbu' => $fbu,
), WATCHDOG_ERROR);
}
$account->fbu = $fbu;
return $account;
}
}
function fb_form_alter(&$form, &$form_state, $form_id) {
// Because facebook users don't have email, it can't be required on user form
if ($form_id == 'user_register') {
if (user_access('administer users')) {
$form['mail']['#required'] = FALSE;
}
}
if ($form_id == 'user_edit') {
if (user_access('administer users')) {
$form['account']['mail']['#required'] = FALSE;
}
}
}
//// Menu structure.
/**
* Implementation of hook_menu().
*/
function fb_menu() {
$items = array();
// Admin pages overview.
$items[FB_PATH_ADMIN] = array(
'title' => 'Facebook Applications',
'description' => 'Facebook Applications',
'page callback' => 'fb_admin_page',
'access arguments' => array(
FB_PERM_ADMINISTER,
),
'file' => 'fb.admin.inc',
'type' => MENU_NORMAL_ITEM,
);
$items[FB_PATH_ADMIN . '/list'] = array(
'title' => 'List',
'weight' => -2,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
// Admin pages for each app.
$items[FB_PATH_ADMIN_APPS . '/%fb'] = array(
'title' => 'Application Detail',
'description' => 'Facebook Applications',
'page callback' => 'fb_admin_app_page',
'page arguments' => array(
FB_PATH_ADMIN_APPS_ARGS,
),
'access arguments' => array(
FB_PERM_ADMINISTER,
),
'file' => 'fb.admin.inc',
'type' => MENU_CALLBACK,
);
$items[FB_PATH_ADMIN_APPS . '/%fb/fb'] = array(
'title' => 'View',
'weight' => -2,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
// When forms are submitted directly to us, we cache the results,
// and show them later via this callback
$items['fb/form_cache'] = array(
'page callback' => '_fb_form_cache_cb',
'type' => MENU_CALLBACK,
'access callback' => TRUE,
);
return $items;
}
/**
* Implementation of a %wildcard_load(). http://drupal.org/node/224170
*/
function fb_load($id) {
$query = array(
'label' => $id,
);
if (fb_is_fb_admin_page()) {
// Show disabled apps to admins.
$query['status'] = 0;
// status >= 0
}
$fb_app = fb_get_app($query);
return $fb_app;
}
/**
* Implementation of hook_perm().
*/
function fb_perm() {
return array(
FB_PERM_ADMINISTER,
);
}
/**
* Implements hook_exit().
*
* When completing a canvas page we need special processing for the session. See fb_session.inc.
*
* Also invoke hook_fb(FB_OP_EXIT), so that other modules can handle special
* cases (in particular form support in b_canvas.module.
*/
function fb_exit($destination = NULL) {
global $_fb_app, $_fb;
if ($_fb_app && $_fb) {
// Session management
if (function_exists('fb_session_exit')) {
fb_session_exit();
}
// Invoke other modules.
fb_invoke(FB_OP_EXIT, array(
'fb_app' => $_fb_app,
'fb' => $GLOBALS['_fb'],
), $destination);
}
}
function _fb_form_cache_cb($cid) {
// Facebook started appending a '?', we need to get rid of it.
if ($pos = strpos($cid, '?')) {
$cid = substr($cid, 0, $pos);
}
if (fb_verbose() == 'extreme') {
watchdog('fb', "Returning cached form page {$cid}");
// debug
}
$cache = cache_get($cid, 'cache_page');
// Don't clear, as user may refresh browser. Cache will expire eventually.
// cache_clear_all($cid, 'cache_page');
print $cache->data;
exit;
}
function fb_session_key_form() {
global $_fb_app;
$form = array(
'auth_token' => array(
'#type' => 'textfield',
'#title' => t('One-time code'),
'#description' => t('If you do not have a one-time code, you can get one !here.', array(
'!here' => l(t('here'), 'http://www.facebook.com/code_gen.php?v=1.0&api_key=' . $_fb_app->apikey),
)),
),
'submit' => array(
'#type' => 'submit',
'#value' => t('Submit'),
),
'#redirect' => FALSE,
);
return $form;
}
/**
* Invoke hook_fb.
*/
function fb_invoke($op, $data = NULL, $return = NULL, $hook = FB_HOOK) {
foreach (module_implements($hook) as $name) {
$function = $name . '_' . $hook;
try {
$function($op, $data, $return);
} catch (Exception $e) {
fb_log_exception($e, t('Exception calling %function(%op)', array(
'%function' => $function,
'%op' => $op,
)));
}
}
return $return;
}
/**
* This method will clean up URLs. When serving canvas pages, extra
* information is included in URLs (see fb_url_rewrite.inc). This will remove
* the extra information.
*/
function fb_scrub_urls($content) {
if (function_exists('_fb_settings_url_rewrite_prefixes')) {
foreach (_fb_settings_url_rewrite_prefixes() as $key) {
$patterns[] = "|{$key}/[^/]*/|";
$replacements[] = "";
}
$content = preg_replace($patterns, $replacements, $content);
}
return $content;
}
/**
* Convenience method for displaying facebook api errors.
*/
function fb_report_errors($fb = FB_APP_CURRENT, $message = NULL) {
if ($fb == FB_APP_CURRENT) {
$fb = $GLOBALS['_fb'];
}
if ($fb) {
if (isset($fb->api_client->error_code)) {
$message = t('!message Facebook API error %code (see !link).', array(
'%code' => $fb->api_client->error_code,
'!link' => l(t('error codes'), "http://wiki.developers.facebook.com/index.php/Error_codes"),
'!message' => $message,
));
watchdog('fb', $message, array(), WATCHDOG_ERROR);
if (user_access(FB_PERM_ADMINISTER)) {
drupal_set_message($message, 'error');
}
}
}
}
function fb_log_exception($e, $text = '', $fb = NULL) {
if ($text) {
$message = $text . ': ' . $e
->getMessage();
}
else {
$message = $e
->getMessage();
}
$message .= ' ' . $e
->getCode();
if ($fb) {
$message .= '. (' . t('logged into facebook as %fbu', array(
'%fbu' => $fb
->get_loggedin_user(),
)) . ')';
}
if (fb_verbose()) {
$message .= '<pre>' . $e . '</pre>';
}
watchdog('fb', $message, array(), WATCHDOG_ERROR);
if (user_access(FB_PERM_ADMINISTER)) {
drupal_set_message($message, 'error');
}
}
/**
* Exception handler for PHP5 exceptions.
*/
function fb_handle_exception($exception) {
$message = t('Facebook API exception %message. !trace', array(
'%message' => $exception
->getMessage(),
'!trace' => '<pre>' . $exception
->getTraceAsString() . '</pre>',
));
watchdog('fb', $message, array(), WATCHDOG_ERROR);
//drupal_set_message($message, 'error');
print $message;
print "<pre>\$_REQUEST:\n";
print_r($_REQUEST);
print "\n\nREQUEST_URI:\n" . request_uri();
print "</pre>";
}
/**
* Helper function for facebook's users_getInfo API.
*
* This function makes calls to users_getInfo more efficient, by caching
* results in the session, so calls do not always require hitting Facebook's
* servers.
*
* @param $oids
* Array of facebook object IDs. In this case they should each be a user id.
*/
function fb_users_getInfo($oids, $fb = NULL, $refresh_cache = FALSE) {
if (!$fb) {
$fb = $GLOBALS['_fb'];
}
$infos = array();
if (!is_array($oids)) {
$oids = array();
}
if ($fb) {
// First try cache
if (!$refresh_cache) {
foreach ($oids as $oid) {
if ($info = $_SESSION['fb'][$fb->api_key]['userinfo'][$oid]) {
$infos[] = $info;
}
}
}
if (count($infos) != count($oids)) {
// Session cache did not include all users, update the cache.
$infos = $fb->api_client
->users_getInfo($oids, array(
'about_me',
'affiliations',
'name',
'is_app_user',
'pic',
'pic_big',
'pic_square',
'profile_update_time',
'proxied_email',
'status',
'email_hashes',
'email',
));
// Update cache with recent results.
if (is_array($infos)) {
foreach ($infos as $info) {
$_SESSION['fb'][$fb->api_key]['userinfo'][$info['uid']] = $info;
}
}
}
return $infos;
}
}
/**
* Helper function for FBJS files.
*
* Useful for adding Facebook Javascript, which will be incorporated into
* canvas pages or profile boxes. When included this way, javascript must be
* embedded inline, rather than refer to an external URL. So this function
* will actually read a local file and include the contents inline.
*/
function fb_add_js($filename, $type) {
static $cache;
if (!$cache) {
$cache = array();
// Add the most basic file we need.
$base_file = drupal_get_path('module', 'fb') . '/fb_fbml.js';
$base_file .= "?v=" . filemtime($base_file);
drupal_add_js($base_file, 'module', 'fbml');
// Add some settings that FBJS code will often need.
$baseUrl = url('', array(
'absolute' => TRUE,
));
drupal_add_js(array(
'fbjs' => array(
'baseUrlFb' => $baseUrl,
'baseUrl' => fb_scrub_urls($baseUrl),
),
), 'setting', 'fbml');
}
if (!$cache[$filename]) {
if (file_exists($filename)) {
// Refresh facebook's cache when file changes
$filename .= "?v=" . filemtime($filename);
}
// 'post_settings' is a hack to make our code come after settings. This is
// ugly, but we're doing it because there is no "onready" in FBJS.
drupal_add_js($filename, 'post_settings', 'fbml');
$cache[$filename] = TRUE;
}
}
/**
* For debugging, add $conf['fb_verbose'] = TRUE; to settings.php.
*/
function fb_verbose() {
return variable_get('fb_verbose', NULL);
}
/**
* This function will be replaced, hopefully, by format_username in D7.
*
* See http://drupal.org/node/192056
*/
function fb_format_username($account) {
$name = !empty($account->name) ? $account->name : variable_get('anonymous', t('Anonymous'));
drupal_alter('username', $name, $account);
return $name;
}
/**
* hook_username_alter().
*
* Return a user's facebook name, instead of local username.
*/
function fb_username_alter(&$name, $account) {
//dpm(func_get_args(), "fb_username_alter($name)");
if (isset($account->fbu) && $name == $account->fbu . '@facebook') {
$info = fb_users_getInfo(array(
$account->fbu,
));
if (is_array($info) && is_array($info[0])) {
if ($info[0]['name']) {
$name = $info[0]['name'];
}
}
}
}
Functions
Name | Description |
---|---|
fb_add_js | Helper function for FBJS files. |
fb_api_check_session | Sometimes calls to fb_api_init succeed, but calls to the client api will fail because cookies are obsolete or what have you. This function makes a call to facebook to test the session. Expensive, so use only when necessary. |
fb_api_init | Include the necessary facebook-platform code and initialize the API object. |
fb_exit | Implements hook_exit(). |
fb_facebook_user | Returns the facebook user id currently visiting a canvas page, or if set_user has been called. Unlike fb_get_fbu(), works only on canvas pages or when infinite session has been initialized. |
fb_format_username | This function will be replaced, hopefully, by format_username in D7. |
fb_form_alter | |
fb_get_all_apps | Convenience method to return array of all know fb_apps. |
fb_get_app | Convenience method to get app info based on apikey or nid. |
fb_get_app_data | Convenience method for other modules to attach data to the fb_app object. |
fb_get_app_title | Will return a human-readable name if the fb_app module supports it, or fb_admin_get_app_properties($fb_app) has been called. However we don't take the relatively expensive step of calling that ourselves. |
fb_get_fbu | Given a local user id, find the facebook id. |
fb_get_friends | A convenience method for returning a list of facebook friends. |
fb_get_groups | |
fb_get_groups_data | |
fb_get_object_fbu | Convenience function to learn the fbu associated with a user, node or comment. Used in theming (X)FBML tags. |
fb_get_profile_id | |
fb_handle_exception | Exception handler for PHP5 exceptions. |
fb_init | Implementation of hook_init |
fb_invoke | Invoke hook_fb. |
fb_is_app_user | Facebook provides a method, users_isAppUser(), which is buggy and unreliable. So we need to implement our own. |
fb_is_connect | |
fb_is_fbml_canvas | Determine whether current page is FBML canvas page. |
fb_is_fb_admin_page | Helper tells other modules when to load admin hooks. |
fb_is_iframe_canvas | Determine whether current page is iframe canvas page. |
fb_is_profile_tab | Determine whether we are rendering a profile tab. |
fb_load | Implementation of a %wildcard_load(). http://drupal.org/node/224170 |
fb_log_exception | |
fb_menu | Implementation of hook_menu(). |
fb_perm | Implementation of hook_perm(). |
fb_report_errors | Convenience method for displaying facebook api errors. |
fb_scrub_urls | This method will clean up URLs. When serving canvas pages, extra information is included in URLs (see fb_url_rewrite.inc). This will remove the extra information. |
fb_session_key_form | |
fb_username_alter | hook_username_alter(). |
fb_users_getInfo | Helper function for facebook's users_getInfo API. |
fb_user_load | |
fb_verbose | For debugging, add $conf['fb_verbose'] = TRUE; to settings.php. |
_fb_api_init | Wrapper function for fb_api_init. This helps for functions that should work whether or not we are on a canvas page. For canvas pages, the active fb object is used. For non-canvas pages, it will initialize the API using an infinite session, if… |
_fb_form_cache_cb |