View source
<?php
define('FB_PERM_ADMINISTER', 'fb__administer');
define('FB_PERM_ADMINISTER_TOKEN', 'fb__administer_token');
define('FB_VAR_ADD_JS', 'fb__add_js');
define('FB_VAR_DEFAULT_APP', 'fb__default_app');
define('FB_VAR_ADMIN_ACCESS_TOKEN', 'fb__access_token');
define('FB_VAR_PREFER_LONG_TOKEN', 'fb__prefer_long_token');
define('FB_VAR_USE_CACHE', 'fb__use_cache');
define('FB_VAR_ALTER_USERNAME', 'fb__format_username');
define('FB_VAR_USE_JSON_BIGINT', 'fb__json_bigint');
define('FB_ALTER_USERNAME_ALWAYS', 'always');
define('FB_ALTER_USERNAME_NEVER', 'never');
define('FB_STATUS_FLAG_VALID', 1);
define('FB_STATUS_FLAG_APP', 1 << 1);
define('FB_STATUS_FLAG_ADMIN', 1 << 2);
define('FB_STATUS_FLAG_OFFLINE', 1 << 3);
define('FB_TOKEN_NONE', 0);
define('FB_STATUS_APP_ENABLED', 1);
define('FB_STATUS_APP_LOCAL', 1 << 1);
define('FB_STATUS_APP_REMOTE', 1 << 2);
define('FB_CACHE_NONE', 0);
define('FB_CACHE_QUERY', 1);
define('FB_CACHE_STORE', 1 << 1);
define('FB_CACHE_QUERY_AND_STORE', FB_CACHE_QUERY | FB_CACHE_STORE);
define('FB_PATH_ADMIN_CONFIG', 'admin/config/fb');
define('FB_PATH_ADMIN_ARGS', 3);
define('FB_PATH_ADMIN_APPS', FB_PATH_ADMIN_CONFIG . '/application');
define('FB_PATH_ADMIN_APPS_ARGS', FB_PATH_ADMIN_ARGS + 1);
define('FB_PATH_AJAX_EVENT', 'fb/ajax');
define('FB_PATH_AJAX_EVENT_ARGS', 2);
define('FB_OP_TOKEN_USER', 'fb_token_user');
define('FB_OP_AJAX', 'fb_ajax');
define('FB_OP_TOKEN_INVALID', 'fb_token_invalid');
define('FB_OP_POST_INIT', 'fb_post_init');
function fb_init() {
$fb_app = fb_get_app();
if ($fb_app) {
$fba = $fb_app['client_id'];
$access_token = fb_user_token($fb_app);
}
else {
$fba = 0;
$access_token = null;
}
drupal_add_js(array(
'fb' => array(
'client_id' => $fba,
'ajax_event_url' => url(FB_PATH_AJAX_EVENT, array(
'absolute' => TRUE,
)),
'fb_reloading' => !empty($_REQUEST['fb_reloading']),
'status' => $access_token ? 'connected' : 'unknown',
),
), 'setting');
drupal_add_library('system', 'jquery.cookie');
if ($fb_app) {
drupal_add_js(array(
'fb_app_' . $fba => _fb_js_settings($fb_app),
), 'setting');
}
if (variable_get(FB_VAR_ADD_JS, FALSE)) {
fb_require_js();
}
fb_invoke(FB_OP_POST_INIT, array(
'fb_app' => $fb_app,
));
}
function fb_require_js() {
drupal_add_js(drupal_get_path('module', 'fb') . '/fb_sdk.js', array(
'type' => 'file',
'scope' => 'header',
'group' => JS_LIBRARY,
));
}
function _fb_js_settings($fb_app) {
$access_token = fb_user_token($fb_app);
$settings = array(
'namespace' => $fb_app['namespace'],
'name' => $fb_app['name'],
'client_id' => $fb_app['client_id'],
'access_token' => $access_token,
);
$settings['scope'] = array();
$settings['client_auth_url'] = fb_client_auth_url($fb_app);
return $settings;
}
function _fb_oauth_state() {
return 'fb_' . session_name();
}
function fb_permission() {
return array(
FB_PERM_ADMINISTER => array(
'title' => t('Administer Facebook integration'),
'description' => t('Control how this site interacts with Facebook.com'),
'restrict access' => TRUE,
),
FB_PERM_ADMINISTER_TOKEN => array(
'title' => t('Administer Facebook tokens and secrets'),
'description' => t('View and edit sensitive Facebook user information.'),
'restrict access' => TRUE,
),
);
}
function fb_menu() {
$items = array();
$admin_item = array(
'access arguments' => array(
FB_PERM_ADMINISTER,
),
'type' => MENU_NORMAL_ITEM,
'file' => 'fb.admin.inc',
'file path' => drupal_get_path('module', 'fb'),
);
$items[FB_PATH_ADMIN_CONFIG] = array(
'title' => 'Facebook',
'description' => 'Connectivity to facebook.com.',
'page callback' => 'system_admin_menu_block_page',
'access arguments' => array(
'access administration pages',
),
'file' => 'system.admin.inc',
'file path' => drupal_get_path('module', 'system'),
);
$items[FB_PATH_ADMIN_CONFIG . '/settings'] = array(
'title' => 'Settings',
'weight' => -20,
'description' => 'Control how this site interacts with Facebook.com',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fb_admin_settings_form',
),
) + $admin_item;
$items[FB_PATH_ADMIN_CONFIG . '/settings/default'] = array(
'title' => 'Facebook Settings',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -20,
) + $admin_item;
$items[FB_PATH_ADMIN_CONFIG . '/settings/app'] = array(
'title' => 'Application',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fb_admin_default_app_form',
),
'type' => MENU_LOCAL_TASK,
) + $admin_item;
$items[FB_PATH_ADMIN_CONFIG . '/settings/token'] = array(
'title' => 'Token',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fb_admin_default_token_form',
),
'type' => MENU_LOCAL_TASK,
) + $admin_item;
$items[FB_PATH_ADMIN_CONFIG . '/token'] = array(
'title' => 'Access Tokens',
'weight' => 20,
'description' => 'Manage Facebook access tokens',
'page callback' => 'fb_admin_token_page',
'access arguments' => array(
FB_PERM_ADMINISTER_TOKEN,
),
) + $admin_item;
$items[FB_PATH_ADMIN_CONFIG . '/token_replace'] = array(
'title' => 'Replace Token',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fb_admin_token_replace_form',
),
'type' => MENU_CALLBACK,
) + $admin_item;
$items[FB_PATH_ADMIN_APPS] = array(
'title' => 'Applications',
'description' => 'Manage Facebook Apps.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fb_admin_applications_form',
),
) + $admin_item;
$items[FB_PATH_ADMIN_APPS . '/default'] = array(
'title' => 'Applications',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -20,
) + $admin_item;
$items[FB_PATH_ADMIN_APPS . '/add'] = array(
'title' => 'Add Application',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fb_admin_application_edit_form',
),
'type' => MENU_LOCAL_TASK,
'weight' => 20,
) + $admin_item;
$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/view'] = array(
'title' => 'View',
'weight' => -2,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items[FB_PATH_ADMIN_APPS . '/%fb/edit'] = array(
'title' => 'Edit',
'description' => 'Edit Facebook Application',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fb_admin_application_edit_form',
FB_PATH_ADMIN_APPS_ARGS,
),
'access arguments' => array(
FB_PERM_ADMINISTER,
),
'file' => 'fb.admin.inc',
'weight' => -1,
'type' => MENU_LOCAL_TASK,
);
$items[FB_PATH_ADMIN_APPS . '/%fb/delete'] = array(
'title' => 'Delete',
'description' => 'Delete Facebook Application',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fb_admin_application_delete_form',
FB_PATH_ADMIN_APPS_ARGS,
),
'access arguments' => array(
FB_PERM_ADMINISTER,
),
'file' => 'fb.admin.inc',
'weight' => -1,
'type' => MENU_NORMAL_ITEM,
);
$items['fb/token'] = array(
'title' => 'Fb Token',
'page callback' => 'fb_page_token',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items[FB_PATH_AJAX_EVENT . '/%'] = array(
'page callback' => 'fb_ajax_event',
'type' => MENU_CALLBACK,
'access callback' => TRUE,
'page arguments' => array(
FB_PATH_AJAX_EVENT_ARGS,
),
);
return $items;
}
function fb_load($id, $params = array()) {
if (!$id) {
return array();
}
$cache =& drupal_static(__FUNCTION__);
$token =& drupal_static('fb_load_token');
if (!isset($cache)) {
$cache = array();
}
if (!isset($cache[$id])) {
try {
drupal_alter('fb_load', $token, $params, $id);
$cache[$id] = fb_graph($id, $params + array(
'access_token' => $token,
));
} catch (exception $e) {
fb_log_exception($e, t('Failed to query facebook for url argument %id', array(
'%id' => $id,
)));
$cache[$id] = array(
'id' => $id,
);
}
}
return $cache[$id];
}
function fb_application_load($app_id) {
foreach (array(
'namespace',
'fba',
) as $id_field) {
$fb_app = db_select('fb_application', 'fba')
->fields('fba')
->condition($id_field, $app_id, '=')
->execute()
->fetchAssoc();
if (!empty($fb_app)) {
break;
}
}
$fb_app['client_id'] = $fb_app['fba'];
if (!isset($fb_app['name'])) {
$fb_app['name'] = $fb_app['title'];
}
if (!empty($fb_app['sdata']) && empty($fb_app['data'])) {
$fb_app['data'] = unserialize($fb_app['sdata']);
}
return $fb_app;
}
function fb_token_load($fbu, $fba = NULL) {
if (!$fba) {
$fb_app = fb_get_app();
$fba = $fb_app['client_id'];
}
$result = db_query("SELECT * FROM {fb_token} WHERE fbu=:fbu AND fba=:fba", array(
':fbu' => $fbu,
':fba' => $fba,
));
$fb_token = $result
->fetchAssoc();
return $fb_token;
}
function fb_debug_token($token, $fb_app = array()) {
if (empty($token)) {
return;
}
if (empty($fb_app)) {
$data = fb_graph('app', $token);
$fb_app = fb_application_load($data['id']);
}
$app_token = fb_token_load($fb_app['client_id']);
$graph = fb_graph('debug_token', array(
'input_token' => $token,
'access_token' => $app_token['access_token'],
));
return $graph['data'];
}
function fb_username_alter(&$name, $account) {
$enabled = variable_get(FB_VAR_ALTER_USERNAME, FB_ALTER_USERNAME_ALWAYS);
if ($enabled == FB_ALTER_USERNAME_NEVER) {
return;
}
if (arg(0) == 'admin') {
return;
}
$names_cache =& drupal_static(__FUNCTION__);
if (isset($names_cache[$account->uid])) {
if (!empty($names_cache[$account->uid])) {
$name = $names_cache[$account->uid];
}
return;
}
if ($pos = strpos($name, '@facebook')) {
if ($fbu = substr($name, 0, $pos)) {
$cache_key = 'fb_username_' . $fbu;
$cache = cache_get($cache_key);
if ($cache && $cache->data) {
$names_cache[$account->uid] = $cache->data;
}
else {
try {
$data = fb_graph($fbu);
$names_cache[$account->uid] = $data['name'];
if ($names_cache[$account->uid]) {
}
} catch (Exception $e) {
fb_log_exception($e, t('Failed to alter username for facebook user %fbu', array(
'%fbu' => $fbu,
)));
$names_cache[$account->uid] = FALSE;
}
}
if (!empty($names_cache[$account->uid])) {
$name = $names_cache[$account->uid];
}
}
}
else {
$names_cache[$account->uid] = FALSE;
}
}
function fb_theme() {
return array(
'fb_markup' => array(
'arguments' => array(
'not_connected_markup' => NULL,
'connected_markup' => '<fb:profile-pic linked=false uid=loggedinuser></fb:profile-pic>',
'options' => NULL,
),
'file' => 'fb.theme.inc',
),
'fb_login_button' => array(
'arguments' => array(
'text' => 'Connect with Facebook',
'onclick' => NULL,
'scope' => NULL,
'options' => NULL,
),
'file' => 'fb.theme.inc',
),
);
}
function fb_preprocess_username(&$variables) {
if ($pos = strpos($variables['name'], '@facebook')) {
$fbu = substr($variables['name'], 0, $pos);
if ($fbu) {
$variables['link_options']['#attributes']['data-fbu'] = $fbu;
$variables['attributes_array']['data-fbu'] = $fbu;
}
}
}
function fb_preprocess_user_picture(&$variables) {
if ((empty($variables['user_picture']) || empty($variables['user']->picture)) && !empty($variables['account']->name) && ($pos = strpos($variables['account']->name, '@facebook'))) {
$fbu = substr($variables['account']->name, 0, $pos);
if ($fbu) {
$variables['user_picture'] = theme('image', array(
'path' => '//graph.facebook.com/' . $fbu . '/picture',
));
}
}
}
function fb_element_info() {
return array(
'fb_friend_select' => array(
'#input' => TRUE,
'#process' => array(
'fb_friend_select_process',
),
'#element_validate' => array(
'fb_friend_select_validate',
),
'#theme_wrappers' => array(
'form_element',
),
'#base_type' => 'textfield',
),
'fb_admin_token_generate' => array(
'#input' => TRUE,
'#process' => array(
'fb_admin_token_generate_process',
),
'#element_validate' => array(
'fb_admin_token_generate_validate',
),
'#theme_wrappers' => array(
'form_element',
),
'#base_type' => 'fieldset',
),
'fb_admin_token_select' => array(
'#input' => TRUE,
'#process' => array(
'fb_admin_token_select_process',
),
'#element_validate' => array(
'fb_admin_token_select_validate',
),
'#theme_wrappers' => array(
'form_element',
),
'#base_type' => 'fieldset',
),
);
}
function fb_friend_select_process(&$element) {
$element += array(
'#fb_login_button' => array(
'text' => t('Connect to Facebook'),
),
'#noscript' => t('Enable javascript to select your friends.'),
);
$fb_app = fb_get_app();
if (!$fb_app) {
if (user_access('access administration pages')) {
drupal_set_message(t('No Facebook Application configured. The friend selector needs a <a href="!url">default application</a>.', array(
'!url' => url(FB_PATH_ADMIN_CONFIG . '/settings/app'),
)), 'error');
}
drupal_not_found();
drupal_exit();
}
if ($element['#noscript']) {
$element['noscript'] = array(
'#type' => 'markup',
'#markup' => $element['#noscript'],
'#prefix' => '<noscript>',
'#suffix' => '</noscript>',
);
}
$element['connect'] = array(
'#type' => 'markup',
'#markup' => theme('fb_login_button', $element['#fb_login_button']),
'#prefix' => '<div class="fb_not_connected">',
'#suffix' => '</div>',
);
drupal_add_library('system', 'ui.autocomplete');
drupal_add_js(drupal_get_path('module', 'fb') . '/fb_friend_select.js', array(
'type' => 'file',
'scope' => 'header',
'group' => JS_LIBRARY,
));
$element['fb_names'] = array(
'#type' => 'textfield',
'#attributes' => array(
'class' => array(
'fb_friend_select_names',
'fb_connected',
),
),
'#required' => $element['#required'],
);
$element['#required'] = FALSE;
$element['fb_uids'] = array(
'#type' => 'hidden',
'#attributes' => array(
'class' => array(
'fb_friend_select_uids',
),
),
);
return $element;
}
function fb_element_validate_friend(&$element, &$form_state, $form) {
if ($element['#value']) {
$split = preg_split('/[\\(\\)]/', $element['#value']);
$name = trim($split[0]);
$username = trim($split[1]);
if (!$username) {
form_error($element, t('Could not parse friend name %name.', array(
'%name' => $name,
)));
return;
}
$result = fb_graph_batch(array(
$username,
'me/friends/' . $username,
));
$friend_data = $result['me/friends/' . $username]['data'];
if (count($friend_data)) {
form_set_value($element, array(
$result[$username],
), $form_state);
}
else {
form_error($element, t('Could not confirm friendship with %name.', array(
'%name' => $name,
)));
}
}
else {
}
}
function fb_verbose() {
return variable_get('fb_verbose', NULL);
}
function fb_get_app($variable = NULL) {
if ($variable) {
$app = variable_get($variable, array());
}
else {
$app = variable_get(FB_VAR_DEFAULT_APP, array());
}
drupal_alter('fb_app', $app, $variable);
if (empty($app)) {
return FALSE;
}
$app += array(
'fba' => NULL,
'client_id' => NULL,
'namespace' => NULL,
'name' => NULL,
);
if (!empty($app['client_id'])) {
$app['fba'] = $app['client_id'];
}
if (empty($app['client_id'])) {
$app['client_id'] = $app['fba'];
}
if (!is_array($app)) {
return array();
}
return $app;
}
function fb_app_defaults() {
return array(
'client_id' => '138744759520314',
'base_url' => 'http://apps.facebook.com/the-fridge',
'name' => 'Default App',
);
}
function fb_app_devel_defaults() {
return array(
'client_id' => '102712003139606',
'base_url' => 'http://apps.facebook.com/the-fridge-beta',
'name' => 'Default App (Devel)',
);
}
function fb_access_token() {
static $token;
if (!isset($token)) {
$token = fb_user_token();
if (!$token) {
$token = fb_get_admin_token();
}
}
return $token;
}
function fb_get_admin_token($variable = FB_VAR_ADMIN_ACCESS_TOKEN) {
$token = variable_get($variable, NULL);
if ($token === NULL) {
$token = variable_get(FB_VAR_ADMIN_ACCESS_TOKEN, NULL);
}
return $token;
}
function fb_token_invalid($token) {
db_query("UPDATE {fb_token} SET status = status &~ :valid_flag WHERE access_token=:token", array(
':valid_flag' => FB_STATUS_FLAG_VALID,
':token' => $token,
));
if (!empty($_SESSION['fb']) && !empty($_SESSION['fb'][$token])) {
unset($_SESSION['fb'][$token]);
}
if (!empty($_SESSION['fb'])) {
foreach ($_SESSION['fb'] as $fba => $app) {
if (!empty($app['access_token']) && $app['access_token'] == $token) {
unset($_SESSION['fb'][$fba]);
}
}
}
if (empty($_SESSION['fb'])) {
unset($_SESSION['fb']);
}
drupal_add_js(array(
'fb' => array(
'token_invalid' => $token,
),
), 'setting');
fb_invoke(FB_OP_TOKEN_INVALID, array(
'invalid_token' => $token,
));
}
function fb_token_save($token, $params = array()) {
$params = $params + array(
'status' => FB_STATUS_FLAG_VALID,
'access_token' => $token,
'changed' => REQUEST_TIME,
'data' => NULL,
);
if (empty($params['fbu']) || empty($params['fba'])) {
if (empty($params['graph'])) {
$params['graph'] = fb_graph_batch(array(
'me',
'app',
), $params['access_token'], FB_CACHE_STORE);
}
$params['fbu'] = $params['graph']['me']['id'];
$params['fba'] = $params['graph']['app']['id'];
}
$result = db_merge('fb_token')
->key(array(
'fba' => $params['fba'],
'fbu' => $params['fbu'],
))
->fields(array(
'access_token' => $params['access_token'],
'status' => $params['status'],
'changed' => $params['changed'],
'data' => $params['data'] ? serialize($params['data']) : NULL,
))
->execute();
if ($result) {
return $params;
}
}
function fb_user_token($app = NULL, $token = NULL) {
static $cache = NULL;
if (!$app) {
$app = fb_get_app();
}
if (is_array($app) && !empty($app['client_id'])) {
$client_id = $app['client_id'];
}
else {
$client_id = $app;
}
if (!$client_id) {
return FB_TOKEN_NONE;
}
if ($token) {
if ($token == 'null') {
$token = FB_TOKEN_NONE;
}
$cache[$client_id] = $token;
if (empty($_SESSION['fb'][$client_id]) || $_SESSION['fb'][$client_id]['access_token'] != $token) {
fb_invoke(FB_OP_TOKEN_USER, array(
'client_id' => $client_id,
'access_token' => $token,
));
}
$_SESSION['fb'][$client_id]['access_token'] = $token;
}
if ($token === NULL && isset($_REQUEST['access_token'])) {
return fb_user_token($client_id, $_REQUEST['access_token']);
}
elseif ($token === NULL && isset($_REQUEST['code']) && ($new_token = fb_auth_get_token($app))) {
return fb_user_token($client_id, $new_token);
}
elseif ($token === NULL && !empty($_REQUEST['signed_request'])) {
try {
$sr = fb_parse_signed_request($_REQUEST['signed_request'], is_array($app) && !empty($app['secret']) ? $app['secret'] : NULL);
if (!empty($sr['oauth_token'])) {
return fb_user_token($client_id, $sr['oauth_token']);
}
} catch (Exception $e) {
fb_log_exception($e, t('Failed to parse or validate signed_request.'));
}
}
elseif (!empty($cache) && !empty($cache[$client_id])) {
if ($cache[$client_id] == 'null') {
$cache[$client_id] = FB_TOKEN_NONE;
}
return $cache[$client_id];
}
elseif ($token === NULL && !empty($_SESSION['fb']) && !empty($_SESSION['fb'][$client_id]) && !empty($_SESSION['fb'][$client_id]['access_token'])) {
return fb_user_token($client_id, $_SESSION['fb'][$client_id]['access_token']);
}
return FB_TOKEN_NONE;
}
function fb_server_auth_url($options = array()) {
if (empty($options['fba'])) {
$options = fb_get_app();
}
$options += array(
'redirect_uri' => fb_auth_redirect_uri(current_path(), array(
'query' => array(
'client_id' => $options['fba'],
),
)),
'scope' => '',
);
$url = url('https://www.facebook.com/dialog/oauth', array(
'query' => array(
'client_id' => $options['fba'],
'redirect_uri' => $options['redirect_uri'],
'scope' => $options['scope'],
'state' => _fb_oauth_state($options['fba']),
),
));
return $url;
}
function fb_client_auth_url($options = array()) {
if (!empty($options['client_id'])) {
$options['fba'] = $options['client_id'];
}
if (empty($options['fba'])) {
$options = fb_get_app();
}
if (empty($options['fba'])) {
return NULL;
}
$options += array(
'redirect_uri' => fb_auth_redirect_uri(current_path(), array(
'query' => array(
'client_id' => $options['fba'],
),
)),
'scope' => '',
);
$query = array(
'client_id' => $options['fba'],
'redirect_uri' => $options['redirect_uri'],
'response_type' => 'token',
);
if (is_array($options['scope'])) {
$options['scope'] = implode(',', $options['scope']);
}
if (!empty($options['scope'])) {
$query['scope'] = $options['scope'];
}
$url = url('https://www.facebook.com/dialog/oauth', array(
'query' => $query,
));
return $url;
}
function fb_remote_auth_url($options) {
$url = NULL;
if (empty($options['fba'])) {
$options = fb_get_app();
}
$options += array(
'remote_uri' => fb_auth_redirect_uri(current_path(), array(
'query' => array(
'client_id' => $options['fba'],
),
)),
'scope' => '',
);
if (!empty($options['namespace'])) {
$url = 'https://apps.facebook.com/' . $options['namespace'] . '/fb_remote/auth/' . urlencode(urlencode('scope=' . $options['scope'])) . '/' . urlencode(urlencode('site_name=' . variable_get('site_name', url('<front>', array(
'absolute' => TRUE,
))))) . '/' . urlencode(urlencode('remote_uri=' . $options['remote_uri']));
$url = url('https://www.facebook.com/dialog/oauth', array(
'query' => array(
'scope' => $options['scope'],
'client_id' => $options['fba'],
'redirect_uri' => $url,
),
));
}
return $url;
}
function fb_auth_redirect_uri($path = NULL, $options = array()) {
if (!$path) {
$path = current_path();
}
$options = $options + array(
'absolute' => TRUE,
);
$uri = url(current_path(), $options);
return $uri;
}
function fb_auth_get_token($app = NULL) {
if (!$app) {
$app = fb_get_app();
}
if (!empty($_REQUEST['code']) && !empty($_REQUEST['state']) && !empty($app['secret'])) {
if (!empty($_REQUEST['client_id']) && $_REQUEST['client_id'] != $app['fba']) {
return;
}
if ($_REQUEST['state'] == _fb_oauth_state() && !empty($app['secret'])) {
$url = url('https://graph.facebook.com/oauth/access_token', array(
'query' => array(
'client_id' => $app['fba'],
'client_secret' => $app['secret'],
'code' => $_REQUEST['code'],
'redirect_uri' => fb_auth_redirect_uri(current_path(), array(
'query' => array(
'client_id' => $app['fba'],
),
)),
),
));
$result = drupal_http_request($url);
if ($result->code == 200 && !empty($result->data)) {
$data = array();
parse_str($result->data, $data);
return $data['access_token'];
}
}
}
}
function fb_user_token_url() {
$app = fb_get_app();
$this_page = url(current_path(), array(
'absolute' => TRUE,
));
$url = url($app['base_url'] . '/fb_app/authorize/form', array(
'query' => array(
'redirect_uri' => $this_page,
'site_name' => variable_get('site_name', ''),
),
));
return $url;
}
function fb_http($url, array $options = array()) {
try {
$response = drupal_http_request($url, $options);
return fb_http_parse_response($response);
} catch (Exception $e) {
if (!empty($e->fb_code) && $e->fb_code == 190) {
$url_data = drupal_parse_url($url);
if ($token = $url_data['query']['access_token']) {
fb_token_invalid($token);
}
}
else {
fb_log_exception($e, t('Failed to query %url.', array(
'%url' => $url,
'%code' => $e->fb_code,
)));
fb_log_exception($e, t('Failed to query %url. <pre>!debug</pre>', array(
'%url' => $url,
'%code' => $e->fb_code,
'!debug' => print_r($options, 1),
)));
}
throw $e;
}
}
function fb_http_parse_response($response) {
if (is_object($response) && $response->data) {
$data = fb_json_decode($response->data);
if (is_string($data)) {
$data = fb_json_decode($data);
}
}
elseif (is_array($response) && !empty($response['body'])) {
$response = (object) $response;
$data = fb_json_decode($response->body);
}
if (isset($response->error)) {
$msg = t("!error: !detail (http !code)", array(
'!error' => $response->error,
'!code' => $response->code,
'!detail' => implode(' ', $data['error']),
));
throw new fb_GraphException($msg, $data['error']['code'], $response->code);
}
elseif (isset($data['error'])) {
$msg = t("(!type !code) !error: !detail", array(
'!error' => $data['error']['message'],
'!code' => $data['error']['code'],
'!type' => $data['error']['type'],
'!detail' => implode(' ', $data['error']),
));
throw new fb_GraphException($msg, $data['error']['code'], $response->code);
}
else {
return $data;
}
}
function fb_json_decode($json, $assoc = TRUE, $depth = 512) {
if (variable_get(FB_VAR_USE_JSON_BIGINT, defined('JSON_BIGINT_AS_STRING'))) {
return json_decode($json, $assoc, $depth, JSON_BIGINT_AS_STRING);
}
else {
$json = preg_replace('/"([^"]+)":(\\d{9}\\d*)/', '"$1":"$2"', $json);
return json_decode($json, $assoc, $depth);
}
}
function fb_graph($path, $params = NULL, $do_cache = NULL) {
if (isset($params['access_token']) && !$params['access_token'] && function_exists('debugger')) {
debugger();
}
if (is_array($params)) {
$token = isset($params['access_token']) ? $params['access_token'] : NULL;
}
elseif (is_string($params)) {
$token = $params;
$params = array();
}
else {
$token = NULL;
$params = array();
}
if ($token === NULL) {
$token = fb_access_token();
if ($do_cache === NULL) {
$do_cache = variable_get(FB_VAR_USE_CACHE, FB_CACHE_QUERY | FB_CACHE_STORE);
}
}
if ($do_cache != FB_CACHE_NONE) {
$cid = $path;
}
$session_cache = FALSE;
foreach (array(
'me',
'app',
) as $key) {
if (strpos($path, $key) === 0) {
$session_cache = TRUE;
$cid = FALSE;
break;
}
}
if ($session_cache && ($do_cache && FB_CACHE_QUERY) && !empty($_SESSION) && !empty($_SESSION['fb']) && !empty($_SESSION['fb'][$token]) && !empty($_SESSION['fb'][$token][$path])) {
return $_SESSION['fb'][$token][$path];
}
if ($do_cache & FB_CACHE_QUERY && $cid) {
$cache = cache_get($cid, 'cache_fb');
if ($cache && !empty($cache->data)) {
return $cache->data;
}
}
foreach ($params as $key => $value) {
if (is_array($value)) {
$params[$key] = json_encode($value);
}
}
if ($token) {
$params['access_token'] = $token;
}
$url = url("https://graph.facebook.com/{$path}", array(
'query' => $params,
));
$return = fb_http($url);
if ($session_cache && $do_cache & FB_CACHE_STORE) {
$_SESSION['fb'][$token][$path] = $return;
}
if (!empty($cid) && $do_cache & FB_CACHE_STORE) {
cache_set($cid, $return, 'cache_fb', CACHE_TEMPORARY);
if (!empty($return['id']) && $return['id'] != $cid) {
cache_set($return['id'], $return, 'cache_fb', CACHE_TEMPORARY);
}
}
return $return;
}
function fb_graph_batch($paths, $params = NULL, $options = array(), &$errors = NULL) {
if (isset($params['access_token']) && !$params['access_token'] && function_exists('debugger')) {
debugger();
}
if (is_array($params)) {
$token = !empty($params['access_token']) ? $params['access_token'] : FALSE;
}
elseif (is_string($params)) {
$token = $params;
$params = array(
'access_token' => $token,
);
}
elseif ($params === NULL) {
$token = NULL;
$params = array(
'access_token' => fb_access_token(),
);
}
foreach ($paths as $path) {
if (is_string($path)) {
$path_array[] = array(
'method' => 'GET',
'relative_url' => $path,
);
}
else {
$path_array[] = $path + array(
'method' => 'GET',
);
}
}
$params['batch'] = json_encode($path_array);
$url = url("https://graph.facebook.com/", array(
'query' => $params,
));
$result = fb_http($url, array(
'method' => 'POST',
));
foreach ($paths as $i => $path) {
if (is_array($path)) {
$path = $path['relative_url'];
}
try {
$return[$path] = fb_http_parse_response($result[$i]);
} catch (exception $e) {
if (!isset($errors)) {
fb_log_exception($e, t('Batch query %path failed.', array(
'%path' => $path,
)));
throw $e;
}
else {
$errors[$path] = $e;
}
}
}
return $return;
}
function fb_graph_post($path, $params) {
if (isset($params['access_token']) && !$params['access_token'] && function_exists('debugger')) {
debugger();
}
if (!isset($params['access_token'])) {
$params['access_token'] = fb_access_token();
}
$url = url("https://graph.facebook.com/{$path}");
$options = array(
'method' => 'POST',
'data' => drupal_http_build_query($params),
);
$data = fb_http($url, $options);
return $data;
}
function fb_graph_delete($path, $params) {
if (isset($params['access_token']) && !$params['access_token'] && function_exists('debugger')) {
debugger();
}
if (is_array($params)) {
$token = !empty($params['access_token']) ? $params['access_token'] : FALSE;
}
elseif (is_string($params)) {
$token = $params;
$params = array(
'access_token' => $token,
);
}
elseif ($params === NULL) {
$token = NULL;
$params = array(
'access_token' => fb_access_token(),
);
}
$url = url("https://graph.facebook.com/{$path}");
$options = array(
'method' => 'DELETE',
'data' => drupal_http_build_query($params),
);
$data = fb_http($url, $options);
return $data;
}
function fb_api($method, $params) {
$params['format'] = 'json-strings';
$app = fb_get_app();
$params['api_key'] = $app['client_id'];
$url = url("https://api.facebook.com/method/{$method}", array(
'query' => $params,
));
$http = drupal_http_request($url);
if ($http->data) {
$data = fb_json_decode($http->data);
if (is_string($data)) {
$data = fb_json_decode($data);
}
if (is_array($data)) {
if (isset($data['error_code'])) {
throw new Exception($data['error_msg'], $data['error_code']);
}
}
elseif ($http->data == 'true' || $http->code == 200) {
}
else {
if (function_exists('dpm')) {
dpm($http, __FUNCTION__ . " unexpected result from {$url}");
}
}
return $data;
}
else {
throw new FacebookApiException(array(
'error_msg' => t('fb_call_method failed calling !method. !detail', array(
'!method' => $method,
'!detail' => $http->error,
)),
'error_code' => $http->code,
));
}
}
function fb_fql($query, $token = NULL) {
$params['query'] = $query;
if ($token === NULL) {
$params['access_token'] = fb_access_token();
}
elseif ($token) {
$params['access_token'] = $token;
}
return fb_api('fql.query', $params);
}
function fb_flush_caches() {
unset($_SESSION['fb']);
return array();
}
function fb_log_exception($e, $detail = NULL, $token = NULL) {
$text = "{$detail} <em>" . $e
->getMessage() . '</em>';
if (user_access('access administration pages') && error_reporting()) {
drupal_set_message($text, 'error');
if ($e
->getCode() == 100) {
}
}
if ($token) {
$link = l(t('debug token'), url('https://developers.facebook.com/tools/debug/access_token', array(
'query' => array(
'q' => $token,
),
)));
}
else {
$link = NULL;
}
watchdog('fb', $text, array(), WATCHDOG_WARNING, $link);
}
function fb_me() {
if ($token = fb_user_token()) {
try {
$me = fb_graph('me', $token);
return $me;
} catch (Exception $e) {
fb_log_exception($e, t('Failed to query "me".'));
}
}
}
function fb_is_ajax() {
return arg(0) == 'fb' && arg(1) == 'ajax';
}
function fb_ajax_event($event_type) {
if (!empty($_REQUEST['client_id'])) {
$fba = $_REQUEST['client_id'];
}
else {
watchdog('fb', 'FB ajax event invoked without application id.', array(), WATCHDOG_ERROR);
}
$js_array = array();
if ($event_type == 'token_invalid') {
if (fb_user_token() == $_REQUEST['invalid_token']) {
fb_logout();
$js_array['fb_ajax_event'] = "FB_JS.reload()";
}
fb_token_invalid($_REQUEST['invalid_token']);
}
elseif ($event_type == 'session_change') {
if (!empty($_SESSION['fb'])) {
if (!empty($_SESSION['fb'][$fba]) && !empty($_SESSION['fb'][$fba]['access_token'])) {
fb_token_invalid($_SESSION['fb'][$fba]['access_token']);
}
unset($_SESSION['fb'][$fba]);
}
}
if (!empty($_REQUEST['access_token'])) {
fb_user_token($fba, $_REQUEST['access_token']);
}
if (!empty($_REQUEST['signed_request'])) {
$sr = fb_parse_signed_request($_REQUEST['signed_request']);
$_SESSION['fb'][$fba]['signed_request'] = $sr;
$_SESSION['fb'][$fba]['fbu'] = $sr['user_id'];
$_SESSION['fb'][$fba]['status'] = $_REQUEST['status'];
}
$data = isset($_SESSION['fb'][$fba]) ? $_SESSION['fb'][$fba] : array();
$data['fba'] = $fba;
$data['event_type'] = $event_type;
$js_array = fb_invoke(FB_OP_AJAX, $data, $js_array);
drupal_json_output(array_values($js_array));
}
function _fb_handle_tokenXXX($token, $fba) {
if (empty($_SESSION['fb']) || empty($_SESSION['fb'][$fba]) || $_SESSION['fb'][$fba]['access_token'] != $token) {
$data = array(
'token' => $token,
'fba' => $fba,
);
fb_invoke('token', $data);
}
$_SESSION['fb'][$fba]['access_token'] = $token;
}
function fb_invoke($op, $data = NULL, $return = NULL, $hook = 'fb') {
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;
}
function fb_logout() {
if (session_name()) {
session_destroy();
}
$GLOBALS['user'] = drupal_anonymous_user();
drupal_session_initialize();
}
function fb_parse_signed_request($signed_request, $secret = NULL) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$sig = fb_base64_url_decode($encoded_sig);
$data = fb_json_decode(fb_base64_url_decode($payload));
if ($secret) {
if ($data['algorithm'] !== 'HMAC-SHA256') {
throw new Exception('Parsing facebook signed request, expected HMAC-SHA256 but got ' . $data['algorithm']);
}
else {
$expected_sig = hash_hmac('sha256', $payload, $secret, TRUE);
if ($expected_sig != $sig) {
throw new Exception('Invalid signature in facebook signed request.');
}
}
}
return $data;
}
function fb_base64_url_decode($input) {
return base64_decode(strtr($input, '-_', '+/'));
}
function fb_get_name($graph_data) {
if (!empty($graph_data['name'])) {
return $graph_data['name'];
}
elseif (!empty($graph_data['id'])) {
return $graph_data['id'];
}
else {
return t('Unknown');
}
}
function fb_get_link($graph_data) {
if (!empty($graph_data['link'])) {
return $graph_data['link'];
}
elseif (!empty($graph_data['id'])) {
return 'http://www.facebook.com/' . $graph_data['id'];
}
else {
return '';
}
}
function fb_url_inbound_alter(&$path, $original_path, $path_language) {
if (strpos($path, 'fb__') === 0) {
$fb_url_alter_prefix =& drupal_static('fb_url_alter_prefix');
$fb_url_alter_prefix = '';
$fb_settings =& drupal_static('fb_settings');
$args = explode('/', $path);
while (!empty($args) && isset($fb_settings[$args[0]])) {
$key = array_shift($args);
$value = array_shift($args);
$fb_url_alter_prefix .= "{$key}/{$value}/";
}
if (count($args)) {
$path = implode('/', $args);
}
else {
$path = variable_get('site_frontpage', 'node');
}
$alias = drupal_lookup_path('source', $path, $path_language);
if ($alias) {
$path = $alias;
}
$result = $path;
}
else {
}
}
function fb_url_outbound_alter(&$path, array &$options, $original_path) {
$options += array(
'fb_url_alter' => TRUE,
'external' => FALSE,
'fb_canvas' => NULL,
);
if ($options['external'] || !$options['fb_url_alter']) {
return;
}
$fb_url_alter_prefix =& drupal_static('fb_url_alter_prefix');
if ($options['fb_canvas'] === TRUE) {
dpm($fb_url_alter_prefix, __FUNCTION__);
$fb_settings =& drupal_static('fb_settings');
dpm($fb_settings, __FUNCTION__);
$app = fb_get_app();
dpm($app, __FUNCTION__);
$fb_url_alter_prefix = 'fb__canvas/' . $app['namespace'] . '/';
}
if ($fb_url_alter_prefix) {
if ($path == '<front>') {
$path = '';
}
$path = $fb_url_alter_prefix . (!empty($options['prefix']) ? $options['prefix'] : '') . $path;
}
}
class fb_GraphException extends Exception {
public $graph_path;
public $http_code;
public $fb_code;
public function __construct($message, $fb_code, $http_code, Exception $previous = null) {
$this->http_code = $http_code;
$this->fb_code = $fb_code;
parent::__construct($message, $fb_code, $previous);
}
public function __toString() {
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
}
public function customFunction() {
echo "A custom function for this type of exception\n";
}
}