You are here

fbconnect.module in Facebook Connect 5

This module allows site visitors to connect and register with facebook account

File

fbconnect.module
View source
<?php

/**
 * @file
 * This module allows site visitors to connect and register with facebook account
 */
define('FBCONNECT_RENEW_CACHE', 12);
define('FBCONNECT_USER_CACHE_EXPIRE', 24);
define('FBCONNECT_USERBLOCK_CACHE_EXPIRE', 1);
define('FBCONNECT_REG_FEED_BUNDLEID', 47875658217);
define('FBCONNECT_COMMENT_FEED_BUNDLEID', 47874003217);
define('FBCONNECT_USE_FBAVATAR', 1);

/**
 * Implementation of hook_menu().
 */
function fbconnect_menu($may_cache) {
  global $user;
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/settings/fbconnect',
      'title' => 'Fbconnect',
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'fbconnect_admin_settings',
      ),
      'access' => user_access('administer site configuration'),
      'type' => MENU_NORMAL_ITEM,
    );
    $items[] = array(
      'path' => 'fbconnect/register/create',
      'title' => t('Connect with Facebook'),
      'callback' => 'fbconnect_register_page',
      'access' => !$user->uid,
      'type' => MENU_CALLBACK,
    );
    $items[] = array(
      'path' => 'fbconnect/register/prompt',
      'title' => t('Facebook Connect'),
      'callback' => 'fbconnect_prompt_page',
      'access' => !$user->uid,
      'type' => MENU_CALLBACK,
    );
    $items[] = array(
      'path' => 'fbconnect/invite/friends',
      'title' => t('Share with my friends'),
      'callback' => 'fbconnect_render_friends_invite_form',
      'access' => $user->uid,
      'type' => MENU_CALLBACK,
    );
  }
  else {

    // Renders the JS necessary for any Facebook interaction to work.
    _fbconnect_render_js();
    if (arg(0) == 'fbconnect' && arg(1) == 'register') {
      $GLOBALS['conf']['cache'] = FALSE;
    }
    if (arg(0) == 'user' && is_numeric(arg(1))) {
      $account = user_load(array(
        'uid' => arg(1),
      ));
      if ($account->uid) {
        $access = user_access('administer users') || $user->uid == arg(1);
        $items[] = array(
          'path' => 'user/' . arg(1) . '/fbconnect',
          'title' => check_plain($account->name),
          'callback' => 'fbconnect_user_identities',
          'callback arguments' => array(
            $account,
          ),
          'access' => $access,
          'type' => MENU_LOCAL_TASK,
        );
      }
    }
  }
  return $items;
}

/** 
 * Form builder. Configure fbconnect. 
 * @see system_settings_form(). 
 */
function fbconnect_admin_settings() {
  global $base_url;
  $form['api'] = array(
    '#type' => 'fieldset',
    '#title' => t('Facebook connect config'),
    '#collapsible' => FALSE,
    '#weight' => -5,
  );
  $form['api']['fbconnect_fast_reg'] = array(
    '#type' => 'checkbox',
    '#title' => t('Fast registration mode'),
    '#default_value' => variable_get('fbconnect_fast_reg', NULL),
    '#description' => t('Enabling this mode allows the user to create an account in one click.'),
  );
  $form['api']['fbconnect_api_key'] = array(
    '#type' => 'textfield',
    '#title' => t('Facebook API KEY'),
    '#default_value' => variable_get('fbconnect_api_key', NULL),
  );
  $form['api']['fbconnect_secret_api_key'] = array(
    '#type' => 'textfield',
    '#title' => t('Facebook Secret API KEY'),
    '#default_value' => variable_get('fbconnect_secret_api_key', NULL),
  );
  $form['api']['fbconnect_invitef_content'] = array(
    '#type' => 'textfield',
    '#title' => t('Invite message'),
    '#default_value' => variable_get('fbconnect_invitef_content', t('Your invite message')),
  );
  $form['api']['fbconnect_invitef_type'] = array(
    '#type' => 'textfield',
    '#title' => t('Your site name'),
    '#default_value' => variable_get('fbconnect_invitef_type', variable_get('site_name', NULL)),
  );
  $form['api']['fbconnect_invitef_redirect'] = array(
    '#type' => 'textfield',
    '#title' => t('Redirect url, when user valid or skip invite friend form'),
    '#default_value' => variable_get('fbconnect_invitef_redirect', $base_url),
  );
  $module_path = drupal_get_path('module', 'fbconnect') . '/images/';
  $button = array(
    'small_short' => theme_image($module_path . 'Connect_white_small_short.gif'),
    'medium_short' => theme_image($module_path . 'Connect_white_medium_short.gif'),
    'medium_long' => theme_image($module_path . 'Connect_white_medium_long.gif'),
    'large_short' => theme_image($module_path . 'Connect_white_large_short.gif'),
    'large_long' => theme_image($module_path . 'Connect_white_large_long.gif'),
  );
  $form['api']['fbconnect_button_type'] = array(
    '#type' => 'radios',
    '#default_value' => variable_get('fbconnect_button_type', 'large_long'),
    '#options' => $button,
  );
  $form['api']['fbconnect_reg_feed'] = array(
    '#type' => 'checkbox',
    '#title' => t('Display story feed prompt after user registration'),
    '#default_value' => variable_get('fbconnect_reg_feed', array(
      'fbconnect_reg_feed',
    )),
  );
  $form['api']['fbconnect_com_feed'] = array(
    '#type' => 'checkbox',
    '#title' => t('Display story feed prompt after comment post'),
    '#default_value' => variable_get('fbconnect_com_feed', array(
      'fbconnect_com_feed',
    )),
  );
  $form['api']['fbconnect_reg_feed_id'] = array(
    '#type' => 'textfield',
    '#title' => t('Registration feed bundle ID'),
    '#default_value' => variable_get('fbconnect_reg_feed_id', FBCONNECT_REG_FEED_BUNDLEID),
  );
  $form['api']['fbconnect_com_feed_id'] = array(
    '#type' => 'textfield',
    '#title' => t('Comment feed bundle ID'),
    '#default_value' => variable_get('fbconnect_com_feed_id', FBCONNECT_COMMENT_FEED_BUNDLEID),
  );
  drupal_set_message('Read the module\'s readme.txt for installation instructions.');
  return system_settings_form($form);
}
function fbconnect_prompt_page() {
  $reg_msg = t('Don\'t have a account? Create an account now');
  $link_msg = t('I already have an account, I\'d like to use Facebook Connect features.');
  if (module_exists('fbconnect_profile') && !variable_get('fbconnect_fast_reg', NULL)) {
    $step = 'import';
  }
  else {
    $step = 'create';
  }
  $reg_choice = l($reg_msg, 'fbconnect/register/' . $step);
  $link_choice = l($link_msg, 'user', array(), 'destination=fbconnect');
  $output = theme('box', NULL, $reg_choice);
  $output .= theme('box', NULL, $link_choice);
  return $output;
}

