View source
<?php
drupal_add_js(drupal_get_path('module', 'fb') . '/fb.admin.js', array(
'type' => 'file',
'scope' => 'header',
'group' => JS_LIBRARY,
));
function fb_admin_token_info($token) {
$markup = array(
'#type' => 'markup',
'#prefix' => '<p>',
'#suffix' => '</p>',
);
if (!$token) {
return array(
'#markup' => t('There is no token configured.'),
) + $markup;
}
$tdata = db_query("SELECT * FROM {fb_token} WHERE access_token=:token", array(
':token' => $token,
))
->fetchAssoc();
$me = NULL;
$app = NULL;
if ($tdata) {
try {
$app = fb_graph($tdata['fba']);
$me = fb_graph($tdata['fbu']);
} catch (Exception $e) {
}
}
else {
$tdata = array(
'fba' => t('unknown'),
'fbu' => t('unknown'),
);
}
if (!$app || !$me) {
try {
$graph = fb_graph_batch(array(
'app',
'me',
), $token);
extract($graph);
} catch (exception $e) {
}
}
$args = array();
if ($app) {
$args['!app'] = l(fb_get_name($app), fb_get_link($app));
$args['!app_logo'] = $app['logo_url'];
}
else {
$args['!app'] = $tdata['fba'];
$args['!app_logo'] = '';
}
if ($me) {
$args['!me'] = l(fb_get_name($me), fb_get_link($me));
$args['!me_logo'] = "//graph.facebook.com/" . $me['id'] . '/picture';
}
else {
$args['!me'] = $tdata['fbu'];
$args['!me_logo'] = '';
}
$output[] = array(
'#markup' => t('<img src=!me_logo /> <img src=!app_logo /> Token has the privileges of !me, via the application !app.', $args),
) + $markup;
if (user_access(FB_PERM_ADMINISTER_TOKEN)) {
$output[] = array(
'#markup' => t('<a target=_blank href=!fb_url_token_debug>Debug this token on developers.facebook.com</a>.', array(
'!fb_url_token_debug' => url('https://developers.facebook.com/tools/debug/access_token', array(
'query' => array(
'q' => $token,
),
)),
)),
) + $markup;
}
return $output;
}
function fb_admin_app_info($app) {
$markup = array(
'#type' => 'markup',
'#prefix' => '<p>',
'#suffix' => '</p>',
);
if (!$app) {
return array(
'#markup' => t('There is no application configured.'),
) + $markup;
}
try {
$app = fb_graph($app['client_id']);
$args = array(
'!app' => l($app['name'], $app['link']),
);
foreach ($app as $key => $value) {
if (!is_array($value)) {
$args['!' . $key] = $value;
}
}
$output[] = array(
'#markup' => '<img src="' . $app['logo_url'] . '"/>',
) + $markup;
$output[] = array(
'#markup' => t('Using application !app.', $args),
) + $markup;
} catch (exception $e) {
fb_log_exception($e, t('Failed to query application data.'));
$output[] = array(
'#markup' => t('Could not find the application %name (%client_id) !', array(
'%name' => $app['name'],
'%client_id' => $app['client_id'],
)),
) + $markup;
}
return $output;
}
function fb_admin_default_token_form($form, &$form_state) {
$markup = array(
'#type' => 'markup',
'#prefix' => '<p>',
'#suffix' => '</p>',
);
$form['description']['#weight'] = -20;
$form['description'][] = array(
'#markup' => t('This form configures an <em>access token</em> for advanced integration between this website and Facebook.'),
) + $markup;
$form['description'][] = array(
'#markup' => t('Save a token if you want the website to interact with Facebook when the current user is not connected. For example, to cross-post content to a Facebook page while the author is not logged into Facebook.'),
) + $markup;
$form = fb_admin_replace_token_form($form, $form_state, FB_VAR_ADMIN_ACCESS_TOKEN, array(
'replace' => FALSE,
'scope' => array(
'manage_pages',
'publish_actions',
),
));
$form['submit']['#value'] = t('Save default token');
drupal_set_title(t('Site-Wide Default Access Token'));
return $form;
}
function fb_admin_replace_token_form($form, &$form_state, $variable, $options = array()) {
$options = $options + array(
'title' => t('Configure Access Token'),
'save' => TRUE,
'replace' => TRUE,
'scope' => array(),
);
drupal_set_title($options['title']);
$form_state['fb_vars']['variable'] = $variable;
$form_state['fb_vars']['options'] = $options;
if ($variable) {
$current = variable_get($variable, FALSE);
if ($current) {
$form['current_token'] = array(
'#type' => 'fieldset',
'#title' => t('Current Token'),
'info' => fb_admin_token_info($current),
'#attributes' => array(
'class' => array(
'fb_new_token_hide',
),
),
'#weight' => -10,
);
}
}
$form['fb_admin_token_select'] = array(
'#type' => 'fb_admin_token_select',
'#title' => t('Select from previously saved tokens'),
'#description' => t('Select a token from the <a href=!url>token management</a> page.', array(
'!url' => url(FB_PATH_ADMIN_CONFIG . '/token'),
)),
'#default_value' => $variable ? variable_get($variable, NULL) : NULL,
);
$form['fb_admin_token_generate'] = array(
'#type' => 'fb_admin_token_generate',
'#title' => t('Generate a new token'),
'#description' => t('Click a link to create a token for your Facebook account.'),
'#scope' => $options['scope'],
);
$form[FB_VAR_PREFER_LONG_TOKEN] = array(
'#type' => 'checkbox',
'#title' => t('Prefer longer-lived tokens.'),
'#description' => t('Some Facebook access tokens expire in minutes, or when user logs out of facebook.com. Longer lived tokens can last weeks before expiring. Facebook no longer offers access that never expire.'),
'#default_value' => variable_get(FB_VAR_PREFER_LONG_TOKEN, TRUE),
);
$form['#validate'] = array(
'fb_admin_replace_token_form_validate',
);
$form['#submit'] = array(
'fb_admin_replace_token_form_submit',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save token'),
);
return $form;
}
function fb_admin_replace_token_form_validate($form, &$form_state) {
$values = $form_state['values'];
if ($values['fb_admin_token_select'] && $values['fb_admin_token_select'] != -1 && $values['fb_admin_token_generate'] && $values['fb_admin_token_generate'] != -1) {
form_error($form[fb_admin_token_select], t('Select either a saved token or a new token. Not both.'));
}
}
function fb_admin_replace_token_form_submit($form, &$form_state) {
extract($form_state['fb_vars']);
$values = $form_state['values'];
$long_token = NULL;
$token = NULL;
foreach (array(
'fb_admin_token_select',
'fb_admin_token_generate',
) as $key) {
if ($values[$key] && $values[$key] != -1) {
$token = $values[$key];
}
}
if ($variable) {
if ($options['replace']) {
$orig_token = variable_get($variable, NULL);
db_query("DELETE FROM {fb_token} WHERE access_token = :token", array(
':token' => $orig_token,
));
}
variable_del($variable);
}
if (!$token) {
drupal_set_message(t("No token chosen."));
return;
}
extract($form_state['fb_graph']);
if ($token && $values[FB_VAR_PREFER_LONG_TOKEN]) {
$long_token = fb_admin_long_lived_token($token, $app['id']);
}
if ($long_token) {
$token = $long_token;
}
if ($variable) {
variable_set($variable, $token);
}
if ($options['save']) {
fb_token_save($token, array(
'status' => FB_STATUS_FLAG_ADMIN | FB_STATUS_FLAG_VALID,
'graph' => $form_state['fb_graph'],
));
}
drupal_set_message(t("Now using access token for %user_name via application %app_name.", array(
'%user_name' => fb_get_name($me),
'%app_name' => fb_get_name($app),
)));
}
function fb_admin_token_page() {
$token = variable_get(FB_VAR_ADMIN_ACCESS_TOKEN, NULL);
if ($token) {
try {
$graph = fb_graph_batch(array(
'me',
'app',
), $token);
} catch (Exception $e) {
}
}
return array(
'manage' => drupal_get_form('fb_admin_tokens_form'),
'add' => drupal_get_form('fb_admin_add_token_form', array(
'status' => FB_STATUS_FLAG_ADMIN,
)),
);
}
function fb_admin_add_token_form($form0, &$form_state, $options = array()) {
$form_state['fb']['options'] = $options + array(
'status' => 0,
);
if ($user_token = fb_user_token()) {
$already_saved = db_query("SELECT count(*) FROM {fb_token} WHERE access_token = :token", array(
':token' => $user_token,
))
->fetchField();
if (!$already_saved) {
try {
$graph = fb_graph_batch(array(
'me',
'app',
), $user_token);
$form['user_token'] = array(
'#type' => 'checkbox',
'#title' => t('%user via %application', array(
'%user' => $graph['me']['name'],
'%application' => $graph['app']['name'],
)),
'#return_value' => $user_token,
'#default_value' => 0,
'#description' => t('Use your current connection to facebook.'),
);
$form_state['fb_user_token'] = array(
'user_token' => $user_token,
'graph' => $graph,
);
} catch (Exception $e) {
}
}
}
$form['data'] = array(
'#tree' => TRUE,
);
$form['token'] = array(
'#type' => 'textarea',
'#rows' => 1,
'#title' => t('Access token'),
'#description' => t('Paste a complete access token. Facebook provides developer tools to <a href=!explore_url target=_blank>create</a> and <a href=!tool_url target=_blank>list</a> tokens.', array(
'!explore_url' => 'https://developers.facebook.com/tools/explorer',
'!tool_url' => 'https://developers.facebook.com/tools/access_token',
)),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Add token'),
);
$form0['wrapper'] = array(
'#type' => 'fieldset',
'#title' => t('Add Access Token'),
'form' => $form,
);
return $form0;
}
function _fb_admin_parse_textfield($text) {
$id = NULL;
$secret = NULL;
$token = NULL;
$split = preg_split('/\\s+/', $text);
if (count($split) > 1) {
foreach ($split as $item) {
if (is_numeric($item)) {
$id = trim($item);
}
else {
$secret = trim($item);
}
}
}
elseif (is_numeric($text)) {
$id = $text;
}
else {
$token = $text;
}
if ($id && $secret) {
$token = fb_admin_get_app_token($id, $secret);
}
return array(
$id,
$secret,
$token ? $token : FB_TOKEN_NONE,
);
}
function fb_admin_add_token_form_validate(&$form, &$form_state) {
extract($form_state['values']);
list($id, $secret, $token) = _fb_admin_parse_textfield($token);
if ($secret) {
$data['secret'] = $secret;
form_set_value($form['wrapper']['form']['data'], $data, $form_state);
}
if (!$token) {
form_set_error('token', t('Could not parse token %token.', array(
'%token' => $form_state['values']['token'],
)));
return;
}
if ($token) {
try {
$errors = array();
$result = fb_graph_batch(array(
'me',
'app',
), $token, array(), $errors);
$form_state['fb'] += $result;
$form_state['fb']['token'] = $token;
} catch (exception $e) {
$message = t('Access token %token is not valid.', array(
'%token' => $token,
));
fb_log_exception($e, $message);
form_set_error('token', $message);
}
if (empty($result['app'])) {
$message = t('Access token %token is not valid.', array(
'%token' => $token,
));
form_set_error('token', $message);
}
}
if (!$token && !$user_token) {
form_set_error('token', t('You have not given a token to add.'));
}
}
function fb_admin_add_token_form_submit(&$form, &$form_state) {
extract($form_state['fb']);
$status = $options['status'];
if ($token) {
$status |= FB_STATUS_FLAG_VALID;
$fba = $app['id'];
if (empty($me)) {
$record->status |= FB_STATUS_FLAG_APP;
$me = $app;
}
$fbu = $me['id'];
$data = empty($form_state['values']['data']) ? NULL : $form_state['values']['data'];
$result = fb_token_save($token, array(
'fba' => $fba,
'fbu' => $fbu,
'status' => $status,
));
if ($result) {
drupal_set_message(t('Saved !user\'s access token for !app.', array(
'!user' => l($me['name'], $me['link']),
'!app' => l($app['name'], $app['link']),
)));
}
else {
drupal_set_message(t('Failed to save token!'), 'error');
}
}
if (!empty($form_state['fb_user_token'])) {
extract($form_state['fb_user_token']);
}
if (!empty($user_token)) {
$result = fb_token_save($user_token, array(
'graph' => $graph,
'fba' => $graph['app']['id'],
'fbu' => $graph['me']['id'],
'status' => FB_STATUS_FLAG_VALID | FB_STATUS_FLAG_ADMIN,
));
if ($result) {
drupal_set_message(t('Saved !user\'s access token for !app.', array(
'!user' => l($graph['me']['name'], $graph['me']['link']),
'!app' => l($graph['app']['name'], $graph['app']['link']),
)));
}
else {
drupal_set_message(t('Failed to save token!'), 'error');
}
}
}
function fb_admin_token_filter_form() {
}
function fb_admin_tokens_form() {
$header = array(
'fba' => array(
'data' => t('Application'),
),
'fbu' => array(
'data' => t('Account'),
),
'status' => array(
'data' => t('Status'),
'field' => 'fbt.status',
),
'token' => array(
'data' => t('Token'),
'style' => 'display:none;',
'class' => 'fb_access_token',
),
'changed' => array(
'data' => t('Updated'),
'field' => 'fbt.changed',
'sort' => 'desc',
),
'operations' => array(
'data' => t('Operations'),
),
);
$query = db_select('fb_token', 'fbt')
->extend('PagerDefault')
->extend('TableSort');
$query
->leftjoin('cache_fb', 'fbc_fba', 'fbc_fba.cid = fbt.fba');
$query
->addField('fbc_fba', 'data', 'fba_data');
$query
->leftjoin('cache_fb', 'fbc_fbu', 'fbc_fbu.cid = fbt.fbu');
$query
->addField('fbc_fbu', 'data', 'fbu_data');
$results = $query
->fields('fbt')
->limit(50)
->orderByHeader($header)
->execute();
$options = array();
while ($tdata = $results
->fetchObject()) {
$options[$tdata->access_token] = array(
'fba' => $tdata->fba,
'fbu' => $tdata->fbu,
'status' => $tdata->status,
'token' => array(
'data' => $tdata->access_token,
'class' => 'fb_access_token',
'style' => 'display:none;',
),
'changed' => format_date($tdata->changed, 'short'),
'operations' => array(
'data' => array(
'#theme' => 'links',
'#attributes' => array(
'class' => array(
'links',
'inline',
),
),
'#links' => array(
'debug' => array(
'title' => t('debug'),
'href' => 'https://developers.facebook.com/tools/debug/access_token',
'query' => array(
'q' => $tdata->access_token,
),
'attributes' => array(
'target' => '_blank',
),
),
'access_token_info' => array(
'title' => t('info'),
'href' => 'https://graph.facebook.com/oauth/access_token_info',
'query' => array(
'access_token' => $tdata->access_token,
'client_id' => $tdata->fba,
),
),
),
),
),
);
if ($tdata->status & FB_STATUS_FLAG_APP) {
$options[$tdata->access_token]['operations']['data']['#links']['settings'] = array(
'title' => t('settings'),
'href' => 'https://developers.facebook.com/apps/' . $tdata->fba,
);
$options[$tdata->access_token]['operations']['data']['#links']['explore'] = array(
'title' => t('explore'),
'href' => 'https://developers.facebook.com/tools/explorer/' . $tdata->fba,
'query' => array(
'method' => 'GET',
'path' => 'me',
),
);
}
$fba_data = unserialize($tdata->fba_data);
$fbu_data = unserialize($tdata->fbu_data);
if (!empty($fba_data)) {
$options[$tdata->access_token]['fba'] = array(
'data' => array(
'#type' => 'link',
'#title' => '<img src="' . $fba_data['icon_url'] . '"/> ' . $fba_data['name'],
'#href' => $fba_data['link'],
'#suffix' => ' (' . $tdata->fba . ')',
'#options' => array(
'html' => TRUE,
),
),
);
}
if (!empty($fbu_data)) {
$options[$tdata->access_token]['fbu'] = array(
'data' => array(
'#type' => 'link',
'#title' => fb_get_name($fbu_data),
'#href' => fb_get_link($fbu_data),
'#suffix' => ' (' . $tdata->fbu . ')',
),
);
}
if ($tdata->fba == $tdata->fbu) {
$options[$tdata->access_token]['fbu'] = t('N/A');
}
}
$form['tokens'] = array(
'#type' => 'tableselect',
'#header' => $header,
'#options' => $options,
'#empty' => t('No tokens found.'),
);
$form['toggle_tokens'] = array(
'#type' => 'markup',
'#markup' => '<a href=# onclick="jQuery(\'.fb_access_token\').toggle(); return false;">show/hide tokens</a>',
);
$form['pager'] = array(
'#markup' => theme('pager'),
);
return $form;
}
function fb_admin_tokens_form_validate() {
}
function fb_admin_tokens_form_submit() {
}
function fb_admin_applications_form($form, &$form_state) {
$header = array(
'title' => array(
'data' => t('Name'),
'field' => 'fba.title',
'sort' => 'asc',
),
'fba' => array(
'data' => t('ID'),
'field' => 'fba.fba',
),
'status' => array(
'data' => t('Status'),
'field' => 'fba.status',
),
'token' => array(
'data' => t('Token'),
'style' => 'display:none;',
'class' => 'fb_access_token',
),
'local' => t('Local Operations'),
'remote' => array(
'data' => t('Facebook Operations'),
),
);
$query = db_select('fb_application', 'fba')
->extend('PagerDefault')
->extend('TableSort');
$query
->leftjoin('cache_fb', 'fbc_fba', 'fbc_fba.cid = fba.fba');
$query
->addField('fbc_fba', 'data', 'fba_data');
$results = $query
->fields('fba')
->limit(50)
->orderByHeader($header)
->execute();
$options = array();
while ($adata = $results
->fetchObject()) {
$adata->data = unserialize($adata->sdata);
$options[$adata->fba] = array(
'fba' => $adata->fba,
'title' => $adata->title,
'status' => $adata->status,
'token' => array(
'data' => $adata->data['access_token'],
'class' => 'fb_access_token',
'style' => 'display:none;',
),
'local' => array(
'data' => array(
'#theme' => 'links',
'#attributes' => array(
'class' => array(
'links',
'inline',
),
),
'#links' => array(
'edit' => array(
'title' => t('edit'),
'href' => FB_PATH_ADMIN_APPS . '/' . $adata->fba . '/edit',
),
),
),
),
'remote' => array(
'data' => array(
'#theme' => 'links',
'#attributes' => array(
'class' => array(
'links',
'inline',
),
),
'#links' => array(
'settings' => array(
'title' => t('settings'),
'href' => 'https://developers.facebook.com/apps/' . $adata->fba . '/summary',
'attributes' => array(
'target' => '_blank',
),
),
'explore' => array(
'title' => t('explore'),
'href' => 'https://developers.facebook.com/tools/explorer/' . $adata->fba,
'attributes' => array(
'target' => '_blank',
),
'query' => array(
'method' => 'GET',
'path' => $adata->fba,
),
),
),
),
),
);
$fba_data = unserialize($adata->fba_data);
if (!empty($fba_data)) {
$options[$adata->fba]['title'] = array(
'data' => array(
'#type' => 'link',
'#title' => '<img src="' . $fba_data['icon_url'] . '"/> ' . $fba_data['name'],
'#href' => $fba_data['link'],
'#options' => array(
'html' => TRUE,
),
),
);
if (!empty($fba_data['access_token'])) {
$options[$adata->fba]['remote']['data']['#links']['debug'] = array(
'title' => t('debug'),
'href' => 'https://developers.facebook.com/tools/debug/access_token',
'query' => array(
'q' => $adata->fba,
),
'attributes' => array(
'target' => '_blank',
),
);
}
}
}
$form['applications'] = array(
'#type' => 'tableselect',
'#header' => $header,
'#options' => $options,
'#empty' => t('No applications found.'),
);
$form['toggle_tokens'] = array(
'#type' => 'markup',
'#markup' => '<a href=# onclick="jQuery(\'.fb_access_token\').toggle(); return false;">show/hide tokens</a>',
);
$form['pager'] = array(
'#markup' => theme('pager'),
);
return $form;
}
function fb_admin_applications_form_validate($form, &$form_state) {
}
function fb_admin_applications_form_submit($form, &$form_state) {
}
function fb_admin_application_edit_form($form, $form_state, $data = NULL) {
if (is_numeric($data)) {
$fba = $data;
}
elseif (!empty($data['id'])) {
$fba = $data['id'];
}
else {
$fba = 0;
}
if ($fba) {
$fb_app = db_query("SELECT * FROM {fb_application} WHERE fba = :fba", array(
':fba' => $fba,
))
->fetchAssoc();
}
if (empty($fb_app)) {
$fb_app = array();
}
$fb_app = $fb_app + array(
'namespace' => NULL,
'fba' => NULL,
'status' => FB_STATUS_APP_ENABLED,
'data' => NULL,
'secret' => NULL,
'title' => t('UNKNOWN'),
);
$form['#fb_app'] = $fb_app;
$form['fba'] = array(
'#type' => 'textfield',
'#title' => t('Facebook Application ID'),
'#required' => TRUE,
'#default_value' => $fb_app['fba'],
'#description' => t('Copy and paste <em>App ID</em> (a.k.a. <em>API Key</em>) from <a href=!url target=_blank>Facebook</a>.', array(
'!url' => 'https://developers.facebook.com/apps',
)),
);
$form['secret'] = array(
'#type' => 'textfield',
'#title' => t('Secret'),
'#required' => FALSE,
'#default_value' => $fb_app['secret'],
'#description' => t('For locally hosted applications, copy and paste <em>App Secret</em> from Facebook.'),
);
$form['data'] = array(
'#tree' => TRUE,
);
$form['fb_app_data'] = array(
'#type' => 'value',
'#value' => NULL,
);
foreach (array(
'namespace',
'title',
'status',
) as $key) {
$form[$key] = array(
'#type' => 'value',
'#value' => $fb_app[$key],
);
}
$default_app = variable_get(FB_VAR_DEFAULT_APP);
$is_default = !$default_app || $default_app['client_id'] == $fb_app['fba'];
$form['is_default'] = array(
'#type' => 'value',
'#value' => $is_default,
);
$form['make_default'] = array(
'#type' => 'checkbox',
'#title' => t('Default application'),
'#description' => t('If your website hosts only one Facebook Application, check this box. If you host more than one, you may choose one primary application.'),
'#default_value' => $is_default,
);
if (!$is_default) {
$form['make_default']['#description'] .= '<br/>' . t('If checked, this application will replace %application as the default.', array(
'%application' => $default_app['name'],
));
}
$form['states'] = array(
'#tree' => TRUE,
);
$form['states']['enabled'] = array(
'#type' => 'checkbox',
'#title' => t('Enabled'),
'#default_value' => $fb_app['status'] | FB_STATUS_APP_ENABLED,
'#return_value' => FB_STATUS_APP_ENABLED,
'#description' => t('Uncheck if this server no longer hosts this application, but you prefer not to delete the settings.'),
);
$form['buttons'] = array();
$form['buttons']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save application'),
'#weight' => 20,
);
if ($fb_app['fba']) {
$form['buttons']['delete'] = array(
'#type' => 'submit',
'#value' => t('Delete application'),
'#weight' => 21,
'#submit' => array(
'fb_admin_form_delete_submit',
),
);
}
return $form;
}
function fb_admin_get_app_token($fba, $secret) {
$path = "https://graph.facebook.com/oauth/access_token?client_id=" . $fba . "&client_secret=" . $secret . "&grant_type=client_credentials";
$http = drupal_http_request($path);
if ($http->code == 200 && isset($http->data)) {
$parse = explode('=', $http->data);
$token = $parse[1];
return $token;
}
else {
drupal_set_message(t('Failed to get application token. %detail.', array(
'%detail' => $http->error,
)), 'error');
}
}
function fb_admin_application_edit_form_validate($form, &$form_state) {
$fb_app = $form_state['values'];
if ($form_state['values']['op'] != t('Delete application')) {
try {
if (!empty($fb_app['secret'])) {
$fb_app['data']['access_token'] = fb_admin_get_app_token($fb_app['fba'], $fb_app['secret']);
}
else {
list($fba, $secret, $token) = _fb_admin_parse_textfield($fb_app['fba']);
$fb_app['fba'] = $fba;
$fb_app['secret'] = $secret;
$fb_app['data']['access_token'] = $token;
}
foreach (array(
'fba',
'secret',
'data',
) as $key) {
form_set_value($form[$key], $fb_app[$key], $form_state);
}
if (!empty($fb_app['secret']) && empty($fb_app['data']['access_token'])) {
form_set_error('secret', t('Unable to get an application token. Are you sure your ID (%id) and Secret are correct?', array(
'%id' => $fb_app['fba'],
)));
}
else {
$graph = fb_graph($fb_app['fba'], $fb_app['data']['access_token'], FB_CACHE_STORE) + array(
'namespace' => NULL,
);
$form_state['fb']['graph'] = $graph;
$fb_app['data']['logo_url'] = $graph['logo_url'];
form_set_value($form['data'], $fb_app['data'], $form_state);
form_set_value($form['title'], $graph['name'], $form_state);
form_set_value($form['namespace'], $graph['namespace'], $form_state);
form_set_value($form['fb_app_data'], array(
'client_id' => $graph['id'],
'name' => $graph['name'],
'namespace' => $graph['namespace'],
), $form_state);
}
} catch (exception $e) {
$msg = t('Failed to confirm application data with facebook. (%fba)', array(
'%fba' => $fb_app['fba'],
));
fb_log_exception($e, $msg);
form_set_error('fba', $msg);
if ($e
->getCode() == 100) {
drupal_set_message(t('Hint: Error code 100 may mean that an application has "social discovery" disabled.'), 'error');
}
}
}
}
function fb_admin_application_edit_form_submit($form, &$form_state) {
$fb_app = $form_state['values'];
extract($form_state['fb']);
try {
if ($fb_app['data']['access_token']) {
fb_token_save($fb_app['data']['access_token'], array(
'fba' => $fb_app['fba'],
'fbu' => $fb_app['fba'],
'status' => FB_STATUS_FLAG_VALID | FB_STATUS_FLAG_APP,
));
}
fb_admin_app_save($fb_app);
drupal_set_message(t('Saved facebook application setting for !app.', array(
'!app' => l($graph['name'], $graph['link']),
)));
if ($form_state['values']['make_default']) {
variable_set(FB_VAR_DEFAULT_APP, $form_state['values']['fb_app_data']);
}
elseif ($form_state['values']['is_default']) {
variable_del(FB_VAR_DEFAULT_APP);
}
} catch (Exception $e) {
fb_log_exception($e, t('Failed to save application settings.'));
}
$form_state['redirect'] = FB_PATH_ADMIN_APPS;
}
function fb_admin_app_save($fb_app) {
$fb_app['sdata'] = serialize($fb_app['data']);
$result = db_merge('fb_application')
->key(array(
'fba' => $fb_app['fba'],
))
->fields(array(
'fba' => $fb_app['fba'],
'secret' => $fb_app['secret'],
'namespace' => $fb_app['namespace'],
'title' => $fb_app['title'],
'status' => $fb_app['status'],
'sdata' => empty($fb_app['data']) ? NULL : serialize($fb_app['data']),
))
->execute();
if ($result) {
return $fb_app;
}
}
function fb_admin_form_delete_submit($form, &$form_state) {
$destination = '';
if (isset($_REQUEST['destination'])) {
$destination = drupal_get_destination();
unset($_REQUEST['destination']);
}
$fb_app = $form['#fb_app'];
$form_state['redirect'] = array(
FB_PATH_ADMIN_APPS . '/' . $fb_app['fba'] . '/delete',
array(
'query' => $destination,
),
);
}
function fb_admin_application_delete_form($form, &$form_state, $fb_app) {
$form['fb_admin_description'] = array(
'#markup' => t('This will delete all local settings and access tokens associated with the facebook application %title. The application will <strong>not</strong> be deleted from facebook.com.', array(
'%title' => fb_get_name($fb_app),
)),
'#prefix' => '<p>',
'#suffix' => '</p>',
);
$form['#fb_app'] = $fb_app;
return confirm_form($form, t('Are you sure you want to delete %title?', array(
'%title' => fb_get_name($fb_app),
)), isset($_GET['destination']) ? $_GET['destination'] : FB_PATH_ADMIN_APPS . '/' . $fb_app['id'] . '/edit', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
}
function fb_admin_application_delete_form_submit($form, &$form_state) {
if ($form_state['values']['confirm']) {
$fb_app = $form['#fb_app'];
db_delete('fb_token')
->condition('fba', $fb_app['id'])
->execute();
db_delete('fb_application')
->condition('fba', $fb_app['id'])
->execute();
}
$form_state['redirect'] = FB_PATH_ADMIN_APPS;
}
function fb_admin_settings_form($form, &$form_state) {
$form[FB_VAR_PREFER_LONG_TOKEN] = array(
'#type' => 'checkbox',
'#title' => t('Use Long-lived Tokens'),
'#description' => t('When storing access tokens, get longer-lived tokens when possible. Normal tokens expire in a few hours, or when users log out of facebook. Longer-lived tokens may last months or in some cases never expire.'),
'#default_value' => variable_get(FB_VAR_PREFER_LONG_TOKEN, TRUE),
);
$form[FB_VAR_ADD_JS] = array(
'#type' => 'checkbox',
'#title' => t('Javascript SDK'),
'#description' => t('Initialize <a href=!fb_js_url target=_blank>facebook\'s javascript</a>. This enables <a href=!fb_sp_url target=_blank>social plugins</a>, for example a <a href=!fb_lb_url target=_blank>like button</a> by simply adding <em><fb:like></fb:like></em> markup.', array(
'!fb_js_url' => 'http://developers.facebook.com/docs/reference/javascript/',
'!fb_sp_url' => 'http://developers.facebook.com/docs/plugins/',
'!fb_lb_url' => 'http://developers.facebook.com/docs/reference/plugins/like/',
)),
'#default_value' => variable_get(FB_VAR_ADD_JS, FALSE),
);
$form[FB_VAR_USE_JSON_BIGINT] = array(
'#type' => 'checkbox',
'#title' => t('Use native JSON bigint decoding'),
'#description' => t('Use the JSON_BIGINT_AS_STRING flag when calling json_decode(). If the native bigint handling is not implemented on your system, uncheck this.'),
'#default_value' => variable_get(FB_VAR_USE_JSON_BIGINT, defined('JSON_BIGINT_AS_STRING')),
'#access' => defined('JSON_BIGINT_AS_STRING'),
);
return system_settings_form($form);
}
function fb_admin_settings_form_validate(&$form, &$form_state) {
$values = $form_state['values'];
if ($values[FB_VAR_USE_JSON_BIGINT]) {
$test = json_decode('[1000000000000]', TRUE, 512, JSON_BIGINT_AS_STRING);
if (!is_string($test[0])) {
form_error($form[FB_VAR_USE_JSON_BIGINT], t('Your system does not appear to support JSON_BIGINT_AS_STRING!'));
}
}
}
function fb_admin_default_app_form($form, &$form_state) {
drupal_set_title(t('Site-Wide Application'));
$markup = array(
'#type' => 'markup',
'#prefix' => '<p>',
'#suffix' => '</p>',
);
$form['description'][] = array(
'#markup' => t('A <em>Facebook application</em> enables advanced Facebook integration features.'),
) + $markup;
$form['description'][] = array(
'#markup' => t('This form selects a default for this website. Most websites need only a single application and should select it here.'),
) + $markup;
return fb_admin_app_select_form($form, $form_state, array(
'variable' => FB_VAR_DEFAULT_APP,
));
}
function fb_admin_all_apps() {
$all_apps = array();
$result = db_query("SELECT * FROM {fb_application} WHERE status & :is_enabled", array(
':is_enabled' => FB_STATUS_APP_ENABLED,
));
while ($row = $result
->fetchAssoc()) {
$row['data'] = unserialize($row['sdata']);
$all_apps[$row['fba']] = $row;
}
$result = db_query("SELECT * FROM {fb_token} WHERE status & :is_app AND status & :is_valid", array(
':is_app' => FB_STATUS_FLAG_APP,
':is_valid' => FB_STATUS_FLAG_VALID,
));
while ($row = $result
->fetchAssoc()) {
if (empty($all_apps[$row['fba']])) {
$all_apps[$row['fba']] = $row;
}
else {
$all_apps[$row['fba']] = $all_apps[$row['fba']] + $row;
}
}
return $all_apps;
}
function fb_admin_app_select_form($form, &$form_state, $params = array()) {
$params = $params + array(
'variable' => FB_VAR_DEFAULT_APP,
);
$form_state['fb']['params'] = $params;
$all_apps = fb_admin_all_apps();
$current_app = variable_get($params['variable'], array(
'client_id' => '',
));
if ($current_app['client_id'] && empty($all_apps[$current_app['client_id']])) {
$current_app['fba'] = $current_app['client_id'];
$all_apps[$current_app['client_id']] = $current_app;
}
foreach ($all_apps as $fba => $app) {
$graph[$fba] = fb_graph($fba, !empty($app['access_token']) ? $app['access_token'] : NULL);
}
if (!empty($graph)) {
foreach ($graph as $fba_data) {
$options[$fba_data['id']] = l('<img src=' . $fba_data['icon_url'] . '></img> ' . $fba_data['name'], $fba_data['link'], array(
'html' => TRUE,
'attributes' => array(
'target' => '_blank',
),
));
}
}
$options[0] = t('None');
$form['application'] = array(
'#type' => 'fieldset',
'#title' => t('Application'),
);
$form_state['fb']['graph'] = !empty($graph) ? $graph : NULL;
$form_state['fb']['all_apps'] = $all_apps;
$form['fb_app_data'] = array(
'#type' => 'value',
'#value' => NULL,
);
if (in_array($current_app['client_id'], array_keys($options))) {
$default_select = $current_app['client_id'];
$default_text = NULL;
}
else {
$default_select = 0;
$default_text = $current_app['client_id'];
}
if (count($options) > 1) {
$form['application']['client_id'] = array(
'#type' => 'radios',
'#title' => t('Application'),
'#options' => $options,
'#default_value' => $default_select,
'#description' => t('If your desired application is not shown, use the <a href=!add_app_url>add application form</a>.', array(
'!add_app_url' => url(FB_PATH_ADMIN_APPS . '/add'),
)),
);
$form['#validate'] = array(
'fb_admin_app_select_form_validate',
);
$form['#submit'] = array(
'fb_admin_app_select_form_submit',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Select application'),
);
}
else {
$form['application']['new'] = array(
'#markup' => t('Use the <a href=!add_app_url>add application form</a> to configure an application.', array(
'!add_app_url' => url(FB_PATH_ADMIN_APPS . '/add'),
)),
);
}
return $form;
}
function fb_admin_app_select_form_validate($form, &$form_state) {
extract($form_state['fb']);
$values = $form_state['values'];
if (!empty($values['client_id']) && !empty($values['client_id_new'])) {
form_error($form['application']['client_id_new'], t('Select either a local application radio button or paste a remote application ID. Not both.'));
return;
}
$token = NULL;
if (!empty($values['client_id_new'])) {
list($id, $secret, $token) = _fb_admin_parse_textfield($token);
$client_id = $id;
$key = 'client_id_new';
if ($secret) {
form_set_error($key, t('Use add application form to paste ID and secret.'));
return;
}
}
else {
$client_id = $values['client_id'];
$key = 'client_id';
}
if (empty($graph[$client_id])) {
try {
$gdata = fb_graph($client_id, $token);
} catch (exception $e) {
fb_log_exception($e, t('Failed to look up application %id.', array(
'%id' => $client_id,
)));
$gdata = NULL;
}
}
else {
$gdata = $graph[$client_id];
}
if (empty($gdata) || empty($gdata['id'])) {
form_set_error($key, t('Failed to look up application id %id.', array(
'%id' => $client_id,
)));
}
else {
form_set_value($form['fb_app_data'], array(
'client_id' => $gdata['id'],
'name' => $gdata['name'],
'namespace' => !empty($gdata['namespace']) ? $gdata['namespace'] : NULL,
), $form_state);
}
}
function fb_admin_app_select_form_submit($form, &$form_state) {
$app_data = $form_state['values']['fb_app_data'];
extract($form_state['fb']);
if ($app_data['client_id']) {
variable_set($params['variable'], $app_data);
}
else {
variable_del($params['variable']);
}
drupal_set_message(t('Recommended: <a href=!cache_url>clear all caches</a> after changing Facebook app settings.', array(
'!cache_url' => url('admin/config/development/performance'),
)), 'warning');
drupal_set_message(t('The configuration options have been saved.'));
}
function fb_admin_token_select_process(&$element, &$form_state, &$form) {
$element = $element + array(
'#default_value' => -1,
);
$element['#tree'] = TRUE;
$all_tokens = array();
$i = 0;
$option_default = -1;
$result = db_query("SELECT * FROM {fb_token} WHERE access_token = :current_token OR (status & :valid_flag AND status & :admin_flag) ORDER BY changed DESC", array(
':current_token' => $element['#default_value'],
':valid_flag' => FB_STATUS_FLAG_VALID,
':admin_flag' => FB_STATUS_FLAG_ADMIN,
));
while ($token_data = $result
->fetchAssoc()) {
$i++;
$all_tokens[$i] = $token_data;
try {
$fba_data = fb_graph($token_data['fba']);
$fbu_data = fb_graph($token_data['fbu']);
} catch (exception $e) {
fb_log_exception($e, t('Failed to get token data.'));
}
if ($token_data['status'] & FB_STATUS_FLAG_ADMIN && !($token_data['status'] & FB_STATUS_FLAG_APP)) {
$options[$i] = t('%name via %app', array(
'%name' => fb_get_name($fbu_data),
'%app' => fb_get_name($fba_data),
'%time_ago' => format_interval(REQUEST_TIME - $token_data['changed']),
));
if (!($token_data['status'] & FB_STATUS_FLAG_VALID)) {
$options[$i] .= ' ' . t('(This token has expired!)');
}
elseif ($token_data['access_token'] == $element['#default_value']) {
$option_default = $i;
}
}
}
$form_state['fb']['all_tokens'] = $all_tokens;
if (!empty($options)) {
$options[-1] = t('Do not use a saved token');
if (!empty($_REQUEST['code'])) {
$option_default = -1;
}
$element['fb_token_index'] = array(
'#type' => 'radios',
'#options' => $options,
'#default_value' => $option_default,
);
}
return $element;
}
function fb_admin_token_select_validate($element, &$form_state) {
$token = NULL;
extract($form_state['fb']);
if (!empty($element['#value'])) {
extract($element['#value']);
}
else {
$fb_token_index = -1;
}
if ($fb_token_index > 0) {
$token = $all_tokens[$fb_token_index]['access_token'];
try {
$graph = fb_graph_batch(array(
'me',
'app',
), $token);
$form_state['fb_graph'] = $graph;
} catch (Exception $e) {
form_error($element['fb_token_index'], t('Could not validate token. %detail', array(
'%detail' => $e
->getMessage(),
)));
$token = NULL;
}
}
form_set_value($element, $token, $form_state);
}
function fb_admin_token_generate_process(&$element, &$form_state, &$form) {
$element = $element + array(
'#scope' => array(),
'#options' => array(),
);
$element['#tree'] = TRUE;
unset($element['#needs_validation']);
$all_apps = fb_admin_all_apps();
$scope = implode(',', $element['#scope']);
$new_token_options = $element['#options'] + array(
-1 => t('Do not save new token'),
);
foreach ($all_apps as $app_data) {
if (!empty($app_data['secret'])) {
$auth_url = fb_server_auth_url(array(
'fba' => $app_data['fba'],
'scope' => $scope,
));
}
elseif (!empty($app_data['data']['access_token'])) {
$auth_url = fb_client_auth_url(array(
'fba' => $app_data['fba'],
'scope' => $scope,
));
}
else {
$auth_url = fb_remote_auth_url($app_data + array(
'scope' => $scope,
));
}
$generate_links[] = array(
'title' => t('Generate new token via %application', array(
'%application' => $app_data['title'],
)),
'href' => $auth_url,
'html' => TRUE,
);
if (empty($_POST) && ($token = fb_auth_get_token($app_data))) {
if (empty($new_token_options[$token])) {
try {
$me = fb_graph('me', $token);
$app = fb_graph('app', $token);
$new_token_options[$token] = t('%user_name via the %app_name application', array(
'%user_name' => fb_get_name($me),
'%app_name' => fb_get_name($app),
));
drupal_set_message(t('Generated a new access token, but not yet saved. Remember to press the submit button.'), 'warning');
$default_token = $token;
} catch (exception $e) {
fb_log_exception($e, t('Failed to save new access token for %application.', array(
'%application' => $app['title'],
)), $token);
drupal_set_message(t('Failed to validate new token. You may <a target=_blank href=!token_debug_url>debug the token on Facebook</a>.', array(
'!token_debug_url' => 'https://developers.facebook.com/tools/debug/access_token?q=' . $token,
)), 'error');
}
try {
$accounts = fb_graph('me/accounts', $token);
foreach ($accounts['data'] as $account_data) {
if (!empty($account_data['access_token'])) {
$new_token_options[$account_data['access_token']] = t('%account_name (%account_type) via %app_name', array(
'%account_name' => fb_get_name($account_data),
'%account_type' => $account_data['category'],
'%app_name' => !empty($app) ? fb_get_name($app) : t('(could not determine application)'),
));
}
}
} catch (Exception $e) {
}
}
}
}
if (count($new_token_options) > 1) {
$element['fb_admin_token_generate_new'] = array(
'#type' => 'radios',
'#options' => $new_token_options,
'#default_value' => $default_token,
);
}
if (!empty($generate_links)) {
$element['fb_admin_token_generate_links'] = array(
'#theme' => 'links',
'#links' => $generate_links,
);
}
return $element;
}
function fb_admin_token_generate_after_build(&$element, &$form_state) {
return $element;
}
function fb_admin_token_generate_validate($element, &$form_state) {
$token = NULL;
if (!empty($element['#value']['fb_admin_token_generate_new'])) {
$token = $element['#value']['fb_admin_token_generate_new'];
try {
$graph = fb_graph_batch(array(
'me',
'app',
), $token);
$form_state['fb_graph'] = $graph;
extract($graph);
if (empty($form_state['redirect'])) {
$form_state['redirect'] = current_path();
}
} catch (Exception $e) {
form_error($element, t('Could not validate new token. %detail', array(
'%detail' => $e
->getMessage(),
)));
$token = NULL;
}
}
form_set_value($element, $token, $form_state);
}
function fb_admin_long_lived_token($token, $app_id = NULL) {
$all_apps = fb_admin_all_apps();
$app = $all_apps[$app_id];
if ($app && $app['secret']) {
try {
$result = fb_graph('oauth/access_token', array(
'client_id' => $app['fba'],
'client_secret' => $app['secret'],
'grant_type' => 'fb_exchange_token',
'fb_exchange_token' => $token,
), FALSE);
if (!empty($result['access_token'])) {
drupal_set_message(t('Using longer-lived token which is set to expire in %duration.', array(
'%token' => $result['access_token'],
'%duration' => !empty($result['expires']) ? format_interval($result['expires']) : t('(could not determine expiration)'),
)));
return $result['access_token'];
}
} catch (Exception $e) {
drupal_set_message(t('Could not convert the token into a longer-lived token. This is expected when token belongs to a page rather than a user.'));
}
}
}