diff --git a/contrib/fb_example.info b/contrib/fb_example.info index 24320c2..687a382 100644 --- a/contrib/fb_example.info +++ b/contrib/fb_example.info @@ -1,8 +1,15 @@ -name = FB Example Customizations -description = (fb_example.module) These hooks will make your site behave more like drupalforfacebook.org. Use this code as an example for your own customizations. -package = Drupal for Facebook - contrib -core = 6.x -dependencies[] = fb -dependencies[] = fb_form -dependencies[] = fb_app -dependencies[] = fb_friend +name = FB Example Customizations +description = (fb_example.module) These hooks will make your site behave more like drupalforfacebook.org. Use this code as an example for your own customizations. +package = Drupal for Facebook - contrib +core = 7.x +dependencies[] = fb +dependencies[] = fb_form +dependencies[] = fb_app +dependencies[] = fb_friend + +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/contrib/fb_friend.info b/contrib/fb_friend.info index 8ffe311..a93a126 100644 --- a/contrib/fb_friend.info +++ b/contrib/fb_friend.info @@ -1,8 +1,15 @@ -name = FB Friend Features -description = (fb_friend.module) Blocks for showing the current user's friends, sending them requests, etc. -package = Drupal for Facebook - contrib -core = 6.x -dependencies[] = fb -dependencies[] = fb_form -dependencies[] = fb_app - +name = FB Friend Features +description = (fb_friend.module) Blocks for showing the current user's friends, sending them requests, etc. +package = Drupal for Facebook - contrib +core = 7.x +dependencies[] = fb +dependencies[] = fb_form +dependencies[] = fb_app + + +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/contrib/fb_permission.info b/contrib/fb_permission.info index 167a7f4..faeefb2 100644 --- a/contrib/fb_permission.info +++ b/contrib/fb_permission.info @@ -1,6 +1,13 @@ -name= FB Extended Permissions -description = (fb_permission.module) Host applications that require or support Extended Permissions. -package = Drupal for Facebook - contrib -dependencies[] = fb -dependencies[] = fb_app -core = 6.x +name= FB Extended Permissions +description = (fb_permission.module) Host applications that require or support Extended Permissions. +package = Drupal for Facebook - contrib +dependencies[] = fb +dependencies[] = fb_app +core = 7.x + +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/contrib/fb_registration.info b/contrib/fb_registration.info index e8417a0..8965b56 100644 --- a/contrib/fb_registration.info +++ b/contrib/fb_registration.info @@ -1,7 +1,14 @@ -name = FB Registration -description = (fb_registration.module) Use the registration feature. -package = Drupal for Facebook - contrib -core = 6.x -dependencies[] = fb -dependencies[] = fb_app - +name = FB Registration +description = (fb_registration.module) Use the registration feature. +package = Drupal for Facebook - contrib +core = 7.x +dependencies[] = fb +dependencies[] = fb_app + + +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/contrib/fb_rules.info b/contrib/fb_rules.info index e9e3ffe..145dbef 100644 --- a/contrib/fb_rules.info +++ b/contrib/fb_rules.info @@ -1,6 +1,13 @@ -name= FB Rules Integration -description = (fb_rules.module) Provide Facebook events access and interaction through Rules. -package = Drupal for Facebook - contrib -dependencies[] = fb -dependencies[] = rules -core = 6.x +name= FB Rules Integration +description = (fb_rules.module) Provide Facebook events access and interaction through Rules. +package = Drupal for Facebook - contrib +dependencies[] = fb +dependencies[] = rules +core = 7.x + +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/contrib/fb_test.info b/contrib/fb_test.info index 82ba0a2..f3474c5 100644 --- a/contrib/fb_test.info +++ b/contrib/fb_test.info @@ -1,9 +1,16 @@ -name = FB Testing Helpers -description = (fb_test.module) Create test accounts. -package = Drupal for Facebook - contrib -core = 7.x -dependencies[] = fb -dependencies[] = fb_app - -files[] = fb_test.module - +name = FB Testing Helpers +description = (fb_test.module) Create test accounts. +package = Drupal for Facebook - contrib +core = 7.x +dependencies[] = fb +dependencies[] = fb_app + +files[] = fb_test.module + + +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/contrib/fb_test.module b/contrib/fb_test.module index 0d10455..1bf2051 100644 --- a/contrib/fb_test.module +++ b/contrib/fb_test.module @@ -1,196 +1,196 @@ - 'Test Accounts', - 'page callback' => 'fb_test_detail_page', - 'page arguments' => array(FB_PATH_ADMIN_APPS_ARGS), - 'access arguments' => array(FB_PERM_ADMINISTER), - 'type' => MENU_LOCAL_TASK, - ); - - return $items; -} - -function fb_test_detail_page($fb_app) { - $output['form1'] = drupal_get_form('fb_test_create_form', $fb_app); - $output['form2'] = drupal_get_form('fb_test_accounts_form', $fb_app); - return $output; -} - -function fb_test_create_form(&$form, &$form_state, $fb_app) { - $form['#fb_app'] = $fb_app; - - // @TODO make this a dropdown, limit to 50 total test accounts. - $form['how_many'] = array( - '#type' => 'textfield', - '#title' => t('Number of test accounts to create'), - ); - - $form['installed'] = array( - '#type' => 'checkbox', - '#title' => t('Installed'), - '#description' => t('If selected, new users have already authorized the application'), - ); - - // Which permissions? - $perms = array(); - drupal_alter('fb_required_perms', $perms); // @TODO pass fb_app to this function. - if (count($perms)) { - $default_perms = implode(',', $perms); - } - - $form['perms'] = array( - '#type' => 'textfield', - '#title' => t('Extended Permission'), - '#description' => t('If app is authorized, users have granted these permissions.'), - '#default_value' => $default_perms, - ); - - $form['submit'] = array( - '#type' => 'submit', - '#value' => t('Create Test Accounts'), - ); - return $form; -} - -function fb_test_create_form_submit($form, &$form_state) { - $values = $form_state['values']; - $fb_app = $form['#fb_app']; - try { - $fb = fb_api_init($fb_app); - for ($i = 0; $i < $values['how_many']; $i++) { - $result = $fb->api($fb_app->id . "/accounts/test-users", 'POST', array( - 'installed' => $values['installed'], - 'permissions' => $values['perms'], - 'access_token' => fb_get_token($fb), - )); - } - drupal_set_message(t('Created %num test accounts.', array('%num' => $values['how_many']))); - } - catch (Exception $e) { - fb_log_exception($e, t('Failed to create test accounts.')); - } -} - -function fb_test_accounts_form($form, &$form_state, $fb_app) { - try { - $form['#fb_app'] = $fb_app; - $fb = fb_api_init($fb_app); - - $result = $fb->api($fb_app->id . "/accounts/test-users", 'GET', array( - 'access_token' => fb_get_token($fb), - )); - - foreach ($result['data'] as $test_account) { - $form['#fb_test_accounts'][$test_account['id']] = $test_account; - - $markup = "$test_account[id] (login)"; - if (isset($test_account['access_token'])) { - $data = $fb->api($test_account['id'], 'GET', array( - 'access_token' => $test_account['access_token'], // Only when account is authorized - )); - if ($data['name']) { - $markup .= " $data[name] (profile) "; - } - } - - $options[$test_account['id']] = $markup; - } - if (!empty($options)) { - $form['checkboxes'] = array( - '#type' => 'checkboxes', - '#options' => $options, - ); - } - - $form['operation'] = array( - '#type' => 'select', - '#title' => t('With selected...'), - '#options' => array( - 'none' => t('please select...'), - 'friends' => t('make friends'), - 'delete' => t('delete account'), - ), - '#description' => t('Use caution, there will be no confirmation page.'), - ); - - $form['submit'] = array( - '#type' => 'submit', - '#value' => t('Submit'), - ); - - $form['header'] = array( - '#type' => "markup", - '#value' => "
Test Accounts
", - '#weight' => -10, - ); - } - catch (Exception $e) { - fb_log_exception($e, t('Failed to access test accounts.')); - } - return $form; -} - -function fb_test_accounts_form_submit($form, &$form_state) { - $values = $form_state['values']; - $fb_app = $form['#fb_app']; - $fb = fb_api_init($fb_app); - - try { - if ($values['operation'] == 'friends') { - foreach ($values['checkboxes'] as $fbu => $selected) { - if ($selected && isset($form['#fb_test_accounts'][$fbu]['access_token'])) { - foreach ($values['checkboxes'] as $fbu2 => $selected2) { - if ($selected2 && ($fbu != $fbu2)) { - try { - $result = $fb->api("$fbu/friends/{$fbu2}", "POST", array( - 'access_token' => $form['#fb_test_accounts'][$fbu]['access_token'], - )); - if ($result) { - drupal_set_message(t("User %fbu is friends with $fbu2.", array( - '%fbu' => $fbu, - '%fbu2' => $fbu2, - ))); - } - } - catch (Exception $e) { - $message = t("Failed to create friendship between %fbu and %fbu2.", array( - '%fbu' => $fbu, - '%fbu2' => $fbu2, - )); - fb_log_exception($e, $message); - } - } - } - } - } - } - elseif ($values['operation'] == 'delete') { - foreach ($values['checkboxes'] as $fbu => $selected) { - if ($selected) { - $result = $fb->api($fbu, 'DELETE', array('access_token' => fb_get_token($fb))); - if ($result) { - drupal_set_message(t('Deleted test account %fbu', array( - '%fbu' => $fbu, - ))); - } - } - } - } - else { - dpm("Operation $values[operation] not implemented.", __FUNCTION__); // debug - } - } - catch (Exception $e) { - fb_log_exception($e, t('Failed to perform operation.')); - } -} + 'Test Accounts', + 'page callback' => 'fb_test_detail_page', + 'page arguments' => array(FB_PATH_ADMIN_APPS_ARGS), + 'access arguments' => array(FB_PERM_ADMINISTER), + 'type' => MENU_LOCAL_TASK, + ); + + return $items; +} + +function fb_test_detail_page($fb_app) { + $output['form1'] = drupal_get_form('fb_test_create_form', $fb_app); + $output['form2'] = drupal_get_form('fb_test_accounts_form', $fb_app); + return $output; +} + +function fb_test_create_form($form, &$form_state, $fb_app) { + $form['#fb_app'] = $fb_app; + + // @TODO make this a dropdown, limit to 50 total test accounts. + $form['how_many'] = array( + '#type' => 'textfield', + '#title' => t('Number of test accounts to create'), + ); + + $form['installed'] = array( + '#type' => 'checkbox', + '#title' => t('Installed'), + '#description' => t('If selected, new users have already authorized the application'), + ); + + // Which permissions? + $perms = array(); + drupal_alter('fb_required_perms', $perms); // @TODO pass fb_app to this function. + if (count($perms)) { + $default_perms = implode(',', $perms); + } + + $form['perms'] = array( + '#type' => 'textfield', + '#title' => t('Extended Permission'), + '#description' => t('If app is authorized, users have granted these permissions.'), + '#default_value' => $default_perms, + ); + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Create Test Accounts'), + ); + return $form; +} + +function fb_test_create_form_submit($form, &$form_state) { + $values = $form_state['values']; + $fb_app = $form['#fb_app']; + try { + $fb = fb_api_init($fb_app); + for ($i = 0; $i < $values['how_many']; $i++) { + $result = $fb->api($fb_app->id . "/accounts/test-users", 'POST', array( + 'installed' => $values['installed'], + 'permissions' => $values['perms'], + 'access_token' => fb_get_token($fb), + )); + } + drupal_set_message(t('Created %num test accounts.', array('%num' => $values['how_many']))); + } + catch (Exception $e) { + fb_log_exception($e, t('Failed to create test accounts.')); + } +} + +function fb_test_accounts_form($form, &$form_state, $fb_app) { + try { + $form['#fb_app'] = $fb_app; + $fb = fb_api_init($fb_app); + + $result = $fb->api($fb_app->id . "/accounts/test-users", 'GET', array( + 'access_token' => fb_get_token($fb), + )); + + foreach ($result['data'] as $test_account) { + $form['#fb_test_accounts'][$test_account['id']] = $test_account; + + $markup = "$test_account[id] (login)"; + if (isset($test_account['access_token'])) { + $data = $fb->api($test_account['id'], 'GET', array( + 'access_token' => $test_account['access_token'], // Only when account is authorized + )); + if ($data['name']) { + $markup .= " $data[name] (profile) "; + } + } + + $options[$test_account['id']] = $markup; + } + if (!empty($options)) { + $form['checkboxes'] = array( + '#type' => 'checkboxes', + '#options' => $options, + ); + } + + $form['operation'] = array( + '#type' => 'select', + '#title' => t('With selected...'), + '#options' => array( + 'none' => t('please select...'), + 'friends' => t('make friends'), + 'delete' => t('delete account'), + ), + '#description' => t('Use caution, there will be no confirmation page.'), + ); + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Submit'), + ); + + $form['header'] = array( + '#type' => "markup", + '#value' => "Test Accounts
", + '#weight' => -10, + ); + } + catch (Exception $e) { + fb_log_exception($e, t('Failed to access test accounts.')); + } + return $form; +} + +function fb_test_accounts_form_submit($form, &$form_state) { + $values = $form_state['values']; + $fb_app = $form['#fb_app']; + $fb = fb_api_init($fb_app); + + try { + if ($values['operation'] == 'friends') { + foreach ($values['checkboxes'] as $fbu => $selected) { + if ($selected && isset($form['#fb_test_accounts'][$fbu]['access_token'])) { + foreach ($values['checkboxes'] as $fbu2 => $selected2) { + if ($selected2 && ($fbu != $fbu2)) { + try { + $result = $fb->api("$fbu/friends/{$fbu2}", "POST", array( + 'access_token' => $form['#fb_test_accounts'][$fbu]['access_token'], + )); + if ($result) { + drupal_set_message(t("User %fbu is friends with $fbu2.", array( + '%fbu' => $fbu, + '%fbu2' => $fbu2, + ))); + } + } + catch (Exception $e) { + $message = t("Failed to create friendship between %fbu and %fbu2.", array( + '%fbu' => $fbu, + '%fbu2' => $fbu2, + )); + fb_log_exception($e, $message); + } + } + } + } + } + } + elseif ($values['operation'] == 'delete') { + foreach ($values['checkboxes'] as $fbu => $selected) { + if ($selected) { + $result = $fb->api($fbu, 'DELETE', array('access_token' => fb_get_token($fb))); + if ($result) { + drupal_set_message(t('Deleted test account %fbu', array( + '%fbu' => $fbu, + ))); + } + } + } + } + else { + dpm("Operation $values[operation] not implemented.", __FUNCTION__); // debug + } + } + catch (Exception $e) { + fb_log_exception($e, t('Failed to perform operation.')); + } +} diff --git a/contrib/fb_user_app.info b/contrib/fb_user_app.info index 80d6ce5..9967305 100644 --- a/contrib/fb_user_app.info +++ b/contrib/fb_user_app.info @@ -1,9 +1,16 @@ -name= FB User Tracking -description = (fb_user_app.module) Keep records of users most recent visits to your apps. Note that this adds some overhead to each app visit. -package = Drupal for Facebook - contrib -configure = admin/structure/fb/fb_user_app -core = 7.x -dependencies[] = fb -dependencies[] = fb_app - -files[] = fb_user_app.module +name= FB User Tracking +description = (fb_user_app.module) Keep records of users most recent visits to your apps. Note that this adds some overhead to each app visit. +package = Drupal for Facebook - contrib +configure = admin/structure/fb/fb_user_app +core = 7.x +dependencies[] = fb +dependencies[] = fb_app + +files[] = fb_user_app.module + +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/contrib/fb_user_app.module b/contrib/fb_user_app.module index ac1fce3..09a5000 100644 --- a/contrib/fb_user_app.module +++ b/contrib/fb_user_app.module @@ -1,231 +1,231 @@ - 'Tracking', - 'description' => 'Settings that track statistics in Drupal for Facebook', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('fb_user_app_admin_settings'), - 'access arguments' => array(FB_PERM_ADMINISTER), - 'file' => 'fb_user_app.admin.inc', - 'type' => MENU_LOCAL_TASK, - ); - - return $items; -} - -/** - * Implementation of hook_fb() - */ -function fb_user_app_fb($op, $data, &$return) { - $fb_app = isset($data['fb_app']) ? $data['fb_app'] : NULL; - $fb = isset($data['fb']) ? $data['fb'] : NULL; - - global $user; - - if ($op == FB_OP_APP_IS_AUTHORIZED && - variable_get(FB_USER_APP_VAR_TRACK_EVERY_PAGE, FALSE)) { - - // This hook is called on every page request, if the user has authorized - // the app/page and permission has been granted in the settings. We used - // to create accounts and maps here. That code is now - // in FB_OP_AJAX_EVENT, because it turns out this hook is invoked even on - // page not found and access denied pages. - - fb_user_app_track($fb, $fb_app, $user); - } - elseif ($op == FB_APP_OP_EVENT) { - - // Facebook has notified us of some event. - // We handle some of the events here. - $event_type = $data['event_type']; - - // Ensure fb_user_app table accurately reflects whether user has authorized. - if ($event_type == FB_APP_EVENT_POST_AUTHORIZE) { - // Track new facebook user, $GLOBAL['user'] not valid during post-authorize. - fb_user_app_track($fb, $fb_app); - } - elseif ($event_type == FB_APP_EVENT_POST_REMOVE) { - $fbu = fb_settings(FB_SETTINGS_FBU); - // User has removed the app from their account. - db_query("DELETE FROM {fb_user_app} WHERE apikey=:apikey AND fbu=:fbu", array( - ':apikey' => $fb_app->apikey, - ':fbu' => $fbu, - )); - } - } - elseif ($op == FB_OP_GET_USER_SESSION) { - - // The fb module is asking for session login information. For example, to - // log in as the user when not on a canvas page. This module may be able - // to provide it, depending on whether the user has logged in, and whether - // the session has expired. - $fbu = $data['fbu']; - $result = db_query("SELECT * FROM {fb_user_app} WHERE apikey = :apikey and fbu = :fbu", array( - ':apikey' => $fb_app->apikey, - ':fbu' => $fbu, - )); - $data = $result->fetchObject(); - - if ($data && $data->session_key) - // Return array with FB id and apikey. - $return = array( - 'fbu' => $data->fbu, - 'access_token' => $data->session_key, - 'expires' => $data->session_key_expires, - ); - } - elseif ($op == FB_OP_AJAX_EVENT) { // handle internal login - // @TODO - global user is not correct here. - - // fb.js has notified us of an event via AJAX. Not the same as facebook event callback above. - if ($data['event_type'] == 'session_change' && isset($data['event_data']['fbu'])) { - // A user has logged in. - fb_user_app_track($fb, $fb_app, $user); - } - } -} - -/** - * Implements hook_user_delete(). - * - * @TODO confirm there is no race condition between this module and fb_user. - * That is, during delete, does fb_get_fbu() still work? - */ -function fb_user_app_user_delete($account) { - // Given the uid, fetch the fbu so that we can delete - $fbu = fb_get_fbu($account->uid); - db_query('DELETE FROM {fb_user_app} WHERE fbu=:fbu', array( - ':fbu' => $fbu, - )); -} - -/** - * Keep track of when the user has visited the app, and whether they've - * authorized the app or not. - * - * Historically this supported infinite sessions. I believe if this data is - * no longer necessary for the offline access extended permission. - */ -function fb_user_app_track($fb, $fb_app) { - // Coming from a user adding the app or a page adding the app? - $fb_user_type = "user"; - $fbu = fb_facebook_user($fb); - if (array_key_exists('fb_sig_page_added', $_REQUEST)) { - // It's a post-authorize event for app added to page. - $fb_user_type = "page"; - $fbu = $_REQUEST['fb_sig_page_id']; - } - - - // test if we are tracking only those apps that have been granted offline - // access. - $fb_session = $fb->getSession(); - - // when 'expires' == 0 app has been granted offline access - if ($fb_user_type == 'user' && - $fb_session["expires"] <> 0 && - variable_get(FB_USER_APP_VAR_USERS_THAT_GRANT_OFFLINE, FALSE)) - return; - - // Track this event only if allowed to and only for users, not pages - if ((variable_get(FB_USER_APP_VAR_TRACK_USERS, TRUE) && $fb_user_type = "user") || - (variable_get(FB_USER_APP_VAR_TRACK_PAGES, TRUE) && $fb_user_type = "page")) { - - $access_token = isset($fb_session['access_token']) ? $fb_session['access_token'] : ''; - $result1 = db_query("UPDATE {fb_user_app} SET time_access=:time, session_key=:token, session_key_expires=:expires, user_type=:type WHERE apikey=:apikey AND fbu=:fbu", array( - ':time' => REQUEST_TIME, - ':token' => $access_token, - ':expires' => $fb_session['expires'], - ':type' => $fb_user_type, - ':apikey' => $fb_app->apikey, - ':fbu' => fb_facebook_user($fb), - )); - - if ($result1 && $result1->rowCount() == 0) { - // The row for this user was never inserted, or it was deleted, or the times were the same. - $fbu = fb_facebook_user($fb); - if ($fbu) { - //First make sure it was not just the same time - $result = db_query("SELECT * FROM {fb_user_app} WHERE apikey=:apikey AND fbu=:fbu", array( - ':apikey' => $fb_app->apikey, - ':fbu' => $fbu, - )); - if (!$result->fetchObject()) { - //This row does not exist, even with the same time. Insert now - list($data) = fb_fql_query($fb, "SELECT name, is_app_user, email, proxied_email FROM user WHERE uid=$fbu", array('access_Token' => $fb_session_key)); - //watchdog('fb_user_app', "fb user data" . print_r($data, 1) . ''); - $fb_user_type = "user"; - $result = db_query("INSERT INTO {fb_user_app} (apikey, fbu, added, user_type, session_key, session_key_expires, time_access, proxied_email, time_cron) VALUES (:apikey, :fbu, :added, :user_type, :session_key, :session_key_expires, :time_access, :proxied_email, :time_cron)", array( - ':apikey' => $fb_app->apikey, - ':fbu' => $fbu, - ':added' => $data['is_app_user'], - ':user_type' => $fb_user_type, - ':session_key' => $access_token, - ':session_key_expires' => $fb_session['expires'], - ':time_access' => REQUEST_TIME, - ':proxied_email' => $data['email'] ? $data['email'] : ($data['proxied_email'] ? $data['proxied_email'] : ''), // test accounts will not have - ':time_cron' => 0, - )); - } - } - } - if (FALSE && $result === FALSE) { // XXX upgrade to D7??? - watchdog('fb_user_app', "Failed to update fb_user_app table.", array(), WATCHDOG_ERROR); - } - } -} - -/** - * Learn the user's proxied email address. - * - */ -function fb_user_app_get_proxied_email($fbu, $fb_app) { - // Try to learn from local database - $result = db_query("SELECT * FROM {fb_user_app} WHERE apikey=:apikey AND fbu=:fbu", array( - ':apikey' => $fb_app->apikey, - ':fbu' => $fbu, - )); - if ($data = $result->fetchObject()) { - $mail = $data->proxied_email; - } - - if (!$mail) { - // Ask facebook for info. - $fb = fb_api_init($fb_app); - $info = fb_users_getInfo(array($fbu), $fb); - $data = $info[0]; - $mail = $data['proxied_email']; - if ($mail && variable_get(FB_USER_APP_VAR_TRACK_USERS, TRUE)) { - // Store locally. - $result = db_query("UPDATE {fb_user_app} SET proxied_email=:mail WHERE apikey=:apikey AND fbu=:fbu", array( - ':mail' => $mail, - ':apikey' => $fb_app->apikey, - ':fbu' => $fbu, - )); - } - } - return $mail; -} + 'Tracking', + 'description' => 'Settings that track statistics in Drupal for Facebook', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('fb_user_app_admin_settings'), + 'access arguments' => array(FB_PERM_ADMINISTER), + 'file' => 'fb_user_app.admin.inc', + 'type' => MENU_LOCAL_TASK, + ); + + return $items; +} + +/** + * Implementation of hook_fb() + */ +function fb_user_app_fb($op, $data, &$return) { + $fb_app = isset($data['fb_app']) ? $data['fb_app'] : NULL; + $fb = isset($data['fb']) ? $data['fb'] : NULL; + + global $user; + + if ($op == FB_OP_APP_IS_AUTHORIZED && + variable_get(FB_USER_APP_VAR_TRACK_EVERY_PAGE, FALSE)) { + + // This hook is called on every page request, if the user has authorized + // the app/page and permission has been granted in the settings. We used + // to create accounts and maps here. That code is now + // in FB_OP_AJAX_EVENT, because it turns out this hook is invoked even on + // page not found and access denied pages. + + fb_user_app_track($fb, $fb_app, $user); + } + elseif ($op == FB_APP_OP_EVENT) { + + // Facebook has notified us of some event. + // We handle some of the events here. + $event_type = $data['event_type']; + + // Ensure fb_user_app table accurately reflects whether user has authorized. + if ($event_type == FB_APP_EVENT_POST_AUTHORIZE) { + // Track new facebook user, $GLOBAL['user'] not valid during post-authorize. + fb_user_app_track($fb, $fb_app); + } + elseif ($event_type == FB_APP_EVENT_POST_REMOVE) { + $fbu = fb_settings(FB_SETTINGS_FBU); + // User has removed the app from their account. + db_query("DELETE FROM {fb_user_app} WHERE apikey=:apikey AND fbu=:fbu", array( + ':apikey' => $fb_app->apikey, + ':fbu' => $fbu, + )); + } + } + elseif ($op == FB_OP_GET_USER_SESSION) { + + // The fb module is asking for session login information. For example, to + // log in as the user when not on a canvas page. This module may be able + // to provide it, depending on whether the user has logged in, and whether + // the session has expired. + $fbu = $data['fbu']; + $result = db_query("SELECT * FROM {fb_user_app} WHERE apikey = :apikey and fbu = :fbu", array( + ':apikey' => $fb_app->apikey, + ':fbu' => $fbu, + )); + $data = $result->fetchObject(); + + if ($data && $data->session_key) + // Return array with FB id and apikey. + $return = array( + 'fbu' => $data->fbu, + 'access_token' => $data->session_key, + 'expires' => $data->session_key_expires, + ); + } + elseif ($op == FB_OP_AJAX_EVENT) { // handle internal login + // @TODO - global user is not correct here. + + // fb.js has notified us of an event via AJAX. Not the same as facebook event callback above. + if ($data['event_type'] == 'session_change' && isset($data['event_data']['fbu'])) { + // A user has logged in. + fb_user_app_track($fb, $fb_app, $user); + } + } +} + +/** + * Implements hook_user_delete(). + * + * @TODO confirm there is no race condition between this module and fb_user. + * That is, during delete, does fb_get_fbu() still work? + */ +function fb_user_app_user_delete($account) { + // Given the uid, fetch the fbu so that we can delete + $fbu = fb_get_fbu($account->uid); + db_query('DELETE FROM {fb_user_app} WHERE fbu=:fbu', array( + ':fbu' => $fbu, + )); +} + +/** + * Keep track of when the user has visited the app, and whether they've + * authorized the app or not. + * + * Historically this supported infinite sessions. I believe if this data is + * no longer necessary for the offline access extended permission. + */ +function fb_user_app_track($fb, $fb_app) { + // Coming from a user adding the app or a page adding the app? + $fb_user_type = "user"; + $fbu = fb_facebook_user($fb); + if (array_key_exists('fb_sig_page_added', $_REQUEST)) { + // It's a post-authorize event for app added to page. + $fb_user_type = "page"; + $fbu = $_REQUEST['fb_sig_page_id']; + } + + + // test if we are tracking only those apps that have been granted offline + // access. Not sure what to do here ?? - NB + $fb_session = $fb->getAccessToken(); + + // when 'expires' == 0 app has been granted offline access + if ($fb_user_type == 'user' && + $fb_session["expires"] <> 0 && + variable_get(FB_USER_APP_VAR_USERS_THAT_GRANT_OFFLINE, FALSE)) + return; + + // Track this event only if allowed to and only for users, not pages + if ((variable_get(FB_USER_APP_VAR_TRACK_USERS, TRUE) && $fb_user_type = "user") || + (variable_get(FB_USER_APP_VAR_TRACK_PAGES, TRUE) && $fb_user_type = "page")) { + + $access_token = isset($fb_session['access_token']) ? $fb_session['access_token'] : ''; + $result1 = db_query("UPDATE {fb_user_app} SET time_access=:time, session_key=:token, session_key_expires=:expires, user_type=:type WHERE apikey=:apikey AND fbu=:fbu", array( + ':time' => REQUEST_TIME, + ':token' => $access_token, + ':expires' => $fb_session['expires'], + ':type' => $fb_user_type, + ':apikey' => $fb_app->apikey, + ':fbu' => fb_facebook_user($fb), + )); + + if ($result1 && $result1->rowCount() == 0) { + // The row for this user was never inserted, or it was deleted, or the times were the same. + $fbu = fb_facebook_user($fb); + if ($fbu) { + //First make sure it was not just the same time + $result = db_query("SELECT * FROM {fb_user_app} WHERE apikey=:apikey AND fbu=:fbu", array( + ':apikey' => $fb_app->apikey, + ':fbu' => $fbu, + )); + if (!$result->fetchObject()) { + //This row does not exist, even with the same time. Insert now + list($data) = fb_fql_query($fb, "SELECT name, is_app_user, email, proxied_email FROM user WHERE uid=$fbu", array('access_Token' => $fb_session_key)); + //watchdog('fb_user_app', "fb user data
" . print_r($data, 1) . ''); + $fb_user_type = "user"; + $result = db_query("INSERT INTO {fb_user_app} (apikey, fbu, added, user_type, session_key, session_key_expires, time_access, proxied_email, time_cron) VALUES (:apikey, :fbu, :added, :user_type, :session_key, :session_key_expires, :time_access, :proxied_email, :time_cron)", array( + ':apikey' => $fb_app->apikey, + ':fbu' => $fbu, + ':added' => $data['is_app_user'], + ':user_type' => $fb_user_type, + ':session_key' => $access_token, + ':session_key_expires' => $fb_session['expires'], + ':time_access' => REQUEST_TIME, + ':proxied_email' => $data['email'] ? $data['email'] : ($data['proxied_email'] ? $data['proxied_email'] : ''), // test accounts will not have + ':time_cron' => 0, + )); + } + } + } + if (FALSE && $result === FALSE) { // XXX upgrade to D7??? + watchdog('fb_user_app', "Failed to update fb_user_app table.", array(), WATCHDOG_ERROR); + } + } +} + +/** + * Learn the user's proxied email address. + * + */ +function fb_user_app_get_proxied_email($fbu, $fb_app) { + // Try to learn from local database + $result = db_query("SELECT * FROM {fb_user_app} WHERE apikey=:apikey AND fbu=:fbu", array( + ':apikey' => $fb_app->apikey, + ':fbu' => $fbu, + )); + if ($data = $result->fetchObject()) { + $mail = $data->proxied_email; + } + + if (!$mail) { + // Ask facebook for info. + $fb = fb_api_init($fb_app); + $info = fb_users_getInfo(array($fbu), $fb); + $data = $info[0]; + $mail = $data['proxied_email']; + if ($mail && variable_get(FB_USER_APP_VAR_TRACK_USERS, TRUE)) { + // Store locally. + $result = db_query("UPDATE {fb_user_app} SET proxied_email=:mail WHERE apikey=:apikey AND fbu=:fbu", array( + ':mail' => $mail, + ':apikey' => $fb_app->apikey, + ':fbu' => $fbu, + )); + } + } + return $mail; +} diff --git a/fb.info b/fb.info index 90fa394..e27240e 100644 --- a/fb.info +++ b/fb.info @@ -1,13 +1,19 @@ -name = Facebook API -description = (fb.module) Initializes facebook's PHP and Javascript client libraries. Enables FBML Like buttons and other social plugins. (See modules/fb/README.txt.) - -package = Drupal for Facebook -core = 7.x - -files[] = fb.module -files[] = fb.install -files[] = fb.admin.inc -files[] = fb.theme.inc -files[] = fb_url_rewrite.inc - -scripts[] = fb.js \ No newline at end of file +name = Facebook API +description = (fb.module) Initializes facebook's PHP and Javascript client libraries. Enables FBML Like buttons and other social plugins. (See modules/fb/README.txt.) + +package = Drupal for Facebook +core = 7.x + +files[] = fb.module +files[] = fb.install +files[] = fb.admin.inc +files[] = fb.theme.inc +files[] = fb_url_rewrite.inc + +scripts[] = fb.js +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/fb.module b/fb.module index b437bbf..49a8e19 100644 --- a/fb.module +++ b/fb.module @@ -1,1567 +1,1567 @@ - TRUE, - ))); - - // Data structure to pass to FB.init(); - $fb_init_settings = array( - 'xfbml' => FALSE, - 'status' => FALSE, - 'cookie' => variable_get(FB_VAR_USE_COOKIE, TRUE), - ); - - if ($_fb_app) { - // An App is configured. - - // Javascript settings needed by fb.js. - fb_js_settings('apikey', $_fb_app->apikey); - fb_js_settings('label', $_fb_app->label); - fb_js_settings('page_type', fb_settings(FB_SETTINGS_TYPE)); // canvas or connect. - $fb_init_settings['apiKey'] = $_fb_app->apikey; - $fb_init_settings['appId'] = $_fb_app->id; - - // Initialize the PHP API. - $_fb = fb_api_init($_fb_app); - - if ($_fb) { - - // Look for session info from several sources. - if ($session = $_fb->getSession()) { - // Learned session from cookie or signed request. - // Below, we store in our $_SESSION, just in case third-party cookies are not enabled. - } - elseif (isset($_REQUEST['fb_js_session'])) { - // Ajax callback via fb.js. - $_fb->setSession(json_decode($_REQUEST['fb_js_session'], TRUE)); - $session = $_fb->getSession(); - } - elseif (isset($_SESSION['fb'][$_fb_app->apikey]['session']) && arg(0) != 'logout') { - // Use the session previously stored. - $_fb->setSession($_SESSION['fb'][$_fb_app->apikey]['session']); - } - - // Store session for future use. We'll need it if third-party cookies - // disabled, or we are not using facebook's cookie. - if (isset($session) && variable_get(FB_VAR_USE_SESSION, TRUE)) { - $_SESSION['fb'][$_fb_app->apikey]['session'] = $session; - } - - // Make javascript work even when third-party cookies disabled. - $fb_init_settings['session'] = $_fb->getSession(); - - // Sometimes when canvas page is open in one tab, and user logs out of - // facebook in another, the canvas page has bogus session info when - // refreshed. Here we attempt to detect and cleanup. - if (isset($session) && ($request = $_fb->getSignedRequest())) { - if (!isset($request['user_id']) || - $request['user_id'] != $session['uid']) { - _fb_logout(); - $_fb->setSession(NULL); - unset($session); - unset($_SESSION['fb'][$_fb_app->apikey]); - unset($fb_init_settings['session']); - } - } - - // Give other modules a chance to initialize. - fb_invoke(FB_OP_INITIALIZE, array( - 'fb_app' => $_fb_app, - 'fb' => $_fb, - )); - - // See if the facebook user id is known - if ($fbs = $_fb->getSession()) { - fb_invoke(FB_OP_APP_IS_AUTHORIZED, array( - 'fb_app' => $_fb_app, - 'fb' => $_fb, - 'fbu' => $_fb->getUser(), - )); - fb_js_settings('fbu', $_fb->getUser()); - } - else { - // Add perms to settings, for calling FB.login(). - $perms = array(); - drupal_alter('fb_required_perms', $perms); - fb_js_settings('perms', implode(',', $perms)); - } - } - else - watchdog('fb', "URL indicates a facebook app, but could not initialize Facebook", array(), WATCHDOG_ERROR); - - if (isset($_REQUEST['destination'])) { - $destination = $_REQUEST['destination']; - } - elseif (current_path()) { - $destination = current_path(); - } - else { - $destination = '
' . $e . ''; - } - 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' => '
' . $exception->getTraceAsString() . '', - )); - watchdog('fb', $message, array(), WATCHDOG_ERROR); - //drupal_set_message($message, 'error'); - print $message; - - print "
\$_REQUEST:\n"; - print_r($_REQUEST); - print "\n\nREQUEST_URI:\n" . request_uri(); - print ""; - -} - -/** - * Simple wrapper around $fb->api() which caches data. Does not support the - * polymorphic arguments of $fb->api(). This is not a replacement for that - * function. - * - * This is intended to avoid performace problems when, for example, - * $fb->api('me') is called several times in a single request. - * - * @param $graph_path - * Something facebook's graph API will understand. Could be an ID or a path like 'me/accounts', for example. - * - * @param $params - * Extras to pass to the graph API. When making a request that requires a - * token, try array('access_token' => fb_get_token()). - */ -function fb_api($graph_path, $params = array()) { - static $cache; - $fb = $GLOBALS['_fb']; - if (!$fb) { - return; - } - if (!isset($cache)) { - $cache = array(); - } - if (!isset($cache[$graph_path])) { - $cache[$graph_path] = $fb->api($graph_path, $params); - } - return $cache[$graph_path]; -} - -/** - * DEPRECATED. Use fb_api() instead. - * Returns information about one or more facebook users. - * - * Historically, this helper function used facebook's users_getInfo API, hence - * the name. Now it uses fql.query, but accomplishes the same thing. - * - * @param $oids - * Array of facebook object IDs. In this case they should each be a user id. - * - * @param $fb - * Rarely needed. For cases when global $_fb is not set, or more than one - * facebook api has been initialized. - * - * @param $refresh_cache - * If true, force a call to facebook instead of relying on temporarily stored - * data. - */ -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) { - $app_id = $fb->getAppId(); - // First try cache - if (!$refresh_cache && isset($_SESSION['fb'])) { - foreach ($oids as $oid) { - if (isset($_SESSION['fb'][$app_id]['userinfo'][$oid])) { - $info = $_SESSION['fb'][$app_id]['userinfo'][$oid]; - $infos[] = $info; - } - } - } - if (count($infos) != count($oids)) { - // Session cache did not include all users, update the cache. - $fields = array( - 'about_me', - 'affiliations', - 'name', - 'is_app_user', - 'pic', - 'pic_big', - 'pic_square', - 'profile_update_time', - 'proxied_email', - 'status', - 'email_hashes', - 'email', - 'uid', - ); - try { - $infos = fb_fql_query($fb, 'SELECT ' . implode(', ', $fields) . ' FROM user WHERE uid in(' . implode(', ', $oids) . ')', array(fb_get_token($fb))); - // Update cache with recent results. - if (is_array($infos)) { - foreach ($infos as $info) { - $_SESSION['fb'][$app_id]['userinfo'][$info['uid']] = $info; - } - } - } catch (FacebookApiException $e) { - fb_log_exception($e, t('Failed to query facebook user info'), $fb); - } - } - - return $infos; - } -} - -/** - * For debugging, add $conf['fb_verbose'] = TRUE; to settings.php. - */ -function fb_verbose() { - return variable_get(FB_VAR_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. - * @TODO cache, because drupal doesn't, and calls this often. - */ -function fb_username_alter(&$name, $account) { - // This function can be called very early in the bootstrap process, before - // the modules are initialized, in which case we will fail to alter the - // name. - if ($GLOBALS['_fb'] && $fbu = fb_get_fbu($account)) { // @TODO - is fb_get_fbu() a performance hit here? - try { - // Use fql query instead of graph api, because it will succeed more often. - $data = fb_fql_query($GLOBALS['_fb'], "SELECT name FROM user WHERE uid=$fbu", array( - 'access_token' => fb_get_token($GLOBALS['_fb']), - )); - if (count($data) && isset($data[0]['name'])) { - $name = $data[0]['name']; - } - } - catch (Exception $e) { - fb_log_exception($e, t('Failed to alter username for facebook user %fbu', array( - '%fbu' => $fbu))); - } - } -} - -/** - * Implements hook_theme(). - * - * Returns description of theme functions. - * - * @see fb.theme.inc - */ -function fb_theme() { - return array( - 'fb_username' => array( - 'arguments' => array( - 'fbu' => NULL, - 'object' => NULL, - 'orig' => NULL, - ), - 'file' => 'fb.theme.inc', - ), - 'fb_user_picture' => array( - 'arguments' => array( - 'fbu' => NULL, - 'account' => NULL, - 'orig' => NULL, - ), - 'file' => 'fb.theme.inc', - ), - 'fb_fbml_popup' => array( - 'arguments' => array('elements' => NULL), - 'file' => 'fb.theme.inc', - ), - 'fb_login_button' => array( - 'arguments' => array( - 'text' => 'Connect with Facebook', - 'options' => NULL), - 'file' => 'fb.theme.inc', - ), - ); -} - -//// Javascript and Ajax helpers - -/** - * Ajax javascript callback. - * - * For sites which use ajax, various events may create javascript which is - * normally embedded in a page. For example, posting to a user's wall. When - * ajax is used instead of a page reload, this callback will provide any - * javascript which should be run. - */ -function fb_js_cb() { - $js_array = fb_invoke(FB_OP_JS, array('fb' => $GLOBALS['_fb'], 'fb_app' => $GLOBALS['_fb_app']), array()); - $extra_js = implode("\n", $extra); - print $extra_js; - exit(); -} - -/** - * Ajax callback handles an event from facebook's javascript sdk. - * - * @see - * fb.js and - * http://developers.facebook.com/docs/reference/javascript/FB.Event.subscribe - * - * @return - * Array of javascript to be evaluated by the page which called this - * callback. - */ -function fb_ajax_event($event_type) { - global $_fb, $_fb_app; - $js_array = array(); - - if (isset($_REQUEST['apikey'])) { - $_fb_app = fb_get_app(array('apikey' => $_REQUEST['apikey'])); - if ($_fb_app) { - $_fb = fb_api_init($_fb_app); - // Data to pass to hook_fb. - $data = array( - 'fb_app' => $_fb_app, - 'fb' => $_fb, - 'event_type' => $event_type, - 'event_data' => $_POST, // POSTed via ajax. - ); - - $js_array = fb_invoke(FB_OP_AJAX_EVENT, $data, array()); - - } - else { - watchdog('fb', 'fb_ajax_event did not find application %id', array('%id' => $_REQUEST['apikey']), WATCHDOG_ERROR); - } - - if ($event_type == 'session_change') { - // Session change is a special case. If user has logged out of - // facebook, we want a new drupal session. We do this here, even if - // fb_user.module is not enabled. - if (!isset($_POST['fbu']) || !$_POST['fbu']) { // Logout, not login. - _fb_logout(); - } - } - - } - else { - watchdog('fb', 'fb_ajax_event called badly. Not passed apikey.', array(), WATCHDOG_ERROR); - // Trying to track down what makes this happen. - if (fb_verbose() == 'extreme') { - watchdog('fb', 'fb_ajax_event called badly. Not passed apikey. trace: !trace', array( - '!trace' => '
' . print_r(debug_backtrace(), 1) . '', - ), WATCHDOG_ERROR); - } - } - drupal_json_output($js_array); - exit(); -} - -/** - * Menu callback for custom channel. - * - * @see http://developers.facebook.com/docs/reference/javascript/FB.init - */ -function fb_channel_page() { - //headers instructing browser to cache this page. - // Do these work? - drupal_add_http_header("Cache-Control", "public"); - drupal_add_http_header("Expires", "Sun, 17-Jan-2038 19:14:07 GMT"); - - $date = format_date(time()); - $output = "\n"; - $url = fb_js_settings('js_sdk_url'); - $output .= "\n"; - print $output; - exit(); -} - -//// Miscellaneous helpers and convenience functions. - -/** - * Protocol (http or https) of the current request. - */ -function fb_protocol() { - return (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http'; -} - - -/** - * Convenience wrapper around drupal_access_denied(). Call on pages where the - * access is denied because the user is not logged into facebook. - */ -function fb_access_denied() { - if (!fb_facebook_user()) { - drupal_set_message(t('You must log into facebook to view this page.')); - } - drupal_access_denied(); - exit(); -} - + TRUE, + ))); + + // Data structure to pass to FB.init(); + $fb_init_settings = array( + 'xfbml' => FALSE, + 'status' => FALSE, + 'cookie' => variable_get(FB_VAR_USE_COOKIE, TRUE), + ); + + if ($_fb_app) { + // An App is configured. + + // Javascript settings needed by fb.js. + fb_js_settings('apikey', $_fb_app->apikey); + fb_js_settings('label', $_fb_app->label); + fb_js_settings('page_type', fb_settings(FB_SETTINGS_TYPE)); // canvas or connect. + $fb_init_settings['apiKey'] = $_fb_app->apikey; + $fb_init_settings['appId'] = $_fb_app->id; + + // Initialize the PHP API. + $_fb = fb_api_init($_fb_app); + + if ($_fb) { + + // Look for session info from several sources. + if ($session = $_fb->getUser()) { + // Learned session from cookie or signed request. + // Below, we store in our $_SESSION, just in case third-party cookies are not enabled. + } + elseif (isset($_REQUEST['fb_js_session'])) { + // Ajax callback via fb.js. + $session = json_decode($_REQUEST['fb_js_session'], TRUE); + } + elseif (isset($_SESSION['fb'][$_fb_app->apikey]['session']) && arg(0) != 'logout') { + // Use the session previously stored. + $session = $_SESSION['fb'][$_fb_app->apikey]['session']; + } + + // Set access token for SDK version 3.0 + $_fb->setAccessToken($session['access_token']); + + // Store session for future use. We'll need it if third-party cookies + // disabled, or we are not using facebook's cookie. + if (isset($session) && variable_get(FB_VAR_USE_SESSION, TRUE)) { + $_SESSION['fb'][$_fb_app->apikey]['session'] = $session; + } + + // Make javascript work even when third-party cookies disabled. + $fb_init_settings['session'] = $session; + + // Sometimes when canvas page is open in one tab, and user logs out of + // facebook in another, the canvas page has bogus session info when + // refreshed. Here we attempt to detect and cleanup. + if (isset($session) && ($request = $_fb->getSignedRequest())) { + if (!isset($request['user_id']) || + $request['user_id'] != $session['uid']) { + _fb_logout(); + $_fb->setSession(NULL); + unset($session); + unset($_SESSION['fb'][$_fb_app->apikey]); + unset($fb_init_settings['session']); + } + } + + // Give other modules a chance to initialize. + fb_invoke(FB_OP_INITIALIZE, array( + 'fb_app' => $_fb_app, + 'fb' => $_fb, + )); + + // See if the facebook user id is known + if ($fbs = $session) { + fb_invoke(FB_OP_APP_IS_AUTHORIZED, array( + 'fb_app' => $_fb_app, + 'fb' => $_fb, + 'fbu' => $_fb->getUser(), + )); + fb_js_settings('fbu', $_fb->getUser()); + } + else { + // Add perms to settings, for calling FB.login(). + $perms = array(); + drupal_alter('fb_required_perms', $perms); + fb_js_settings('perms', implode(',', $perms)); + } + } + else + watchdog('fb', "URL indicates a facebook app, but could not initialize Facebook", array(), WATCHDOG_ERROR); + + if (isset($_REQUEST['destination'])) { + $destination = $_REQUEST['destination']; + } + elseif (current_path()) { + $destination = current_path(); + } + else { + $destination = '
' . $e . ''; + } + 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' => '
' . $exception->getTraceAsString() . '', + )); + watchdog('fb', $message, array(), WATCHDOG_ERROR); + //drupal_set_message($message, 'error'); + print $message; + + print "
\$_REQUEST:\n"; + print_r($_REQUEST); + print "\n\nREQUEST_URI:\n" . request_uri(); + print ""; + +} + +/** + * Simple wrapper around $fb->api() which caches data. Does not support the + * polymorphic arguments of $fb->api(). This is not a replacement for that + * function. + * + * This is intended to avoid performace problems when, for example, + * $fb->api('me') is called several times in a single request. + * + * @param $graph_path + * Something facebook's graph API will understand. Could be an ID or a path like 'me/accounts', for example. + * + * @param $params + * Extras to pass to the graph API. When making a request that requires a + * token, try array('access_token' => fb_get_token()). + */ +function fb_api($graph_path, $params = array()) { + static $cache; + $fb = $GLOBALS['_fb']; + if (!$fb) { + return; + } + if (!isset($cache)) { + $cache = array(); + } + if (!isset($cache[$graph_path])) { + $cache[$graph_path] = $fb->api($graph_path, $params); + } + return $cache[$graph_path]; +} + +/** + * DEPRECATED. Use fb_api() instead. + * Returns information about one or more facebook users. + * + * Historically, this helper function used facebook's users_getInfo API, hence + * the name. Now it uses fql.query, but accomplishes the same thing. + * + * @param $oids + * Array of facebook object IDs. In this case they should each be a user id. + * + * @param $fb + * Rarely needed. For cases when global $_fb is not set, or more than one + * facebook api has been initialized. + * + * @param $refresh_cache + * If true, force a call to facebook instead of relying on temporarily stored + * data. + */ +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) { + $app_id = $fb->getAppId(); + // First try cache + if (!$refresh_cache && isset($_SESSION['fb'])) { + foreach ($oids as $oid) { + if (isset($_SESSION['fb'][$app_id]['userinfo'][$oid])) { + $info = $_SESSION['fb'][$app_id]['userinfo'][$oid]; + $infos[] = $info; + } + } + } + if (count($infos) != count($oids)) { + // Session cache did not include all users, update the cache. + $fields = array( + 'about_me', + 'affiliations', + 'name', + 'is_app_user', + 'pic', + 'pic_big', + 'pic_square', + 'profile_update_time', + 'proxied_email', + 'status', + 'email_hashes', + 'email', + 'uid', + ); + try { + $infos = fb_fql_query($fb, 'SELECT ' . implode(', ', $fields) . ' FROM user WHERE uid in(' . implode(', ', $oids) . ')', array(fb_get_token($fb))); + // Update cache with recent results. + if (is_array($infos)) { + foreach ($infos as $info) { + $_SESSION['fb'][$app_id]['userinfo'][$info['uid']] = $info; + } + } + } catch (FacebookApiException $e) { + fb_log_exception($e, t('Failed to query facebook user info'), $fb); + } + } + + return $infos; + } +} + +/** + * For debugging, add $conf['fb_verbose'] = TRUE; to settings.php. + */ +function fb_verbose() { + return variable_get(FB_VAR_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. + * @TODO cache, because drupal doesn't, and calls this often. + */ +function fb_username_alter(&$name, $account) { + // This function can be called very early in the bootstrap process, before + // the modules are initialized, in which case we will fail to alter the + // name. + if ($GLOBALS['_fb'] && $fbu = fb_get_fbu($account)) { // @TODO - is fb_get_fbu() a performance hit here? + try { + // Use fql query instead of graph api, because it will succeed more often. + $data = fb_fql_query($GLOBALS['_fb'], "SELECT name FROM user WHERE uid=$fbu", array( + 'access_token' => fb_get_token($GLOBALS['_fb']), + )); + if (count($data) && isset($data[0]['name'])) { + $name = $data[0]['name']; + } + } + catch (Exception $e) { + fb_log_exception($e, t('Failed to alter username for facebook user %fbu', array( + '%fbu' => $fbu))); + } + } +} + +/** + * Implements hook_theme(). + * + * Returns description of theme functions. + * + * @see fb.theme.inc + */ +function fb_theme() { + return array( + 'fb_username' => array( + 'arguments' => array( + 'fbu' => NULL, + 'object' => NULL, + 'orig' => NULL, + ), + 'file' => 'fb.theme.inc', + ), + 'fb_user_picture' => array( + 'arguments' => array( + 'fbu' => NULL, + 'account' => NULL, + 'orig' => NULL, + ), + 'file' => 'fb.theme.inc', + ), + 'fb_fbml_popup' => array( + 'arguments' => array('elements' => NULL), + 'file' => 'fb.theme.inc', + ), + 'fb_login_button' => array( + 'arguments' => array( + 'text' => 'Connect with Facebook', + 'options' => NULL), + 'file' => 'fb.theme.inc', + ), + ); +} + +//// Javascript and Ajax helpers + +/** + * Ajax javascript callback. + * + * For sites which use ajax, various events may create javascript which is + * normally embedded in a page. For example, posting to a user's wall. When + * ajax is used instead of a page reload, this callback will provide any + * javascript which should be run. + */ +function fb_js_cb() { + $js_array = fb_invoke(FB_OP_JS, array('fb' => $GLOBALS['_fb'], 'fb_app' => $GLOBALS['_fb_app']), array()); + $extra_js = implode("\n", $extra); + print $extra_js; + exit(); +} + +/** + * Ajax callback handles an event from facebook's javascript sdk. + * + * @see + * fb.js and + * http://developers.facebook.com/docs/reference/javascript/FB.Event.subscribe + * + * @return + * Array of javascript to be evaluated by the page which called this + * callback. + */ +function fb_ajax_event($event_type) { + global $_fb, $_fb_app; + $js_array = array(); + + if (isset($_REQUEST['apikey'])) { + $_fb_app = fb_get_app(array('apikey' => $_REQUEST['apikey'])); + if ($_fb_app) { + $_fb = fb_api_init($_fb_app); + // Data to pass to hook_fb. + $data = array( + 'fb_app' => $_fb_app, + 'fb' => $_fb, + 'event_type' => $event_type, + 'event_data' => $_POST, // POSTed via ajax. + ); + + $js_array = fb_invoke(FB_OP_AJAX_EVENT, $data, array()); + + } + else { + watchdog('fb', 'fb_ajax_event did not find application %id', array('%id' => $_REQUEST['apikey']), WATCHDOG_ERROR); + } + + if ($event_type == 'session_change') { + // Session change is a special case. If user has logged out of + // facebook, we want a new drupal session. We do this here, even if + // fb_user.module is not enabled. + if (!isset($_POST['fbu']) || !$_POST['fbu']) { // Logout, not login. + _fb_logout(); + } + } + + } + else { + watchdog('fb', 'fb_ajax_event called badly. Not passed apikey.', array(), WATCHDOG_ERROR); + // Trying to track down what makes this happen. + if (fb_verbose() == 'extreme') { + watchdog('fb', 'fb_ajax_event called badly. Not passed apikey. trace: !trace', array( + '!trace' => '
' . print_r(debug_backtrace(), 1) . '', + ), WATCHDOG_ERROR); + } + } + drupal_json_output($js_array); + exit(); +} + +/** + * Menu callback for custom channel. + * + * @see http://developers.facebook.com/docs/reference/javascript/FB.init + */ +function fb_channel_page() { + //headers instructing browser to cache this page. + // Do these work? + drupal_add_http_header("Cache-Control", "public"); + drupal_add_http_header("Expires", "Sun, 17-Jan-2038 19:14:07 GMT"); + + $date = format_date(time()); + $output = "\n"; + $url = fb_js_settings('js_sdk_url'); + $output .= "\n"; + print $output; + exit(); +} + +//// Miscellaneous helpers and convenience functions. + +/** + * Protocol (http or https) of the current request. + */ +function fb_protocol() { + return (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http'; +} + + +/** + * Convenience wrapper around drupal_access_denied(). Call on pages where the + * access is denied because the user is not logged into facebook. + */ +function fb_access_denied() { + if (!fb_facebook_user()) { + drupal_set_message(t('You must log into facebook to view this page.')); + } + drupal_access_denied(); + exit(); +} + diff --git a/fb_app.info b/fb_app.info index dca0d2a..fa8b79b 100644 --- a/fb_app.info +++ b/fb_app.info @@ -1,10 +1,16 @@ -name = Facebook Apps -description = (fb_app.module) Host and administer Facebook apps. -package = Drupal for Facebook -core = 7.x - -dependencies[] = fb - -files[] = fb_app.module -files[] = fb_app.install -files[] = fb_app.admin.inc \ No newline at end of file +name = Facebook Apps +description = (fb_app.module) Host and administer Facebook apps. +package = Drupal for Facebook +core = 7.x + +dependencies[] = fb + +files[] = fb_app.module +files[] = fb_app.install +files[] = fb_app.admin.inc +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/fb_canvas.info b/fb_canvas.info index 1a5da5c..52d193f 100644 --- a/fb_canvas.info +++ b/fb_canvas.info @@ -1,12 +1,19 @@ -name = FB Canvas Pages -description = (fb_canvas.module) Host apps on facebook.com using iframe canvas pages. -package = Drupal for Facebook -core = 7.x - -dependencies[] = fb -dependencies[] = fb_app - -files[] = fb_canvas.module -files[] = fb_canvas.admin.inc -files[] = fb_url_rewrite.inc - +name = FB Canvas Pages +description = (fb_canvas.module) Host apps on facebook.com using iframe canvas pages. +package = Drupal for Facebook +core = 7.x + +dependencies[] = fb +dependencies[] = fb_app + +files[] = fb_canvas.module +files[] = fb_canvas.admin.inc +files[] = fb_url_rewrite.inc + + +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/fb_connect.info b/fb_connect.info index 632b6b1..91b7a27 100644 --- a/fb_connect.info +++ b/fb_connect.info @@ -1,11 +1,17 @@ -name = Facebook Connect -description = (fb_connect.module) Host Facebook Connect apps. Login buttons and FBML helpers that are useful on iframe canvas pages as well. -package = Drupal for Facebook -core = 7.x - -dependencies[] = fb -dependencies[] = fb_app - -files[] = fb_connect.admin.inc -files[] = fb_connect.install -files[] = fb_connect.module \ No newline at end of file +name = Facebook Connect +description = (fb_connect.module) Host Facebook Connect apps. Login buttons and FBML helpers that are useful on iframe canvas pages as well. +package = Drupal for Facebook +core = 7.x + +dependencies[] = fb +dependencies[] = fb_app + +files[] = fb_connect.admin.inc +files[] = fb_connect.install +files[] = fb_connect.module +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/fb_connect.module b/fb_connect.module index 27dbabb..01ffa77 100644 --- a/fb_connect.module +++ b/fb_connect.module @@ -1,457 +1,457 @@ - 'Facebook Connect', - 'description' => 'Configure Facebook Connect', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('fb_connect_admin_settings'), - 'access arguments' => array(FB_PERM_ADMINISTER), - 'file' => 'fb_connect.admin.inc', - 'type' => MENU_LOCAL_TASK, - ); - - - return $items; -} - - -/** - * Prepare for fbConnect use. Because a single Drupal might support - * multiple apps, we don't know in advance which is the fbConnect app. - */ -function fb_connect_app_init($fb_app) { - if (isset($GLOBALS['_fb_app']) && - $GLOBALS['_fb_app']->apikey != $fb_app->apikey) { - // If we're in an iframe, only support connect for the iframe app. - return; - } - - if ($fb = fb_api_init($fb_app)) { - $fbu = $fb->getUser(); - if ($fbu && - (!isset($GLOBALS['_fb_app']) || $GLOBALS['_fb_app']->apikey != $fb_app->apikey)) { - // The user has authorized the app and we now know something about them. Use a hook to trigger the actions of other modules. - fb_invoke(FB_OP_APP_IS_AUTHORIZED, array( - 'fbu' => $fbu, - 'fb_app' => $fb_app, - 'fb' => $fb)); - } - - // Remember which app we've initialized. - _fb_connect_set_app($fb_app); - _fb_connect_add_js($fb_app, $fb); - } - return $fb; -} - -/** - * Helper function for other modules to know page is connected. - * - * Note that this may return data on connect pages and in iframe apps - * (depending on how iframe is configured). - */ -function fb_connect_get_app() { - return _fb_connect_set_app(); -} -function _fb_connect_set_app($fb_app = NULL) { - $cache = &drupal_static(__FUNCTION__); - if (isset($fb_app)) { - $cache = $fb_app; - } - return $cache; -} - -/** - * Implements hook_fb(). - */ -function fb_connect_fb($op, $data, &$return) { - if ($op == FB_OP_CURRENT_APP && !$return && !fb_is_canvas()) { - // This will cause fb.module to set the global $_fb when user is logged in via fbConnect. - if ($apikey = variable_get(FB_VAR_APIKEY, NULL)) { - // Use $conf['fb_apikey'] if set in settings.php. - $return = fb_get_app(array('apikey' => $apikey)); - } - elseif ($label = variable_get(FB_CONNECT_VAR_PRIMARY, NULL)) { - $return = fb_get_app(array('label' => $label)); - } - } - elseif ($op == FB_OP_POST_INIT) { - if (!fb_is_tab()) { - // Init Facebook javascript for primary app - _fb_connect_add_js($data['fb_app'], $data['fb']); - } - - // Include our admin hooks. - if (fb_is_fb_admin_page()) { - module_load_include('inc', 'fb_connect', 'fb_connect.admin'); - } - } -} - -/** - * This wrapper function around drupal_add_js() ensures that our - * settings are added once and only once when needed. - * - */ -function _fb_connect_add_js($fb_app, $fb) { - $just_once = &drupal_static(__FUNCTION__); - - if (fb_is_tab()) - // Tabs are FBML. - return; - - if (!isset($just_once)) { - drupal_add_js(array( - 'fb_connect' => array( - 'front_url' => url('
Be sure to select a format that allows XFBML tags! (That is, use Full HTML or PHP code (PHP Filter module must be enabled), rather than Filtered HTML.)
", - '#weight' => -10, - ); - $form['config']['anon_not_connected']['#title'] = t('Anonymous user, not connected'); - $form['config']['anon_not_connected']['#description'] = t('Settings when local user is Anonymous, and not connected to Facebook. Typically a new account will be created when the user clicks the connect button.'); - $form['config']['anon_not_connected']['body']['#description'] = t('Suggestion: %default .', array('%default' => $orig_defaults['anon_not_connected']['body']['value'])); - - $form['config']['user_not_connected']['#title'] = t('Registered user, not connected'); - $form['config']['user_not_connected']['#description'] = t('Settings when local user is registered, and not connected to Facebook. Typically the facebook id will be linked to the local id after the user clicks the connect button.'); - $form['config']['user_not_connected']['body']['#description'] = t('Suggestion: %default .', array('%default' => $orig_defaults['user_not_connected']['body']['value'])); - $form['config']['connected']['#title'] = t('Connected user'); - $form['config']['connected']['#description'] = t('Settings when local user is connected to Facebook. You may render facebook\'s logout button, and/or information about the user. Consider using XFBML such as <fb:name uid=!fbu></fb:name> or <fb:profile-pic uid=!fbu></fb:profile-pic>', array('xfbml_url' => 'http://wiki.developers.facebook.com/index.php/XFBML')); - $form['config']['connected']['body']['#description'] .= t('Note that !fbu will be replaced with the user\'s facebook id.Be sure to select a format that allows XFBML tags! (That is, use Full HTML or PHP code (PHP Filter module must be enabled), rather than Filtered HTML.)
", + '#weight' => -10, + ); + $form['config']['anon_not_connected']['#title'] = t('Anonymous user, not connected'); + $form['config']['anon_not_connected']['#description'] = t('Settings when local user is Anonymous, and not connected to Facebook. Typically a new account will be created when the user clicks the connect button.'); + $form['config']['anon_not_connected']['body']['#description'] = t('Suggestion: %default .', array('%default' => $orig_defaults['anon_not_connected']['body']['value'])); + + $form['config']['user_not_connected']['#title'] = t('Registered user, not connected'); + $form['config']['user_not_connected']['#description'] = t('Settings when local user is registered, and not connected to Facebook. Typically the facebook id will be linked to the local id after the user clicks the connect button.'); + $form['config']['user_not_connected']['body']['#description'] = t('Suggestion: %default .', array('%default' => $orig_defaults['user_not_connected']['body']['value'])); + $form['config']['connected']['#title'] = t('Connected user'); + $form['config']['connected']['#description'] = t('Settings when local user is connected to Facebook. You may render facebook\'s logout button, and/or information about the user. Consider using XFBML such as <fb:name uid=!fbu></fb:name> or <fb:profile-pic uid=!fbu></fb:profile-pic>', array('xfbml_url' => 'http://wiki.developers.facebook.com/index.php/XFBML')); + $form['config']['connected']['body']['#description'] .= t('Note that !fbu will be replaced with the user\'s facebook id.' . print_r($data, 1); - $message .= print_r($_REQUEST, 1) . ''; - watchdog('fb_devel', $message); - } - - elseif ($op == FB_OP_JS) { - // Start debugger - //$return[] = "debugger; // added by fb_devel.module"; - } - - elseif ($op == FB_OP_POST_INIT) { - if (isset($_SESSION['fb_devel'])) { - // Counter helps track how long session has been around. - $_SESSION['fb_devel']['FB_OP_POST_INIT'] = $_SESSION['fb_devel']['FB_OP_POST_INIT'] + 1; - } - else { - $_SESSION['fb_devel']['FB_OP_POST_INIT'] = 1; - } - - // Javascript to help us with sanity checks. - drupal_add_js(array( - 'fb_devel' => array( - 'session_id' => session_id(), - 'session_name' => session_name(), - ), - ), 'setting'); - } - elseif ($op == FB_OP_AJAX_EVENT) { - if (fb_verbose() == 'extreme' && FALSE) { // disabled to prevent console not defined error. - $session_id = session_id(); - $session_name = session_name(); - $return[] = "console.log('fb_devel.module extreme verbosity: original session_id is ' + Drupal.settings.fb_devel.session_name + ':' + Drupal.settings.fb_devel.session_id + ', session_id during FB_OP_AJAX_EVENT is $session_name:$session_id');"; - $fbu = fb_facebook_user($data['fb']); - $return[] = "console.log('fb_facebook_user() during FB_OP_AJAX_EVENT is $fbu, data[event_data][fbu] is {$data[event_data][fbu]}');"; - $return[] = "console.log('_COOKIE[fbu_{$fb_app->apikey}] is " . $_COOKIE['fbu_' . $fb_app->apikey] . "');"; - $return[] = "FB_JS.reload();"; - } - } -} - -/** - * Provides a page with useful debug info. - * - * @TODO - clean this up and rely less on drupal_set_message() and dpm(). - */ -function fb_devel_page() { - global $_fb, $_fb_app; - global $user; - - if (isset($_REQUEST['require_login']) && $_REQUEST['require_login']) - fb_require_authorization($_fb); - - $items = array(); - - $items['fb_settings'] = fb_settings(); - - if ($_fb) { - - $items['$GLOBALS[_fb]'] = $_fb; - - // TODO: determine whether connect page or canvas. - - drupal_set_message(t("session name: " . session_name())); - drupal_set_message(t("cookie domain: " . fb_settings(FB_SETTINGS_COOKIE_DOMAIN))); - drupal_set_message(t("session id: " . session_id())); - if (isset($_COOKIE['fbs_' . $_fb_app->apikey])) - drupal_set_message(t("fbs_" . $_fb_app->apikey . ": " . $_COOKIE["fbs_" . $_fb_app->apikey])); - drupal_set_message(t("processed link, unprocessed", array('!url' => url('fb/devel')))); - drupal_set_message(t("getUser() returns " . $_fb->getUser())); - - drupal_set_message(t("base_url: " . $GLOBALS['base_url'])); - drupal_set_message(t("base_path: " . $GLOBALS['base_path'])); - drupal_set_message(t("url() returns: " . url())); - } - - if ($fbu = fb_get_fbu($user)) { - $path = "fb/devel/fbu/$fbu"; - drupal_set_message(t("Learn more about the current user at !link", - array('!link' => l($path, $path)))); - } - - dpm(fb_get_fbu($user), 'Facebook user via fb_get_fbu'); - //dpm($user, "Local user " . theme('username', $user)); - - if (isset($GLOBALS['fb_connect_apikey'])) { - drupal_set_message(t("fb_connect_apikey = " . $GLOBALS['fb_connect_apikey'])); - } - - dpm(fb_settings(), 'fb_settings()'); - dpm($_COOKIE, 'cookie'); - dpm($_REQUEST, "Request"); - //dpm($_fb_app, "fb_app"); - drupal_set_message(t("session_id returns " . session_id())); - dpm($_SESSION, "session:"); - - foreach ($items as $key => $val) { - if (is_array($val) || is_object($val)) { - $markup = print_r($val, 1); - } - else { - $markup = $val; - } - $out[$key] = array( - '#prefix' => "
", - '#suffix' => "
fb_devel.module tab
'; - foreach ($info as $key => $value) { - print "$key:\n"; - if (is_array($value)) { - print '
' . check_plain(print_r($value, 1)) . ''; - } - elseif (is_object($value)) { - print '
' . check_plain(print_r($value, 1)) . ''; - } - else { - print '
' . $value . ''; - } - print "\n\n\n"; - } - - exit(); -} - -/** - * A page which tests function which work with facebook user ids - */ -function fb_devel_fbu_page($fbu = NULL) { - global $_fb, $_fb_app; - if ($fbu) { - $info = $_fb->api($fbu, array('metadata' => 1)); - $output = "
Debug info about facebook id $fbu ({$info[name]}):
\n"; - $output .= ""; - $output .= "" . print_r($info, 1) . ""; - - foreach (array('statuses') as $connection) { - try { - if ($data = $_fb->api($fbu . '/' . $connection)) { - $output .= "
$connection
"; - $output .= print_r($data, 1); - $output .= "\n\n"; - } - } - catch (FacebookApiException $e) { - fb_log_exception($e, t('Failed to lookup %connection', array('%connection' => $fbu . '/' . $connection))); - } - } - try { - $friends = $_fb->api($fbu . '/friends'); - //dpm($friends, "$fbu/friends returned"); - $items = array(); - foreach ($friends['data'] as $data) { - $items[] = l($data['name'], "fb/devel/fbu/{$data[id]}"); - } - if (count($items)) { - $output .= "\n
Known friends:
Local friends:
'; - - $data .= "session_name() = " . session_name() . "\n"; - $data .= "session_id() = " . session_id() . "\n"; - $data .= "REQUEST: " . dprint_r($_REQUEST, 1) . "\n"; - $data .= "SESSION: " . dprint_r($_SESSION, 1) . "\n"; - $data .= ''; - - print drupal_json_output(array('status' => TRUE, 'data' => $data)); - exit(); -} - -function fb_devel_block_info() { - // Provide two copies of same block, for iframe scenarios. - $items[0]['info'] = t('Facebook Devel Page Info'); - $items[1]['info'] = t('Facebook Devel Page Info 2'); - return $items; -} - -function fb_devel_block_view($delta = '') { - if (user_access('access devel information')) { - return array( - 'subject' => t('Facebook Devel Info'), - 'content' => drupal_get_form('fb_devel_info'), - ); - } -} - -function fb_devel_info() { - global $_fb, $_fb_app; - global $user; - global $base_url; - global $base_path; - - $info = array(); - - if ($_fb) { - if (fb_settings(FB_SETTINGS_TYPE) == FB_SETTINGS_TYPE_CANVAS) { - $info['Page Status'] = t('Serving canvas page.'); - } - elseif (fb_settings(FB_SETTINGS_TYPE) == FB_SETTINGS_TYPE_CONNECT) { - $info['Page Status'] = t('Connected via Facebook Connect'); - } - elseif (fb_settings(FB_SETTINGS_TYPE) == FB_SETTINGS_TYPE_PROFILE) { - $info['Page Status'] = t('Serving deprecated FBML profile tab'); - } - elseif (fb_settings(FB_SETTINGS_TYPE) == FB_SETTINGS_TYPE_PAGE_TAB) { - $info['Page Status'] = t('Iframe tab on page %page', array( - '%page' => fb_settings(FB_SETTINGS_PAGE_ID), - )); - } - elseif (!fb_settings(FB_SETTINGS_TYPE)) { - $info['Page Status'] = t('Facebook PHP SDK initialized.'); // Either a facebook connect page, or canvas page where user has not authorized app. - } - else { - $info['Page Status'] = t('Global fb instance is set, but page type unknown (%type).', - array('%type' => fb_settings(FB_SETTINGS_TYPE), - )); - } - $fbu = fb_facebook_user(); - $info['fb_facebook_user'] = $fbu; - - if (!$fbu) { - $info['login button'] = theme('fb_login_button', array('text' => 'Connect')); - $info['login link'] = "fb login"; - } - - // Tests for link on canvas pages (iframe cookie test) - //$link_test = url(fb_scrub_urls($_REQUEST['q']), array('absolute' => TRUE)); - //$info['link test'] = "link test (processed)"; - //$info['link test 2'] = "link test (not processed)"; - - if ($fbu && FALSE) { // Disabled as this expensive check can cause problems. - if (!fb_api_check_session($_fb)) { - $info['fb_api_check_session()'] = t('Returned FALSE'); - } - else { - $info['fb_api_check_session()'] = t('Returned TRUE'); - } - } - } - else { - $info['Page Status'] = t('Not a canvas page.'); - } - // Use theme_username() rather than theme('username') because we want link to local user, even when FBML is enabled - if ($user->uid) { - $name = $user->name; - } - else { - $name = "anonymous"; - } - $info['local user'] = theme_username(array('account' => $user, - 'attributes_array' => array(), - 'name' => $name, - 'extra' => '')); - $info['fb_get_fbu'] = fb_get_fbu($user->uid); - $info['base_url'] = $base_url; - $info['base_path'] = $base_path; - $info['url() returns'] = url(); - $info['current_path'] = current_path(); - $info['arg(0) is'] = arg(0); - $info['arg(1) is'] = arg(1); - $info['session_id'] = session_id(); - $info['session_name'] = session_name(); - $info['fbsettings(FB_SETTINGS_COOKIE_DOMAIN)'] = fb_settings(FB_SETTINGS_COOKIE_DOMAIN); - - $info['request'] = $_REQUEST; - $info['user'] = $GLOBALS['user']; - $info['fb_app'] = $_fb_app; - $info['session'] = $_SESSION; - $info['cookies'] = $_COOKIE; - - - if ($_fb) { - $info['signed_request'] = $_fb->getSignedRequest(); - try { - // app properties - $token = fb_get_token($_fb); - $props = $_fb->api(array( - 'method' => 'admin.getAppProperties', - 'properties' => 'about_url', 'application_name', - 'access_token' => $token, - )); - $info['application properties'] = $props; - - } - catch (FacebookApiException $e) { - fb_log_exception($e, "failed to get app properties"); - } - $info["fb->getSession()"] = $_fb->getSession(); - $info["fb->getSignedRequest()"] = $_fb->getSignedRequest(); - if ($fbu) { - try { - $info["fb->api($fbu)"] = $_fb->api($fbu, array( - 'access_token' => fb_get_token($_fb), - )); - } - catch (FacebookApiException $e) { - fb_log_exception($e, "failed to look up _fb->api($fbu)"); - } - } - } - - $form = array(); - foreach ($info as $key => $val) { - if (is_string($val) || is_numeric($val) || !$val) { - $form[$key] = array('#markup' => t($key) . ' = ' . $val, - '#weight' => count($form), - '#suffix' => '
' . print_r($data, 1) . '', - ))); - } - } -} - - -function fb_devel_fb_tab($op, $data, &$return) { - // debug. - if (fb_verbose() === 'extreme') { - $return['fb_devel'] = array( - '#type' => 'markup', - '#markup' => __FUNCTION__ . ':' . print_r($data, 1), - '#prefix' => '
', - '#suffix' => '', - '#weight' => 99, - ); - if ($data['profile_id'] && isset($data['fb'])) { - $return['fb_devel']['profile_id'] = array( - '#type' => 'markup', - '#markup' => __FUNCTION__ . ':' . print_r($data['fb']->api($data['profile_id']), 1), - '#prefix' => '
', - '#suffix' => '', - '#weight' => 99, - ); - } - } -} - - -/** - * Wrapper for fb_fql_query(). Useful for debugging. - */ -function fb_devel_fql_query($fb, $query, $params = array()) { - if (!is_object($fb)) { - dpm(debug_backtrace(), __FUNCTION__); - return; - } - $url_params = $params; - $url_params['query'] = $query; - $url_params['format'] = 'JSON'; - $url = url("https://api.facebook.com/method/fql.query", array('query' => $url_params)); - dpm(func_get_args(), __FUNCTION__); - drupal_set_message(l($url, $url)); - return fb_fql_query($fb, $query, $params); -} + 'fb_devel_page', + 'type' => MENU_CALLBACK, + 'access callback' => TRUE, /* TODO: restrict access */ + ); + + $items['fb/devel/fbu'] = array( + 'page callback' => 'fb_devel_fbu_page', + 'type' => MENU_CALLBACK, + 'access callback' => TRUE, + ); + + $items['fb/devel/tab'] = array( + 'page callback' => 'fb_devel_tab', + 'type' => MENU_CALLBACK, + 'access callback' => TRUE, /* TODO: restrict access */ + ); + + // Return some info for debugging AHAH problems + $items['fb/devel/js'] = array( + 'page callback' => 'fb_devel_js', + 'type' => MENU_CALLBACK, + 'access callback' => TRUE, + ); + + $items['fb/devel/linter'] = array( + 'title' => 'Facebook linter', + 'page callback' => 'drupal_not_found', // Because we alter link, below. + 'type' => MENU_NORMAL_ITEM, + 'access arguments' => array('access devel information'), + 'menu_name' => 'devel', + 'options' => array('alter' => TRUE), + ); + + return $items; +} + +// Trick learned from devel.module, to make link to linter for the current page. +function fb_devel_translated_menu_link_alter(&$item) { + if ($item['link_path'] == 'fb/devel/linter' || + $item['link_path'] == FB_DEVEL_URL_LINTER) { + //dpm($item, __FUNCTION__); + $item['href'] = FB_DEVEL_URL_LINTER; // href matters. link_path and router path do not. + $item['localized_options']['query'] = array( + 'url' => url(request_path(), array('absolute' => TRUE)), + ); + } +} + +/** + * Implements hook_init(). + */ +function fb_devel_init() { + if (user_access('access devel information')) { + // Add our module's javascript. + drupal_add_js(drupal_get_path('module', 'fb_devel') . '/fb_devel.js'); + } + + // fb_settings.inc sanity check. + if (isset($GLOBALS['fb_init_no_settings'])) { + if (user_access('access administration pages') && (module_exists('fb_canvas') || module_exists('fb_tab'))) { + // fb_settings.php must be included for canvas or tab support. + drupal_set_message(t('!drupal_for_facebook (fb_canvas.module) has been enabled, but fb_settings.inc is not included in settings.php. 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' => 'README.txt')), 'error'); + } + } + + + + // $conf['fb_apikey'] sanity check + if ($apikey = variable_get(FB_VAR_APIKEY, NULL)) { + $fb_app = fb_get_app(array('apikey' => $apikey)); + $message = t('Drupal for Facebook no longer uses the \'fb_apikey\' variable. Change $conf[\'fb_apikey\'] in your settings.php. Use $conf[\'fb_id\'] instead, and make the value the app id (%app_id) instead of the apikey.', array( + '%app_id' => $fb_app->id, + )); + if (user_access(FB_PERM_ADMINISTER)) { + drupal_set_message($message, 'error'); + } + watchdog('fb_devel', $message, array(), WATCHDOG_WARNING); + } + + // $conf['fb_id'] sanity check + if ($id = variable_get(FB_VAR_ID, NULL)) { + if ($label = variable_get(FB_CONNECT_VAR_PRIMARY, NULL)) { + $fb_app = fb_get_app(array('label' => $label)); + if ($fb_app && ($fb_app->id != $id)) { + $message = t('Drupal for Facebook has detected a problem. $conf[\'fb_id\'] (%fb_id) is not the same as the primary application %label (%fb_primary_id).', + array( + '%fb_id' => $id, + '%fb_primary_id' => $fb_app->id, + '%label' => $fb_app->label, + )); + if (user_access(FB_PERM_ADMINISTER)) { + drupal_set_message($message, 'error'); + } + watchdog('fb_devel', $message, array(), WATCHDOG_WARNING); + } + } + } + + // fb_user table sanity check + if (module_exists('fb_user')) { + if (db_query("SELECT count(*) FROM {authmap} WHERE module='fb_user'")->fetchField()) { + $message = 'fb_user data has not been migrated from authmap table. Run update.php.'; + $args = array(); + if (user_access('access administration pages')) { + drupal_set_message(t($message, $args), 'error'); + } + watchdog('fb_devel', $message, $args, WATCHDOG_ERROR); + } + } + + // Old url rewrite sanity check. + if ($id = fb_settings(FB_SETTINGS_CB)) { + if ($GLOBALS['_fb_app']->apikey == $id) { + $message = t('Facebook callback URLs have changed. They now include the app\'s ID, instead of APIKEY. Your application %label has not been updated. Either sync properties or manually change callbacks on remote settings.', array( + '%label' => $GLOBALS['_fb_app']->title, + '!sync_url' => url(FB_PATH_ADMIN_APPS . '/' . $GLOBALS['_fb_app']->label . '/fb/set_props', array( + 'fb_url_alter' => FALSE, + )), + )); + if (user_access('access administration pages')) { + drupal_set_message(t($message, $args), 'warning'); + } + watchdog('fb_devel', $message, $args, WATCHDOG_WARNING); + } + } +} + +/** + * Implements hook_fb(). + */ +function fb_devel_fb($op, $data, &$return) { + $fb_app = isset($data['fb_app']) ? $data['fb_app'] : NULL; + $fb = isset($data['fb']) ? $data['fb'] : NULL; + $errors = 0; + + if ($op == FB_OP_INITIALIZE) { + + if (fb_settings(FB_SETTINGS_APIKEY) && + ($fb_app->apikey != fb_settings(FB_SETTINGS_APIKEY))) { + $message = t('Drupal for Facebook has detected a problem. The initialized app has an apikey (%fb_app_apikey), while the settings indicates a different apikey (%fb_settings_apikey).', array( + '%fb_app_apikey' => $fb_app->apikey, + '%fb_settings_apikey' => fb_settings(FB_SETTINGS_APIKEY), + )); + drupal_set_message($message, 'error'); + watchdog('fb_devel', $message, array(), WATCHDOG_WARNING); + $errors++; + } + + // This value comes from url rewriting. Recommended on canvas pages. + $id = fb_settings(FB_SETTINGS_CB); + + // Sanity check. + if ($id && $id != $fb_app->id) { + $message = t('fb_app id (%fb_app_id) does not equal fb settings id (%fb_settings_id). This is usually caused by the wrong callback url on your facebook application settings form.', + array('%fb_app_id' => $fb_app->id, + '%fb_settings_id' => $id, + '!url' => "http://www.facebook.com/developers/apps.php", + )); + drupal_set_message($message, 'warning'); + watchdog('fb_devel', $message, array(), WATCHDOG_WARNING); + $errors++; + } + + // Catch badly formed links ASAP. + if ($id && !fb_is_canvas() && !fb_is_tab()) { + // Skip check on callbacks from facebook. + if ((arg(0) != 'fb_app') || (arg(1) != 'event')) { + $message = t('URL starts with %prefix. This should never happen on connect pages. Did the previous page have a badly formed link?', array( + '%prefix' => FB_SETTINGS_CB . '/' . $id, + )); + drupal_set_message($message, 'error'); + $errors++; + } + } + + // path replacement sanity check + global $base_path; + if ($base_path == "/{$fb_app->canvas}/") { + $message = t('Facebook canvas page matches Drupal base_path (%base_path). This is currently not supported.', + array('%base_path' => $base_path)); + drupal_set_message($message, 'error'); + watchdog('fb_devel', $message); + } + + // Old API Sanity check. + if (isset($_REQUEST['fb_sig'])) { + $message = t('Passed old-style fb_sig parameters. Go to !url, edit your application. Under "migrations" enable "new sdks".', array( + '!url' => 'http://www.facebook.com/developers/apps.php', + )); + dpm($message); + watchdog('fb_devel', $message); + } + + // server URL sanity check + // This is an expensive test, because it invokes api_client. + try { + $props = $fb->api(array( + 'method' => 'admin.getAppProperties', + 'access_token' => fb_get_token($fb), + 'properties' => array('connect_url', 'callback_url'), + )); + $props = json_decode($props, TRUE); + if (is_array($props)) { + foreach ($props as $prop => $url) { + if ($url && (strpos($url, $GLOBALS['base_url']) === FALSE)) { + $message = t('The Facebook Application labeled %label has a suspicious %prop. The value is %value, while something starting with %url was expected. Consider editing !applink.', array( + '%label' => $fb_app->label, + '%prop' => $prop, + '%value' => $url, + '%url' => $GLOBALS['base_url'], + '!applink' => l($fb_app->label, FB_PATH_ADMIN_APPS . '/' . $fb_app->label), + )); + + if (user_access('access administration pages')) { + drupal_set_message($message, 'warning'); + } + watchdog('fb_devel', $message); + } + } + } + } + catch (Exception $e) { + dpm($e, __FUNCTION__); + if ($e->getCode() == 102) { + // Session key invalid or no longer valid 102, which we can ignore. + } + else { + fb_log_exception($e, t('Failed to get app properties for %name.', array('%name' => $fb_app->title))); + } + } + + // App data sanity checks. + $fb_app_data = fb_get_app_data($fb_app); + + // Account mapping format has changed! + if (isset($fb_app_data['fb_user']) && !is_array($fb_app_data['fb_user']['map_account'])) { + $message = 'The options for mapping facebook account to local accounts has changed. You must manually edit your application. Look for the map accounts options under facebook user settings.'; + $args = array('!url' => url(FB_PATH_ADMIN_APPS . '/' . $fb_app->label)); + if (user_access('access administration pages')) { + drupal_set_message(t($message, $args), 'error'); + } + watchdog('fb_devel', $message, $args, WATCHDOG_ERROR); + } + + } + + elseif ($op == FB_APP_OP_EVENT) { + $type = $data['event_type']; + // Facebook has notified us of some event. + $message = t('Facebook has notified the %label application of a %type event.', + array('%label' => $fb_app->label, + '%type' => $type)); + $message .= '
' . print_r($data, 1); + $message .= print_r($_REQUEST, 1) . ''; + watchdog('fb_devel', $message); + } + + elseif ($op == FB_OP_JS) { + // Start debugger + //$return[] = "debugger; // added by fb_devel.module"; + } + + elseif ($op == FB_OP_POST_INIT) { + if (isset($_SESSION['fb_devel'])) { + // Counter helps track how long session has been around. + $_SESSION['fb_devel']['FB_OP_POST_INIT'] = $_SESSION['fb_devel']['FB_OP_POST_INIT'] + 1; + } + else { + $_SESSION['fb_devel']['FB_OP_POST_INIT'] = 1; + } + + // Javascript to help us with sanity checks. + drupal_add_js(array( + 'fb_devel' => array( + 'session_id' => session_id(), + 'session_name' => session_name(), + ), + ), 'setting'); + } + elseif ($op == FB_OP_AJAX_EVENT) { + if (fb_verbose() == 'extreme' && FALSE) { // disabled to prevent console not defined error. + $session_id = session_id(); + $session_name = session_name(); + $return[] = "console.log('fb_devel.module extreme verbosity: original session_id is ' + Drupal.settings.fb_devel.session_name + ':' + Drupal.settings.fb_devel.session_id + ', session_id during FB_OP_AJAX_EVENT is $session_name:$session_id');"; + $fbu = fb_facebook_user($data['fb']); + $return[] = "console.log('fb_facebook_user() during FB_OP_AJAX_EVENT is $fbu, data[event_data][fbu] is {$data[event_data][fbu]}');"; + $return[] = "console.log('_COOKIE[fbu_{$fb_app->apikey}] is " . $_COOKIE['fbu_' . $fb_app->apikey] . "');"; + $return[] = "FB_JS.reload();"; + } + } +} + +/** + * Provides a page with useful debug info. + * + * @TODO - clean this up and rely less on drupal_set_message() and dpm(). + */ +function fb_devel_page() { + global $_fb, $_fb_app; + global $user; + + if (isset($_REQUEST['require_login']) && $_REQUEST['require_login']) + fb_require_authorization($_fb); + + $items = array(); + + $items['fb_settings'] = fb_settings(); + + if ($_fb) { + + $items['$GLOBALS[_fb]'] = $_fb; + + // TODO: determine whether connect page or canvas. + + drupal_set_message(t("session name: " . session_name())); + drupal_set_message(t("cookie domain: " . fb_settings(FB_SETTINGS_COOKIE_DOMAIN))); + drupal_set_message(t("session id: " . session_id())); + if (isset($_COOKIE['fbs_' . $_fb_app->apikey])) + drupal_set_message(t("fbs_" . $_fb_app->apikey . ": " . $_COOKIE["fbs_" . $_fb_app->apikey])); + drupal_set_message(t("processed link, unprocessed", array('!url' => url('fb/devel')))); + drupal_set_message(t("getUser() returns " . $_fb->getUser())); + + drupal_set_message(t("base_url: " . $GLOBALS['base_url'])); + drupal_set_message(t("base_path: " . $GLOBALS['base_path'])); + drupal_set_message(t("url() returns: " . url())); + } + + if ($fbu = fb_get_fbu($user)) { + $path = "fb/devel/fbu/$fbu"; + drupal_set_message(t("Learn more about the current user at !link", + array('!link' => l($path, $path)))); + } + + dpm(fb_get_fbu($user), 'Facebook user via fb_get_fbu'); + //dpm($user, "Local user " . theme('username', $user)); + + if (isset($GLOBALS['fb_connect_apikey'])) { + drupal_set_message(t("fb_connect_apikey = " . $GLOBALS['fb_connect_apikey'])); + } + + dpm(fb_settings(), 'fb_settings()'); + dpm($_COOKIE, 'cookie'); + dpm($_REQUEST, "Request"); + //dpm($_fb_app, "fb_app"); + drupal_set_message(t("session_id returns " . session_id())); + dpm($_SESSION, "session:"); + + foreach ($items as $key => $val) { + if (is_array($val) || is_object($val)) { + $markup = print_r($val, 1); + } + else { + $markup = $val; + } + $out[$key] = array( + '#prefix' => "
", + '#suffix' => "
fb_devel.module tab
'; + foreach ($info as $key => $value) { + print "$key:\n"; + if (is_array($value)) { + print '
' . check_plain(print_r($value, 1)) . ''; + } + elseif (is_object($value)) { + print '
' . check_plain(print_r($value, 1)) . ''; + } + else { + print '
' . $value . ''; + } + print "\n\n\n"; + } + + exit(); +} + +/** + * A page which tests function which work with facebook user ids + */ +function fb_devel_fbu_page($fbu = NULL) { + global $_fb, $_fb_app; + if ($fbu) { + $info = $_fb->api($fbu, array('metadata' => 1)); + $output = "
Debug info about facebook id $fbu ({$info[name]}):
\n"; + $output .= ""; + $output .= "" . print_r($info, 1) . ""; + + foreach (array('statuses') as $connection) { + try { + if ($data = $_fb->api($fbu . '/' . $connection)) { + $output .= "
$connection
"; + $output .= print_r($data, 1); + $output .= "\n\n"; + } + } + catch (FacebookApiException $e) { + fb_log_exception($e, t('Failed to lookup %connection', array('%connection' => $fbu . '/' . $connection))); + } + } + try { + $friends = $_fb->api($fbu . '/friends'); + //dpm($friends, "$fbu/friends returned"); + $items = array(); + foreach ($friends['data'] as $data) { + $items[] = l($data['name'], "fb/devel/fbu/{$data[id]}"); + } + if (count($items)) { + $output .= "\n
Known friends:
Local friends:
'; + + $data .= "session_name() = " . session_name() . "\n"; + $data .= "session_id() = " . session_id() . "\n"; + $data .= "REQUEST: " . dprint_r($_REQUEST, 1) . "\n"; + $data .= "SESSION: " . dprint_r($_SESSION, 1) . "\n"; + $data .= ''; + + print drupal_json_output(array('status' => TRUE, 'data' => $data)); + exit(); +} + +function fb_devel_block_info() { + // Provide two copies of same block, for iframe scenarios. + $items[0]['info'] = t('Facebook Devel Page Info'); + $items[1]['info'] = t('Facebook Devel Page Info 2'); + return $items; +} + +function fb_devel_block_view($delta = '') { + if (user_access('access devel information')) { + return array( + 'subject' => t('Facebook Devel Info'), + 'content' => drupal_get_form('fb_devel_info'), + ); + } +} + +function fb_devel_info() { + global $_fb, $_fb_app; + global $user; + global $base_url; + global $base_path; + + $info = array(); + + if ($_fb) { + if (fb_settings(FB_SETTINGS_TYPE) == FB_SETTINGS_TYPE_CANVAS) { + $info['Page Status'] = t('Serving canvas page.'); + } + elseif (fb_settings(FB_SETTINGS_TYPE) == FB_SETTINGS_TYPE_CONNECT) { + $info['Page Status'] = t('Connected via Facebook Connect'); + } + elseif (fb_settings(FB_SETTINGS_TYPE) == FB_SETTINGS_TYPE_PROFILE) { + $info['Page Status'] = t('Serving deprecated FBML profile tab'); + } + elseif (fb_settings(FB_SETTINGS_TYPE) == FB_SETTINGS_TYPE_PAGE_TAB) { + $info['Page Status'] = t('Iframe tab on page %page', array( + '%page' => fb_settings(FB_SETTINGS_PAGE_ID), + )); + } + elseif (!fb_settings(FB_SETTINGS_TYPE)) { + $info['Page Status'] = t('Facebook PHP SDK initialized.'); // Either a facebook connect page, or canvas page where user has not authorized app. + } + else { + $info['Page Status'] = t('Global fb instance is set, but page type unknown (%type).', + array('%type' => fb_settings(FB_SETTINGS_TYPE), + )); + } + $fbu = fb_facebook_user(); + $info['fb_facebook_user'] = $fbu; + + if (!$fbu) { + $info['login button'] = theme('fb_login_button', array('text' => 'Connect')); + $info['login link'] = "fb login"; + } + + // Tests for link on canvas pages (iframe cookie test) + //$link_test = url(fb_scrub_urls($_REQUEST['q']), array('absolute' => TRUE)); + //$info['link test'] = "link test (processed)"; + //$info['link test 2'] = "link test (not processed)"; + + if ($fbu && FALSE) { // Disabled as this expensive check can cause problems. + if (!fb_api_check_session($_fb)) { + $info['fb_api_check_session()'] = t('Returned FALSE'); + } + else { + $info['fb_api_check_session()'] = t('Returned TRUE'); + } + } + } + else { + $info['Page Status'] = t('Not a canvas page.'); + } + // Use theme_username() rather than theme('username') because we want link to local user, even when FBML is enabled + if ($user->uid) { + $name = $user->name; + } + else { + $name = "anonymous"; + } + $info['local user'] = theme_username(array('account' => $user, + 'attributes_array' => array(), + 'name' => $name, + 'extra' => '')); + $info['fb_get_fbu'] = fb_get_fbu($user->uid); + $info['base_url'] = $base_url; + $info['base_path'] = $base_path; + $info['url() returns'] = url(); + $info['current_path'] = current_path(); + $info['arg(0) is'] = arg(0); + $info['arg(1) is'] = arg(1); + $info['session_id'] = session_id(); + $info['session_name'] = session_name(); + $info['fbsettings(FB_SETTINGS_COOKIE_DOMAIN)'] = fb_settings(FB_SETTINGS_COOKIE_DOMAIN); + + $info['request'] = $_REQUEST; + $info['user'] = $GLOBALS['user']; + $info['fb_app'] = $_fb_app; + $info['session'] = $_SESSION; + $info['cookies'] = $_COOKIE; + + + if ($_fb) { + $info['signed_request'] = $_fb->getSignedRequest(); + try { + // app properties + $token = fb_get_token($_fb); + $props = $_fb->api(array( + 'method' => 'admin.getAppProperties', + 'properties' => 'about_url', 'application_name', + 'access_token' => $token, + )); + $info['application properties'] = $props; + + } + catch (FacebookApiException $e) { + fb_log_exception($e, "failed to get app properties"); + } + $info["fb->getUser()"] = $_fb->getUser(); + $info["fb->getSignedRequest()"] = $_fb->getSignedRequest(); + if ($fbu) { + try { + $info["fb->api($fbu)"] = $_fb->api($fbu, array( + 'access_token' => fb_get_token($_fb), + )); + } + catch (FacebookApiException $e) { + fb_log_exception($e, "failed to look up _fb->api($fbu)"); + } + } + } + + $form = array(); + foreach ($info as $key => $val) { + if (is_string($val) || is_numeric($val) || !$val) { + $form[$key] = array('#markup' => t($key) . ' = ' . $val, + '#weight' => count($form), + '#suffix' => '
' . print_r($data, 1) . '', + ))); + } + } +} + + +function fb_devel_fb_tab($op, $data, &$return) { + // debug. + if (fb_verbose() === 'extreme') { + $return['fb_devel'] = array( + '#type' => 'markup', + '#markup' => __FUNCTION__ . ':' . print_r($data, 1), + '#prefix' => '
', + '#suffix' => '', + '#weight' => 99, + ); + if ($data['profile_id'] && isset($data['fb'])) { + $return['fb_devel']['profile_id'] = array( + '#type' => 'markup', + '#markup' => __FUNCTION__ . ':' . print_r($data['fb']->api($data['profile_id']), 1), + '#prefix' => '
', + '#suffix' => '', + '#weight' => 99, + ); + } + } +} + + +/** + * Wrapper for fb_fql_query(). Useful for debugging. + */ +function fb_devel_fql_query($fb, $query, $params = array()) { + if (!is_object($fb)) { + dpm(debug_backtrace(), __FUNCTION__); + return; + } + $url_params = $params; + $url_params['query'] = $query; + $url_params['format'] = 'JSON'; + $url = url("https://api.facebook.com/method/fql.query", array('query' => $url_params)); + dpm(func_get_args(), __FUNCTION__); + drupal_set_message(l($url, $url)); + return fb_fql_query($fb, $query, $params); +} diff --git a/fb_form.info b/fb_form.info index 08132db..753abfa 100644 --- a/fb_form.info +++ b/fb_form.info @@ -1,5 +1,11 @@ -name = FB Forms -description = (fb_form.module) Build FBML form constructs such as requests using Drupal's Form API. -package = Drupal for Facebook -dependencies[] = fb -core = 6.x \ No newline at end of file +name = FB Forms +description = (fb_form.module) Build FBML form constructs such as requests using Drupal's Form API. +package = Drupal for Facebook +dependencies[] = fb +core = 7.x +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/fb_stream.info b/fb_stream.info index 2b3cba2..407cb34 100644 --- a/fb_stream.info +++ b/fb_stream.info @@ -1,5 +1,11 @@ -name = FB Streams -description = (fb_stream.module) APIs for posting to Facebook Streams (a.k.a. News Feed or Wall) -package = Drupal for Facebook -dependencies[] = fb -core = 6.x \ No newline at end of file +name = FB Streams +description = (fb_stream.module) APIs for posting to Facebook Streams (a.k.a. News Feed or Wall) +package = Drupal for Facebook +dependencies[] = fb +core = 7.x +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/fb_tab.info b/fb_tab.info index ec1eb33..9fccc69 100644 --- a/fb_tab.info +++ b/fb_tab.info @@ -1,11 +1,17 @@ -name = FB Tabs -description = (fb_tab.module) Enable tabs on pages where your applications are installed. -package = Drupal for Facebook -core = 7.x - -dependencies[] = fb -dependencies[] = fb_app - -files[] = fb_tab.install -files[] = fb_tab.module -files[] = fb_tab.admin.inc \ No newline at end of file +name = FB Tabs +description = (fb_tab.module) Enable tabs on pages where your applications are installed. +package = Drupal for Facebook +core = 7.x + +dependencies[] = fb +dependencies[] = fb_app + +files[] = fb_tab.install +files[] = fb_tab.module +files[] = fb_tab.admin.inc +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/fb_user.info b/fb_user.info index c433bbe..f40ce80 100644 --- a/fb_user.info +++ b/fb_user.info @@ -1,12 +1,18 @@ -name= FB User Management -description = (fb_user.module) Maps local user accounts to facebook user ids. Creates local accounts for app users when configured to do so. - -package = Drupal for Facebook -core = 7.x - -dependencies[] = fb -dependencies[] = fb_app - -files[] = fb_user.install -files[] = fb_user.module -files[] = fb_user.admin.inc \ No newline at end of file +name= FB User Management +description = (fb_user.module) Maps local user accounts to facebook user ids. Creates local accounts for app users when configured to do so. + +package = Drupal for Facebook +core = 7.x + +dependencies[] = fb +dependencies[] = fb_app + +files[] = fb_user.install +files[] = fb_user.module +files[] = fb_user.admin.inc +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" + diff --git a/fb_views/fb_views.info b/fb_views/fb_views.info index a8cd5da..91d0fe8 100644 --- a/fb_views/fb_views.info +++ b/fb_views/fb_views.info @@ -1,7 +1,14 @@ -name = FB Views -description = (fb_views.module) Provides features specific to Views module for Facebook Apps. -package= Drupal for Facebook -core = 6.x -dependencies[] = fb -dependencies[] = fb_user -dependencies[] = views +name = FB Views +description = (fb_views.module) Provides features specific to Views module for Facebook Apps. +package= Drupal for Facebook +core = 7.x +dependencies[] = fb +dependencies[] = fb_user +dependencies[] = views + +; Information added by drupal.org packaging script on 2011-06-23 +version = "7.x-4.x-dev" +core = "7.x" +project = "fb" +datestamp = "1308787966" +