/**
 * Menu callback.
 * Called when user perform facebook registration
 */
function fbconnect_register_page() {
  if (!($fbuid = fbconnect_get_fbuid())) {
    drupal_set_message(t('Your Facebook session has expired, try to reconnect'));
    drupal_goto();
  }
  if (variable_get('fbconnect_fast_reg', NULL)) {
    $name = fbconnect_get_fbname($fbuid);
    try {

      // "http://wiki.developers.facebook.com/index.php/Proxied_Email"
      $fb_return = facebook_client()->api_client
        ->users_getInfo($fbuid, array(
        'proxied_email',
      ));
      $mail = $fb_return[0]['proxied_email'];
    } catch (Exception $e) {
      watchdog('fbconnect', 'Exception thrown : !code', array(
        '!code' => $e
          ->getMessage(),
      ), WATCHDOG_WARNING);
    }
    $udata = array(
      'name' => $name,
      'pass' => user_password(),
      'init' => $mail,
      'status' => 1,
      'mail' => $mail,
    );
    fbconnect_register_user($udata);
    drupal_set_message(t('Registration successful'));
    drupal_goto();
  }
  else {
    $help_box = t('In order to finalize your registration please choose a username and type in your e-mail address.');
    $output = '<div class="fb-help">' . $help_box . '</div>';
    $output .= drupal_get_form('fbconnect_register_form');
    if ($friends = fbconnect_get_connected_friends($fbuid)) {
      $title = t('My Facebook friends already registered');
      $output .= theme('render_friends_list_fbconnect', $friends, $title);
    }
    return $output;
  }
}

/**
 * This form is display when we register a new user.
 */
function fbconnect_register_form() {
  $fbuid = fbconnect_get_fbuid();
  $sitename = variable_get('site_name', t('this website'));
  $form['reg'] = array(
    '#type' => 'fieldset',
    '#collapsible' => FALSE,
  );
  $form['reg']['username'] = array(
    '#type' => 'textfield',
    '#title' => t('Username'),
    '#required' => TRUE,
    '#default_value' => fbconnect_get_fbname($fbuid),
    '#description' => t('Spaces are allowed; punctuation is not allowed except for periods, hyphens, and underscores.'),
  );
  $form['reg']['mail'] = array(
    '#type' => 'textfield',
    '#title' => t('E-mail address'),
    '#required' => TRUE,
    '#description' => t('A valid e-mail address. All e-mails from the system will be sent to this address.'),
  );
  $form['reg']['visibility'] = array(
    '#type' => 'checkbox',
    '#title' => t('Let my Facebook friends see me on @sitename', array(
      '@sitename' => $sitename,
    )),
    '#description' => t('My Facebook friends will be able to see that I own an account on @sitename.', array(
      '@sitename' => $sitename,
    )),
    '#default_value' => 1,
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
  return $form;
}

/** 
 * Validate the register form. 
 */
function fbconnect_register_form_validate($form, &$form_state) {

  // Validate the username
  $name = $form_state['username'];
  if (user_validate_name($name)) {
    form_set_error('username', user_validate_name($name));
  }
  else {
    if (db_result(db_query("SELECT COUNT(*) FROM {users} WHERE LOWER(name) = LOWER('%s')", $name)) > 0) {
      form_set_error('username', t('The name %name is already taken.', array(
        '%name' => $name,
      )));
    }
    else {
      if (drupal_is_denied('user', $name)) {
        form_set_error('username', t('The name %name is a reserved username.', array(
          '%name' => $name,
        )));
      }
    }
  }

  // Validate e-mail
  $mail = $form_state['mail'];
  if (user_validate_mail($mail)) {
    form_set_error('mail', user_validate_mail($mail));
  }
  else {
    if (db_result(db_query("SELECT COUNT(*) FROM {users} WHERE LOWER(mail) = LOWER('%s')", $mail)) > 0) {
      form_set_error('mail', t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array(
        '%email' => $mail,
        '@password' => url('user/password'),
      )));
    }
    else {
      if (drupal_is_denied('mail', $mail)) {
        form_set_error('mail', t('The e-mail address %email has been denied access.', array(
          '%email' => $mail,
        )));
      }
    }
  }
}
function fbconnect_register_user($data) {
  global $user;
  $data['roles'][DRUPAL_AUTHENTICATED_RID] = 'authenticated user';
  $fbuid = fbconnect_get_fbuid();

  // Save facebook picture as avatar.
  if (variable_get('user_pictures', 0)) {
    $picture = fbconnect_get_fb_avatar($fbuid);
    if ($picture) {
      $data['picture'] = $picture;
    }
  }
  $user = user_save($user, $data);
  if ($user->uid) {
    $msg = t('New user: %name %email.', array(
      '%name' => $data['name'],
      '%email' => '<' . $data['mail'] . '>',
    ));
    watchdog('fbconnect', $msg, WATCHDOG_NOTICE, l(t('edit'), 'user/' . $user->uid . '/edit'));
  }
  fbconnect_register($user->uid, $fbuid);
}

