diff --git a/fb.module b/fb.module index 6764641b4735a695eb1a027d2e00a80ae5e467b0..a25a90a3f2167a58a0511d46a39349561cd670b5 100644 --- a/fb.module +++ b/fb.module @@ -22,7 +22,8 @@ define('FB_GRANT_REALM_FRIEND', 'fb_friend'); define('FB_GRANT_REALM_GROUP', 'fb_group'); // When initializing Facebook API, which user to log in as: -define('FB_FBU_INFINITE_SESSION', 'fbu_infinite'); +define('FB_FBU_INFINITE_SESSION', 'fbu_infinite'); // XXX deprecated, use no session +define('FB_FBU_NO_SESSION', 'fbu_no_session'); // http://wiki.developers.facebook.com/index.php/Category:Sessionless_API define('FB_FBU_CURRENT', 'fbu_current'); // Canvas pages only define('FB_FBU_ANY', 'fbu_any'); // Use current user on canvas page, fall back to infinite session otherwise. @@ -135,16 +136,16 @@ function fb_api_init($fb_app, $fbu) { //dpm(func_get_args(), "fb_api_init"); //$trace = debug_backtrace(); //dpm($trace, "fb_api_init call stack"); - + static $cache = array(); - + // This helps with uncaught exceptions. However, it should be configurable // or at least not overwrite previously declared handler. set_exception_handler('fb_handle_exception'); if (!count($cache)) { $filename = variable_get('fb_api_file', 'facebook-platform/client/facebook.php'); - + if (!file_exists($filename)) { // Print an error directly to the canvas page. //print("Failed to open Facebook API file $filename. Either fix this problem or disable Facebook modules."); @@ -187,10 +188,21 @@ function fb_api_init($fb_app, $fbu) { $fbu = $data[0]; $session = $data[1]; } - else { - // FB user id passed in. + else if ($fbu != FB_FBU_NO_SESSION) { + // FB user id passed in. If we happen to have valid session info for + // them, we can log in as them. + $data = fb_invoke(FB_OP_GET_USER_SESSION, + array('fb_app' => $fb_app, + 'fb' => $fb, + 'fbu' => $fbu), + array()); + + if (count($data) && $data[0] && $data[1]) { + $fbu = $data[0]; + $session = $data[1]; + } } - + if (!$cache[$fb_app->apikey][$fbu]) { // We don't have a cached resource for this app/user combo, so we're going to create one. $fb = new Facebook($fb_app->apikey, $fb_app->secret); @@ -211,29 +223,17 @@ function fb_api_init($fb_app, $fbu) { // Canvas page, current user is logged in already. // Nothing to do here. } - else { - // FB user id passed in. If we happen to have valid session info for - // them, we can log in as them. - $data = fb_invoke(FB_OP_GET_USER_SESSION, - array('fb_app' => $fb_app, - 'fb' => $fb, - 'fbu' => $fbu), - array()); - - if (count($data) && $data[0] && $data[1]) { - $fb->set_user($data[0], $data[1]); - $fbu = $data[0]; - } - + else if ($fbu == FB_FBU_NO_SESSION) { + $fb->set_user(NULL, NULL); } - + // Cache the result, in case we're called again. $cache[$fb_app->apikey][$fbu] = $fb; // Note that facebook api has not actually logged into facebook yet. // We won't really know if our session is valid until later. // get_loggedin_user does not really test it. - if ($fbu_orig != FB_FBU_CURRENT && !$fb->get_loggedin_user()) { + if ($fbu_orig != FB_FBU_NO_SESSION && !$fb->get_loggedin_user()) { // An FBU other than CURRENT was specified, but we failed to log in. watchdog('fb', t('Failed to log into facebook app %app as user %user', array('%app' => $fb_app->title, @@ -554,7 +554,6 @@ function fb_session_key_form() { /** * Invoke hook_fb. */ -//function fb_invoke($fb_app, $op, $return = NULL, $data = NULL) { old sig XXX function fb_invoke($op, $data = NULL, $return = NULL) { foreach (module_implements(FB_HOOK) as $name) { $function = $name . '_' . FB_HOOK; @@ -632,13 +631,16 @@ function fb_report_errors($fb = FB_APP_CURRENT, $message = NULL) { } } -function fb_log_exception($e, $text = '') { +function fb_log_exception($e, $text = '', $fb = NULL) { if ($text) $message = $text .': '. $e->getMessage(); else $message = $e->getMessage(); $message .= ' ' . $e->getCode(); + if ($fb) { + $message .= '. (' . t('logged into facebook as %fbu', array('%fbu' => $fb->get_loggedin_user())) . ')'; + } watchdog('fb', $message, WATCHDOG_ERROR); if (user_access('administer fb apps')) { drupal_set_message($message, 'error'); diff --git a/fb_actions.module b/fb_actions.module index ea8461af50be195ff743e05da27264ea3630cf77..20d452d992e5c5c3f5991d3d523212f40cfd7736 100644 --- a/fb_actions.module +++ b/fb_actions.module @@ -121,11 +121,13 @@ function fb_actions_profile_fbml(&$object, $values) { $fb_app = $GLOBALS['fb_app']; } - // Login to facebook as either the current user or the infinite session - if ($fb_app) + // Use already configured $fb if its passed in (cron jobs) + $fb = $values['fb']; + if (!$fb && $fb_app) + // Otherwise, login to facebook as either the current user or the infinite session $fb = fb_api_init($fb_app, FB_FBU_ANY); - if ($fb && $fb->get_loggedin_user()) { + if ($fb) { global $user; $fbu = fb_get_fbu($user->uid, $fb_app); // Replace fb_app related tokens @@ -164,7 +166,7 @@ function fb_actions_profile_fbml(&$object, $values) { // http://wiki.developers.facebook.com/index.php/Profile.setFBML $fb->api_client->profile_setFBML(NULL, $fbu, $body, NULL, $mobile_profile, $profile_main); } catch (Exception $e) { - fb_log_exception($e, t('Failed to set profile FBML')); + fb_log_exception($e, t('Failed to set profile FBML'), $fb); } } } @@ -185,7 +187,7 @@ function fb_actions_ref_fbml_form($values) { '#options' => $options, '#description' => t('Log into Facebook as which application? %current is OK when invoked from canvas pages or cron jobs.', array('%current' => $options[FB_APP_CURRENT])), - ); + ); $form['handle'] = array('#type' => 'textfield', '#title' => t('Handle'), '#default_value' => $values['handle'], @@ -294,6 +296,12 @@ function fb_actions_cron_per_user_submit($form_id, $values) { 'throttle' => $values['throttle'], ); } + +/** + * Trigger an action several times, emulating a different user each + * time. Useful for cron jobs in which we update each users profile + * box, for example. + */ function fb_actions_cron_per_user($obj, $values) { //$args = func_get_args(); //watchdog('fb_action_debug', "fb_actions_cron_per_user" . dpr($args, 1), WATCHDOG_ERROR); @@ -315,7 +323,7 @@ function fb_actions_cron_per_user($obj, $values) { $fb_app->apikey, $values['throttle']); while ($data = db_fetch_object($result)) { - // Log into facebook as the user from the database + // Find a local account for the application user $account = fb_user_get_local_user($data->fbu, $fb_app); if (variable_get('fb_actions_verbose', FALSE)) watchdog('fb_action_debug', "fb_actions_cron_per_user fbu is $data->fbu, local user is " . theme('username', $account), WATCHDOG_ERROR); @@ -329,18 +337,10 @@ function fb_actions_cron_per_user($obj, $values) { } else { // If here, local user has been found. - - $fb = fb_api_init($fb_app, $data->fbu); - if (!$fb || !$fb->api_client->users_getLoggedInUser()) - // Failed to log in as the current user, fallback to infinite session. - $fb = fb_api_init($fb_app, FB_FBU_INFINITE_SESSION); - if (!$fb || !$fb->api_client->users_getLoggedInUser()) { - watchdog('fb cron', t('Failed to log into %app during cron. Try testing infinite session key.', - array('%app' => $fb_app->title))); - } - else { - // if here, we're logged into facebook. - + // The older facebook API required us to log in as the current user. + // In the new API we should not need a user account to perform tasks appropriate for cron jobs. + $fb = fb_api_init($fb_app, FB_FBU_NO_SESSION); + if ($fb) { // Set things up as if this were a canvas page. $GLOBALS['user'] = $account; $GLOBALS['fb'] = $fb; @@ -348,11 +348,13 @@ function fb_actions_cron_per_user($obj, $values) { // Invoke any actions that we've been configured to invoke. try { - actions_do($values['actions'], $fb_app); + actions_do($values['actions'], $fb_app, + array('fb' => $fb, + 'fb_app' => $fb_app)); } catch (Exception $e) { watchdog('fb cron', "Action per user failed. " . $e->getMessage(), WATCHDOG_ERROR); } - + } // end if able to log into facebook } // end if local user found. @@ -362,7 +364,7 @@ function fb_actions_cron_per_user($obj, $values) { db_query("UPDATE {fb_user_app} SET time_cron=%d WHERE apikey='%s' AND fbu=%d", time(), $fb_app->apikey, $data->fbu); - } + } // end loop per user // Restore global variables $GLOBALS['user'] = $before_user;