You are here

function fb_user_fb in Drupal for Facebook 5.2

Same name and namespace in other branches
  1. 5 fb_user.module \fb_user_fb()
  2. 6.3 fb_user.module \fb_user_fb()
  3. 6.2 fb_user.module \fb_user_fb()
  4. 7.4 fb_user.module \fb_user_fb()
  5. 7.3 fb_user.module \fb_user_fb()

Implementation of hook_fb.

File

./fb_user.module, line 73
This module allows Drupal user records to be associated with Facebook user ids. It can create local user accounts when Facebook users visit an application's canvas pages.

Code

function fb_user_fb($op, $data, &$return) {
  $fb_app = $data['fb_app'];
  $fb = $data['fb'];
  global $user;
  $fb_app_data = fb_app_get_data($fb_app);
  $fb_user_data = $fb_app_data['fb_user'];

  // our configuration
  if ($op == FB_OP_INITIALIZE) {

    // Here we ask facebook to prompt the user to authorize the app.
    if (fb_user_authentication_is_required($fb_app)) {
      $fb
        ->require_login();
    }
  }
  else {
    if ($op == FB_OP_POST_INIT) {

      // Observe special rules for canvas page users without local accounts
      if (!$user->uid && !_fb_user_special_page() && !$_REQUEST['form_id']) {
        if ($fbu = fb_facebook_user($fb) && fb_api_check_session($fb) && !$fb->api_client
          ->users_isAppUser()) {
          $uid = $fb_app_data['fb_user']['logged_in_uid'];
        }
        else {
          $uid = $fb_app_data['fb_user']['not_logged_in_uid'];
        }
        if ($uid) {
          dpm("XXX setting global user in fb_user_fb!");
          $user = user_load(array(
            'uid' => $uid,
          ));
        }
      }

      // TODO: is it now necessary to redirect the user back to current page?
    }
    else {
      if ($op == FB_OP_APP_IS_AUTHORIZED) {

        // We reach this point if the user has authorized the app.
        // Could be they visited a canvas page,
        // or could be they clicked a fbConnect link.
        $fbu = $data['fbu'];

        // The user id on facebook.
        // Remember the original uid
        $original_uid = $user->uid;
        if ($user->fbu != $fbu && fb_api_check_session($fb)) {

          // Try the application-specific account.
          $account = user_external_load("{$fbu}-{$fb_app->apikey}@facebook.com");
          if (!$account) {

            // Try the cross-application account.
            $account = user_external_load("{$fbu}@facebook.com");
          }
          if ($account) {
            $account->fbu = $fbu;
            if ($user->uid == 0) {
              $user = $account;
            }
            else {
              watchdog('fb_user', t('fb_user encountered something it cannot handle.  The current user, !user1 is logged in.  But the facebook user id %fbu is associated with another user, !user2', array(
                '!user1' => theme('username', $user),
                '!user2' => theme('username', $account),
                '%fbu' => $fbu,
              )), WATCHDOG_ERROR);
            }
          }
          else {

            // There is no account associated with the facebook id.
            // If the user is not anonymous, we can make an association now.
            if ($user->uid != 0 && $user->uid != $fb_app_data['fb_user']['logged_in_uid']) {
              if ($fb_user_data['map_account'] == FB_USER_OPTION_MAP_ALWAYS) {
                list($module, $authname) = _fb_user_get_authmap($fb_app, $fbu);
                user_set_authmaps($user, array(
                  $module => $authname,
                ));

                // is this right?
                $user->fbu = $fbu;

                //dpm("setting up authmap to associate " . theme('username', $user) . " with fbu $fbu");
                watchdog('fb_user', t('Using authmap to associate user !user with facebook user id %fbu.', array(
                  '!user' => theme('username', $user),
                  '%fbu' => $fbu,
                )));
              }
            }
          }
        }

        // Check if the local account needs to be made.
        if ($user->fbu != fb_facebook_user($fb) && !_fb_user_special_page() && fb_api_check_session($fb)) {
          if ($fb_user_data['create_account'] == FB_USER_OPTION_CREATE_ADD && $fb->api_client
            ->users_isAppUser() || $fb_user_data['create_account'] == FB_USER_OPTION_CREATE_LOGIN) {

            // We need to make a local account for this facebook user.
            $user = fb_user_create_local_user($fb, $fb_app, fb_facebook_user($fb), array(
              'app_specific' => $fb_user_data['unique_account'],
              'roles' => array(
                $fb_user_data['new_user_rid'] => TRUE,
              ),
            ));
            watchdog('fb_user', t("Created new user !username for application %app", array(
              '!username' => theme('username', $user),
              '%app' => $fb_app->label,
            )));
          }
        }

        // It's possible the user was already created by another app.
        // In this case we need to add our role.
        if ($user->fbu == fb_facebook_user() && $fb_user_data['new_user_rid'] && !$user->roles[$fb_user_data['new_user_rid']]) {

          // there should be an API for this...
          db_query('INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)', $user->uid, $fb_user_data['new_user_rid']);
          watchdog('fb_user', t("Added role %role to existing user !username for application %app", array(
            '!username' => theme('username', $user),
            '%app' => $fb_app->label,
            '%role' => $fb_user_data['new_user_rid'],
          )));
        }
        if ($user->uid != $original_uid && !(arg(0) == 'fb_app' && arg(1) == 'event')) {

          // We've changed the user.  In order to ensure that drupal handles
          // permissions properly, the user must make the request all over
          // again.  Skip this for the profile tab, as facebook does not allow
          // redirects (or persistent session) there.
          if (function_exists('fb_canvas_is_fbml') && (fb_canvas_is_fbml() || fb_canvas_is_iframe()) && !$_REQUEST['fb_sig_in_profile_tab']) {

            // Redirect to a canvas page
            $url = fb_canvas_fix_url(url(fb_scrub_urls($_REQUEST['q']), NULL, NULL, TRUE), $fb_app);
            if (fb_verbose()) {
              watchdog('fb_debug', "User uid is now {$user->uid} (was {$original_uid}), redirecting to {$url} to ensure permissions are correct.");
            }

            // debug
            $fb
              ->redirect($url);
          }
          else {
            if (!fb_settings(FB_SETTINGS_APP_NID)) {

              // Facebook connect pages (not callback or receiver)
              $path = $_REQUEST['q'];
              if (fb_verbose()) {
                watchdog('fb_debug', "User uid is now {$user->uid} (was {$original_uid}), redirecting to {$path} to ensure permissions are correct.");
              }

              // debug
              drupal_goto($path);
            }
          }
        }

        // Keep a record of when user accesses app.
        _fb_user_track($fb, $fb_app, $user);

        // We don't want user's who are not logged in (in the facebook sense) to
        // login locally.  So let's make sure they've added the app before doing
        // anything related to Drupal accounts.

        /** I _think_ the new api no longer requires this.  TODO: confirm.
            if (strpos($_GET['q'],'user/login') === 0) {
              // Have to check idAppUser in case of iframe.
              if (!$fb->api_client->users_isAppUser())
                $fb->require_login();
            }
            else if (strpos($_GET['q'],'user/register') === 0) {
              if (!$fb->api_client->users_isAppUser())
                $fb->require_login();
            }
            */

        // Now do I need a goto or some such???
        // debug

        /*
          drupal_set_message("To Drupal, you are " . theme('username', $user));
          drupal_set_message("Facebook user id is " . fb_facebook_user());
          drupal_set_message("Facebook logged in is " . $fb->get_loggedin_user());
        */
      }
      else {
        if ($op == FB_OP_GET_FBU) {

          // This is a request to learn the user's FB id.
          $return = _fb_user_get_fbu($data['uid'], $fb_app);
        }
        else {
          if ($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 = '%s' and fbu = %d AND session_key_expires > %d", $fb_app->apikey, $fbu, time());
            $data = db_fetch_object($result);
            if ($data && $data->session_key) {

              // Return array with FB id and apikey.
              $return = array(
                $data->fbu,
                $data->session_key,
              );
            }
          }
          else {
            if ($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) {

                // User has authorized us to know some details about her.
                db_query("REPLACE INTO {fb_user_app} (apikey, fbu, added, session_key, session_key_expires) VALUES ('%s', %d, 1, '%s', %d)", $fb_app->apikey, fb_facebook_user($fb), $fb->api_client->session_key, $fb->session_expires);
              }
              else {
                if ($event_type == FB_APP_EVENT_POST_REMOVE) {

                  // User has removed the app from their account.
                  // Should we delete the row here???
                  db_query("UPDATE {fb_user_app} SET added=0, session_key=NULL, session_key_expires=NULL WHERE apikey='%s' AND fbu=%d", $fb_app->apikey, fb_facebook_user($fb));
                }
              }
            }
          }
        }
      }
    }
  }
}