/** 
 * Handle post-validation register form submission. 
 */
function fbconnect_register_form_submit($form, &$form_state) {
  global $user;
  $visible = $form_state['visibility'];
  $mail = $form_state['mail'];
  $udata = array(
    'name' => $form_state['username'],
    'mail' => $mail,
    'init' => $mail,
    'status' => 1,
    'login' => time(),
    'pass' => user_password(),
  );
  fbconnect_register_user($udata);

  // Update user visibility, default = 1
  if (!$visible) {
    fbconnect_set_user_visibility($user, $visible);
  }
  if ($_SESSION['fb_reg_import'] && module_exists('fbconnect_profile')) {

    // Saving import settings.
    fbconnect_profile_insert_user_info($user->uid, $_SESSION['fb_reg_import']);
    unset($_SESSION['fb_reg_import']);
  }

  // If the user chose to be visible, and the registration feed parameter is enabled.
  // We store a value in the session variable,
  // this variable will be read by the _fbconnect_render_js function.
  if (variable_get('fbconnect_reg_feed', 1) && $visible) {
    $_SESSION['fbconnect_feed']['type'] = 'registration';
  }

  // The user has chosen to be visible, just redirect to the friends invite page.
  if ($visible) {
    $sitename = variable_get('site_name', t('this website'));
    $welcome_msg = t('Registration successful. You may now invite friends to join you on @site', array(
      '@site' => $sitename,
    ));
    drupal_set_message($welcome_msg, 'status');
    drupal_goto('fbconnect/invite/friends');
  }
  else {
    drupal_set_message(t('Registration successful.'));
    drupal_goto();
  }
}

/**
 * Menu callback fbconnect identities
 */
function fbconnect_user_identities($account) {
  $header = array(
    t('Facebook Connect identities'),
  );
  $rows[] = array(
    t('This website supports Facebook Connect and allow you to log in with your Facebook account.'),
  );
  if ($account->fbuid) {
    $rows[] = array(
      t('Your account is linked with your Facebook account.'),
    );
    if (fbconnect_get_fbuid() && $account->fbuid != fbconnect_get_fbuid()) {
      drupal_set_message('Invalid Facebook session, you\'re not authorized to modify the parameters.');
      return theme('table', $header, $rows);
    }
    if (!fbconnect_get_fbuid()) {
      $rows[] = array(
        t('Open a Facebook session for more settings options.'),
      );
      $rows[] = array(
        fbconnect_render_button(),
      );
    }
    $output = theme('table', $header, $rows);
    $output .= drupal_get_form('fbconnect_user_settings_form');
    return $output;
  }
  if (!fbconnect_get_fbuid()) {
    $rows[] = array(
      t('Click on login button below to link your account on @sitename with your Facebook account.', array(
        '@sitename' => variable_get('site_name', t('this website')),
      )),
    );
    $rows[] = array(
      fbconnect_render_button(),
    );
    return theme('table', $header, $rows);
  }
  $rows[] = array(
    t('Facebook session detected, please confirm that you wish to link your @sitename account and Facebook account.', array(
      '@sitename' => variable_get('site_name', t('this website')),
    )),
  );
  $output = theme('table', $header, $rows);
  $output .= drupal_get_form('fbconnect_association_form');
  return $output;
}

/**
 * Render the user fbconnect association form
 */
function fbconnect_association_form() {
  $form['link'] = array(
    '#type' => 'checkbox',
    '#title' => t('Link my account on @sitename and my Facebook account', array(
      '@sitename' => variable_get('site_name', t('this website')),
    )),
    '#default_value' => 1,
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
  return $form;
}

/**
 *  This form allows the user to manage their facebook connect settings.
 *
 *  Some options are visible only if facebook session is active.
 */
function fbconnect_user_settings_form() {
  $user = user_load(array(
    'uid' => arg(1),
  ));

  // These fields manage the visibility of the user,
  // if the option is enabled, user's facebook friends
  // will be able to see his presence on this site
  $form['view'] = array(
    '#type' => 'fieldset',
    '#collapsible' => FALSE,
    '#weight' => -2,
  );
  $form['view']['visibility'] = array(
    '#type' => 'checkbox',
    '#title' => t('Let my Facebook friends see me on @sitename', array(
      '@sitename' => variable_get('site_name', 'this website'),
    )),
    '#description' => t('My Facebook friends will be able to see that I own an account on this website.'),
    '#default_value' => $user->fb_visibility,
  );

  // This fields is visible only if we got a active Facebook session.
  // Whether user picture is enabled,
  // users can choose to use his facebook avatar as avatar
  if (fbconnect_get_fbuid()) {
    if (variable_get('user_pictures', 0)) {
      $form['avatar'] = array(
        '#type' => 'fieldset',
        '#collapsible' => FALSE,
        '#weight' => -3,
      );
      $form['avatar']['fb_avatar'] = array(
        '#type' => 'checkbox',
        '#title' => t('Use my Facebook picture on @sitename', array(
          '@sitename' => variable_get('site_name', t('this website')),
        )),
        '#description' => t('Your picture will be updated every 24 hours.'),
        '#default_value' => fbconnect_user_avatar_setting($user->uid),
      );
    }
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save settings'),
  );
  return $form;
}

/**
 * Handle post-validation user_settingsForm submission. 
 */
function fbconnect_user_settings_form_submit($form, &$form_state) {
  $user = user_load(array(
    'uid' => arg(1),
  ));
  $form_value_visi = $form_state['visibility'];
  if ($user->fb_visibility != $form_value_visi) {
    fbconnect_set_user_visibility($user, $form_value_visi);
  }
  if (variable_get('user_pictures', 0)) {
    $db_value = fbconnect_user_avatar_setting($user->uid);
    $form_value = $form_state['fb_avatar'];
    if ($form_value && fbconnect_get_fbuid()) {
      fbconnect_refresh_user_avatar($user->fbuid, $user->uid);
    }
    if ($form_value != $db_value) {

      // Update avatar settings.
      fbconnect_user_avatar_setting($user->uid, $form_value);
    }
  }

  // Redirect to user profile.
  if (!module_exists('fbconnect_profile')) {
    drupal_set_message('Your Facebook connect settings have been saved.');
    drupal_goto('user/' . $user->uid);
  }
}

/** 
 * Handle post-validation association_Form submission.
 *
 * When the user submits this form, an association of the drupal uid
 * and the facebook fbuid is inserted into the table fbconnect_users.
 */
function fbconnect_association_form_submit($form, &$form_state) {
  if ($fbuid = fbconnect_get_fbuid()) {
    if ($form_state['link'] == 1) {
      $user = user_load(array(
        'uid' => arg(1),
      ));
      if (fbconnect_register($user->uid, $fbuid)) {
        drupal_set_message(t('Congratulations! Your account is now linked to your Facebook account'), 'status');
        watchdog('fbconnect', 'User uid: !user is now associated with the fbuid: !fbuid.', array(
          '!user' => $user->uid,
          '!fbuid' => $fbuid,
        ));
      }
      else {
        drupal_set_message(t('Association failed'), 'error');
        watchdog('fbconnect', 'User association failed for uid: %user - fbuid: %fbuid.', array(
          '!user' => $user->uid,
          '!fbuid' => $fbuid,
        ));
      }
    }
  }
}

/**
 * Recupere l'avatar Facebook de l'utilisateur.
 * @param Int $fbuid
 */
function fbconnect_get_fb_avatar($fbuid) {
  $size = 'pic_with_logo';

  // Get facebook user picture's url.
  $pic_url = fbconnect_get_info_from_fb($fbuid, $size);
  $result = drupal_http_request($pic_url[$size]);
  if ($result->code != 200) {
    watchdog('fbconnect', 'Failed importing facebook user avatar for !fbuid, code : !code', array(
      '!fbuid' => $fbuid,
      '!code' => $result->code,
    ));
    return;
  }
  if ($result->headers['Content-Type'] != 'image/jpeg') {
    watchdog('fbconnect', 'Failed importing facebook user avatar, invalid content-type.');
    return;
  }
  $filename = 'picture-fb_' . $fbuid . '.jpg';
  $dest = file_directory_path();
  if (variable_get('user_picture_path', '')) {
    $dest .= '/' . variable_get('user_picture_path', '');
  }
  $dest .= '/' . $filename;
  return file_save_data($result->data, $dest, FILE_EXISTS_REPLACE);
}

/**
 * Return the user avatar settings.
 */
function fbconnect_user_avatar_setting($uid, $value = NULL) {
  if (is_numeric($value)) {
    return db_query('UPDATE {fbconnect_users} SET avatar = %d WHERE uid = %d', $value, $uid);
  }
  return db_result(db_query('SELECT avatar FROM {fbconnect_users} WHERE uid = %d', $uid));
}

/**
 * Implementation of hook_block().
 */
function fbconnect_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
      $blocks[0]['info'] = t('Fbconnect friend list');
      $blocks[0]['cache'] = BLOCK_NO_CACHE;
      return $blocks;
    case 'view':
      global $user;
      $fbuid = fbconnect_get_fbuid();
      if ($user->uid && $fbuid) {
        $query = 'SELECT uid FROM {fbconnect_users} WHERE uid = %d AND fbuid = %d';
        if ($res = db_result(db_query($query, $user->uid, $fbuid))) {
          $blocks['content'] = fbconnect_block_render($user);
        }
      }
      return $blocks;
  }
}

/**
 * Render data for fbconnect block
 */
function fbconnect_block_render($user) {
  $fbuid = fbconnect_get_fbuid();
  $cid = 'fbconnect:' . $user->uid;

  // Check for cached version.
  if ($cached = cache_get($cid)) {
    return $cached->data;
  }
  else {
    $content = fbconnect_get_connected_friends($fbuid);
    $data['friend_list'] = $content;
    $data['friend_link'] = l(t('Invite your Facebook friends'), 'fbconnect/invite/friends');
    $output = theme('block_fbconnect', $data, $user);
    cache_set($cid, 'cache', $output, time() + FBCONNECT_USERBLOCK_CACHE_EXPIRE * 3600);
  }
  return $output;
}

/**
 * This form is submitted by javascript when facebook session is detected.
 */
function fbconnect_autoconnect_form() {
  $form['fbconnect'] = array(
    '#type' => 'hidden',
  );
  return $form;
}
function fbconnect_autoconnect_form_validate($form, &$form_state) {
  global $user;
  if ($user->uid) {
    return;
  }
  $fbuid = fbconnect_get_fbuid();
  if (!$fbuid) {
    return;
  }
  $uid = _is_fbconnect_user($fbuid);
  if (!$uid) {
    drupal_goto('fbconnect/register/prompt');
  }
  elseif ($uid) {
    $user = user_load($uid);
    db_query('UPDATE {users} SET login = %d WHERE uid = %d', time(), $user->uid);

    // If the fbconnect_profile module is enabled,
    // we checks the imported information's cache.
    if (module_exists('fbconnect_profile')) {
      fbconnect_profile_check_profile_cache($user->uid);
    }
    drupal_goto($_GET['q']);
  }
}

/**
 * Implementation of hook_footer().
 */
function fbconnect_footer() {
  $fb_js_url = 'http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php';
  $footer = '<script type="text/javascript" src="' . $fb_js_url . '"></script>';

  // Display the autoconnect form.
  $footer .= drupal_get_form('fbconnect_autoconnect_form');
  return $footer;
}

/**
 * This function manage all javascripts used by this module.
 */
function _fbconnect_render_js() {
  global $base_url;
  $url = drupal_to_js($base_url);
  drupal_add_js(drupal_get_path('module', 'fbconnect') . '/js/fbconnect.js', 'module', 'footer');
  if (!($conf = fbconnect_get_config())) {
    return;
  }
  $sitename = drupal_to_js(variable_get('fbconnect_invitef_type', variable_get('site_name', NULL)));
  if ($_SESSION['fbconnect_feed']['type'] == 'registration') {
    $bundle_id = variable_get('fbconnect_reg_feed_id', FBCONNECT_REG_FEED_BUNDLEID);
    $onload_js .= 'facebook_publish_feed_story(' . $bundle_id . ', {
                    "sitename": ' . $sitename . ', "siteurl" : ' . $url . '
                  });';
    unset($_SESSION['fbconnect_feed']);
  }
  if ($_SESSION['fbconnect_feed']['type'] == 'comment') {
    $bundle_id = variable_get('fbconnect_com_feed_id', FBCONNECT_COMMENT_FEED_BUNDLEID);
    $onload_js .= 'facebook_publish_feed_story(' . $bundle_id . ',{
                    "sitename":' . $sitename . ',
                    "siteurl" : ' . $url . ',
                    "title" : ' . $_SESSION['fbconnect_feed']['title'] . ',
                    "article_url" : ' . $_SESSION['fbconnect_feed']['nodeurl'] . ',
                    "comment" : "' . $_SESSION['fbconnect_feed']['comment'] . '"
                   });';
    unset($_SESSION['fbconnect_feed']);
  }
  if (fbconnect_get_fbuid() && $_GET['fblogout']) {
    $onload_js = 'FB.Connect.logout(function() { window.location = ' . $url . ';});';
  }
  $xd_path = drupal_to_js(base_path() . drupal_get_path('module', 'fbconnect') . '/xd_receiver.html');
  drupal_add_js('FB.Bootstrap.requireFeatures(["Connect","XFBML"], function() {
                    FB.Facebook.init("' . $conf['api_key'] . '", ' . $xd_path . ');
                    ' . $onload_js . '
                });', 'inline', 'footer');
}

/**
 * Impletementation of hook_form_alter.
 */
function fbconnect_form_alter($form_id, &$form) {
  if ($form_id == 'user_login' && $_GET['destination'] == 'fbconnect') {
    unset($_REQUEST['destination']);
    $msg = t('Please log in, in order to link your account with Facebook Connect');
    drupal_set_message($msg);
    $form['#submit']['fbconnect_redirect_submit'] = array();
    return;
  }

  // Render fbconnect on login form.
  if ($form_id == 'user_login_block' || $form_id == 'user_login') {
    $cnx_msg = t('Sign in using Facebook');
    $items[] = array(
      'data' => $cnx_msg . fbconnect_render_button(),
      'class' => 'fbconnect-button',
    );
    $form['fbconnect_button'] = array(
      '#value' => theme('item_list', $items),
      '#attributes' => array(
        'class' => 'fbconnect-button',
      ),
      '#weight' => 1,
    );
  }

  // Warning msg on user edit.
  if ($form_id == 'user_edit' && variable_get('user_pictures', 0)) {
    if (fbconnect_user_avatar_setting(arg(1))) {
      $msg = t('You are currently using your Facebook picture, if you delete or load a new picture, your facebook picture will no longer be updated.');
      drupal_set_message($msg);
    }
    $form['#submit']['fbconnect_user_edit_submit'] = array();
  }
  if (!fbconnect_get_fbuid()) {
    return;
  }

  // Facebook feed checkbox on comment form.
  if ($form_id == 'comment_form' && variable_get('fbconnect_com_feed', NULL)) {
    $text = fbconnect_render_fb_favicon() . t('Publish Facebook story feed');
    $form['fbconnect_feed'] = array(
      '#type' => 'checkbox',
      '#title' => $text,
      '#default_value' => 1,
      '#weight' => 0,
    );
    $form['#submit']['fbconnect_comment_feed_submit'] = array();
  }
}

/**
 *  Redirects the user to the account linking page.
 */
function fbconnect_redirect_submit($form, &$form_state) {
  drupal_get_messages('status');
  drupal_goto('user/' . $GLOBALS['user']->uid . '/fbconnect');
}

/**
 * If the user deletes the photo or load a new picture, 
 * we deactivate the automatic import of the Facebook avatar.
 */
function fbconnect_user_edit_submit($form, &$form_state) {
  if ($form_state['picture_delete'] || $form_state['picture']) {
    if (is_numeric(arg(1))) {
      fbconnect_user_avatar_setting(arg(1), 0);
    }
  }
}

/**
 * Stock informations used by the facebook feed javascript function.
 */
function fbconnect_comment_feed_submit($form, &$form_state) {
  if ($form_state['fbconnect_feed'] == 1) {
    $node = node_load(array(
      'nid' => $form_state['nid'],
    ));
    $_SESSION['fbconnect_feed'] = array(
      'type' => 'comment',
      'comment' => check_plain($form_state['comment']),
      'title' => drupal_to_js($node->title),
      'nodeurl' => drupal_to_js(url('node/' . $node->nid, NULL, NULL, TRUE)),
    );
  }
}
function fbconnect_refresh_user_avatar($fbuid, $uid) {
  db_query("UPDATE {users} SET picture = '%s' WHERE uid = %d", fbconnect_get_fb_avatar($fbuid), $uid);
}

/**
 * Impletementation of hook_cron
 */
function fbconnect_cron() {
  $expire = time() - FBCONNECT_USER_CACHE_EXPIRE * 3600;

  // Update user picture
  if (variable_get('user_pictures', 0)) {
    $result = db_query('SELECT uid, fbuid FROM {fbconnect_users} WHERE timestamp < %d AND avatar = %d', $expire, FBCONNECT_USE_FBAVATAR);
    while ($tab = db_fetch_array($result)) {
      if ($tab) {
        fbconnect_refresh_user_avatar($tab['fbuid'], $tab['uid']);
        db_query('UPDATE {fbconnect_users} SET timestamp = %d', time());
      }
    }
  }
  cache_clear_all();
}

/**
 * Implementation of hook_user().
 */
function fbconnect_user($op, &$edit, &$account, $category = NULL) {
  switch ($op) {
    case 'load':
      $data = db_fetch_array(db_query('SELECT fbuid, timestamp, visibility FROM {fbconnect_users} WHERE uid = %d', $account->uid));
      $account->fbuid = $data['fbuid'];
      $account->fb_visibility = $data['visibility'];
      break;
    case 'delete':
      if ($account->fbuid) {
        db_query('DELETE FROM {fbconnect_users} WHERE uid = %d', $account->uid);
        db_query('DELETE FROM {fbconnect_profile} WHERE uid = %d', $account->uid);
      }
      break;
    case 'logout':
      if (fbconnect_get_fbuid()) {
        drupal_goto(NULL, 'fblogout=true');
      }
      break;
  }
}

/**
 * Query information from facebook user table.
 *
 * @return array
 */
function fbconnect_get_info_from_fb($fbuid, $fields) {
  if (facebook_client() && $fields) {
    try {
      $result = facebook_client()->api_client
        ->fql_query("SELECT {$fields} FROM user WHERE uid = {$fbuid}");
      return $result[0];
    } catch (Exception $e) {
      watchdog('fbconnect', 'Exception thrown while using FQL: !code', array(
        '!code' => $e
          ->getMessage(),
      ), WATCHDOG_WARNING);
    }
  }
}

/**
 * Get the facebook username
 * @param integer $fbuid
 *   Facebook user id
 */
function fbconnect_get_fbname($fbuid) {
  if (facebook_client()) {
    try {
      $result = facebook_client()->api_client
        ->users_getStandardInfo($fbuid, array(
        'name',
      ));
      return check_plain($result[0]['name']);
    } catch (Exception $e) {
      watchdog('fbconnect', 'Exception thrown while calling users_getStandardInfo: !code', array(
        '!code' => $e
          ->getMessage(),
      ), WATCHDOG_WARNING);
    }
  }
}

/**
 * Check facebook session.
 *
 * @return integer
 *   facebook user id
 */
function fbconnect_get_fbuid() {
  if (facebook_client()) {
    return facebook_client()
      ->get_loggedin_user();
  }
}

/**
 * Check if user already registered in the fbconnect_users table
 *
 * @param integer $fbuid
 *   Facebook user id
 * @return array
 */
function _is_fbconnect_user($fbuid) {
  $data = db_fetch_array(db_query('SELECT uid FROM {fbconnect_users} WHERE fbuid = %d', $fbuid));
  return $data ? $data : FALSE;
}
function fbconnect_import_filter($var) {
  return is_string($var) ? $var : NULL;
}

/**
 * Store user into table fbconnect
 *
 * @param integer $uid
 *   Drupal user id
 * @param integer $fbuid
 *   Facebook user id
 */
function fbconnect_register($uid, $fbuid) {
  return db_query("REPLACE {fbconnect_users} (uid, fbuid, timestamp) VALUES (%d, %d, %d) ", $uid, $fbuid, time());
}

/**
 * Render a facebook user picture
 *
 * @param string $size 
 *   Size of the pic. one of ('thumb', 'medium', 'large')
 */
function fbconnect_render_avatar($fbuid, $size = 'medium') {
  return '<fb:profile-pic facebook-logo="true" size="' . $size . '" uid="' . $fbuid . '"></fb:profile-pic>';
}

/**
 * Render a custom button to log in via Facebook.
 */
function fbconnect_render_button() {
  list($size, $length) = explode('_', variable_get('fbconnect_button_type', array(
    'medium-short',
  )));
  return '<fb:login-button onlogin="facebook_onlogin_ready();" size="' . $size . '" background="white" length="' . $length . '">
          </fb:login-button>';
}

/**
 * Get fbconnect config parameter
 *
 * @return array
 */
function fbconnect_get_config() {
  $config = array();
  $config['api_key'] = variable_get('fbconnect_api_key', NULL);
  $config['secret_api_key'] = variable_get('fbconnect_secret_api_key', NULL);
  if ($config['api_key'] && $config['secret_api_key']) {
    return $config;
  }
}

/**
 * Get the facebook client object for easy access.
 * @return object
 *   Facebook Api object
 */
function facebook_client() {
  static $fb = NULL;
  if (!$fb instanceof Facebook) {
    if ($conf = fbconnect_get_config()) {

      // Facebook php client API
      $lib_path = drupal_get_path('module', 'fbconnect') . '/facebook-client/';
      $lib_files = array(
        'facebook.php',
        'facebook_desktop.php',
        'jsonwrapper/jsonwrapper_inner.php',
        'jsonwrapper/jsonwrapper.php',
        'jsonwrapper/JSON/JSON.php',
      );
      foreach ($lib_files as $files) {
        if (!file_exists($lib_path . $files)) {
          $msg = t('Fbconnect : Facebook PHP library file @file not found see readme.txt', array(
            '@file' => $lib_path . $files,
          ));
          drupal_set_message($msg, 'status');
          return;
        }
      }

      // Include facebook.php
      include_once $lib_path . $lib_files[0];
      if (class_exists('Facebook')) {
        $fb = new Facebook($conf['api_key'], $conf['secret_api_key']);
      }
    }
  }
  return $fb;
}

/**
 * Get facebook friend who has_added_app.
 */
function fbconnect_get_connected_friends($fbuid) {
  if (facebook_client()) {
    $query = 'SELECT uid, has_added_app FROM user WHERE uid IN ' . '(SELECT uid2 FROM friend WHERE uid1 = ' . $fbuid . ')';
    try {
      $rows = facebook_client()->api_client
        ->fql_query($query);
    } catch (Exception $e) {
      watchdog('fbconnect', 'Exception thrown while using FQL: %code', array(
        '%code' => $e
          ->getMessage(),
      ), WATCHDOG_WARNING);
    }
    if (empty($rows)) {
      return;
    }
    $friends = array();
    foreach ($rows as $row) {
      if ($row['has_added_app'] == 0) {
        continue;
      }
      if ($uid = _is_fbconnect_user($row['uid'])) {
        $user = user_load($uid);
        if ($user->fb_visibility) {
          $friends[] = $user;
        }
      }
    }
    return $friends;
  }
}
function fbconnect_set_user_visibility($user, $visibility) {
  db_query('UPDATE {fbconnect_users} SET visibility = %d WHERE uid = %d', $visibility, $user->uid);
}

/**
 * Render the facebook friends invite form.
 */
function fbconnect_render_friends_invite_form() {
  if (!($fbuid = fbconnect_get_fbuid())) {
    drupal_set_message(t('Your Facebook session has expired, try to reconnect'));
    drupal_goto();
  }
  global $base_url;
  $url = check_url($base_url);
  $sitename = check_plain(variable_get('site_name', t('this website')));
  $actiontxt = t('Please select the Facebook friends you want to tell about @sitename.', array(
    '@sitename' => $sitename,
  ));
  $action = check_plain(variable_get('fbconnect_invitef_redirect', $url));
  $type = check_plain(variable_get('fbconnect_invitef_type', $sitename));
  $text = check_plain(variable_get('fbconnect_invitef_content', t('Enjoy the new drupal facebook connect module')));
  $content = $text . '  <fb:req-choice url=\'' . $url . '\' label=\'Become a Member!\' />';
  $output = '<fb:serverfbml style="width: 100%;">
                <script type="text/fbml">
                  <fb:fbml>
                    <fb:request-form
                      action="' . $action . '"
                      method="POST"
                      invite="true"
                      type="' . $type . '"
                      content="' . $content . '">	
                      <fb:multi-friend-selector
                      showborder="false"
                      actiontext="' . $actiontxt . '">
                    </fb:request-form>
                  </fb:fbml>
                </script>
              </fb:serverfbml>';
  return $output;
}

/**
 * Impletementation of hook_theme
 */
function fbconnect_theme() {
  return array(
    'block_fbconnect' => array(
      'arguments' => array(
        'data' => NULL,
        'account' => NULL,
      ),
    ),
    'render_friends_list_fbconnect' => array(
      'arguments' => array(
        'data' => NULL,
        'title' => NULL,
      ),
    ),
  );
}
function theme_render_friends_list_fbconnect($data, $title) {
  if (!empty($data)) {
    foreach ($data as $account) {
      if ($account->picture && file_exists($account->picture)) {
        $picture = theme('user_picture', $account);
      }
      $items[] = $picture . theme('username', $account);
      unset($picture);
    }
    return theme('item_list', $items, $title);
  }
}

/**
 * Return fbconnect blocks content
 * @param Array $data
 */
function theme_block_fbconnect($data, $account) {
  if (!empty($data)) {
    $output = '<div class="title">' . t('Welcome @username.', array(
      '@username' => $account->name,
    )) . '</div>';
    $output .= $data['friend_link'];
    if (!empty($data['friend_list'])) {
      $title = t('My friends');
      $output .= theme('render_friends_list_fbconnect', $data['friend_list'], $title);
    }
    return $output;
  }
}

/**
 * Render facebook favicon
 */
function fbconnect_render_fb_favicon() {
  return theme_image(drupal_get_path('module', 'fbconnect') . '/images/favicon.gif');
}

Functions

Namesort descending Description
facebook_client Get the facebook client object for easy access.
fbconnect_admin_settings Form builder. Configure fbconnect.
fbconnect_association_form Render the user fbconnect association form
fbconnect_association_form_submit Handle post-validation association_Form submission.
fbconnect_autoconnect_form This form is submitted by javascript when facebook session is detected.
fbconnect_autoconnect_form_validate
fbconnect_block Implementation of hook_block().
fbconnect_block_render Render data for fbconnect block
fbconnect_comment_feed_submit Stock informations used by the facebook feed javascript function.
fbconnect_cron Impletementation of hook_cron
fbconnect_footer Implementation of hook_footer().
fbconnect_form_alter Impletementation of hook_form_alter.
fbconnect_get_config Get fbconnect config parameter
fbconnect_get_connected_friends Get facebook friend who has_added_app.
fbconnect_get_fbname Get the facebook username
fbconnect_get_fbuid Check facebook session.
fbconnect_get_fb_avatar Recupere l'avatar Facebook de l'utilisateur.
fbconnect_get_info_from_fb Query information from facebook user table.
fbconnect_import_filter
fbconnect_menu Implementation of hook_menu().
fbconnect_prompt_page
fbconnect_redirect_submit Redirects the user to the account linking page.
fbconnect_refresh_user_avatar
fbconnect_register Store user into table fbconnect
fbconnect_register_form This form is display when we register a new user.
fbconnect_register_form_submit Handle post-validation register form submission.
fbconnect_register_form_validate Validate the register form.
fbconnect_register_page Menu callback. Called when user perform facebook registration
fbconnect_register_user
fbconnect_render_avatar Render a facebook user picture
fbconnect_render_button Render a custom button to log in via Facebook.
fbconnect_render_fb_favicon Render facebook favicon
fbconnect_render_friends_invite_form Render the facebook friends invite form.
fbconnect_set_user_visibility
fbconnect_theme Impletementation of hook_theme
fbconnect_user Implementation of hook_user().
fbconnect_user_avatar_setting Return the user avatar settings.
fbconnect_user_edit_submit If the user deletes the photo or load a new picture, we deactivate the automatic import of the Facebook avatar.
fbconnect_user_identities Menu callback fbconnect identities
fbconnect_user_settings_form This form allows the user to manage their facebook connect settings.
fbconnect_user_settings_form_submit Handle post-validation user_settingsForm submission.
theme_block_fbconnect Return fbconnect blocks content
theme_render_friends_list_fbconnect
_fbconnect_render_js This function manage all javascripts used by this module.
_is_fbconnect_user Check if user already registered in the fbconnect_users table

Constants