From 4e236a7f2370fa1b706fbc82c3f25ec4f70608d1 Mon Sep 17 00:00:00 2001
From: Ben McIlwain <cydeweys@gmail.com>
Date: Wed, 4 Apr 2012 17:32:39 -0400
Subject: [PATCH] Adds configuration option to not auto-create new user, and pre-fills reg form.

---
 fboauth.install              |    2 +-
 fboauth.module               |   72 ++++++++++++++++++++++++++++++++++++++++++
 includes/fboauth.fboauth.inc |    6 +++
 includes/fboauth.field.inc   |   26 +++++++++++++++
 includes/fboauth.pages.inc   |    7 ++++
 includes/fboauth.profile.inc |   27 ++++++++++++++++
 6 files changed, 139 insertions(+), 1 deletions(-)

diff --git a/fboauth.install b/fboauth.install
index 49ea07f..3ff2441 100644
--- a/fboauth.install
+++ b/fboauth.install
@@ -20,6 +20,7 @@ function fboauth_install() {
 function fboauth_uninstall() {
   variable_del('fboauth_id');
   variable_del('fboauth_secret');
+  variable_del('fboauth_auto_create_account');
   variable_del('fboauth_user_email');
   variable_del('fboauth_user_username');
   variable_del('fboauth_user_profile');
@@ -78,4 +79,3 @@ function _fboauth_change_user_mail_field($action = 'install') {
   db_change_field('users', 'mail', 'mail', $schema['users']['fields']['mail']);
   return $res;
 }
-
diff --git a/fboauth.module b/fboauth.module
index bf54273..1f6d624 100644
--- a/fboauth.module
+++ b/fboauth.module
@@ -82,6 +82,10 @@ function fboauth_block_view($delta) {
 function fboauth_user_insert(&$edit, &$account, $category) {
   if (isset($edit['fboauth_fbid'])) {
     fboauth_save($account->uid, $edit['fboauth_fbid']);
+    // Unset the session var if we used it to create the new user.
+    if (isset($_SESSION['fboauth_fbuser'])) {
+      unset($_SESSION['fboauth_fbuser']);
+    }
   }
 }
 
@@ -419,3 +423,71 @@ function theme_fboauth_user_form_connect($variables) {
   }
   return $output;
 }
+
+/**
+* Modifies the user register form to populate the fields with data retrieved from
+* Facebook after the user has authenticated with Facebook during attempted registration.
+* Implements hook_form_alter().
+*/
+function fboauth_form_user_register_form_alter(&$form, &$form_state) {
+  if (variable_get('fboauth_auto_create_account', 1)) {
+    // Don't change the register form if users are being automatically created.
+    return;
+  }
+
+  global $user;
+  if ($user->uid > 0) {
+    // Don't modify the form for admins attempting to add users.
+    return;
+  }
+
+  if (!isset($_SESSION['fboauth_fbuser'])) {
+    // Don't modify the form if the fbuser isn't found.
+    return;
+  }
+
+  $fbuser = $_SESSION['fboauth_fbuser'];
+
+  // Go through all of the fields in the form and populate them with data on fbuser.
+  $profile_field_values = array();
+  $profile_field_values['mail'] = $fbuser->email;
+  if (variable_get('fboauth_user_username', 'username') == 'username' && !empty($fbuser->username)) {
+    $profile_field_values['name'] = $fbuser->username;
+  }
+  else {
+    $profile_field_values['name'] = $fbuser->name;
+  }
+
+  // Load additional data for fields from the Profile module if it's enabled.
+  if (module_exists('profile')) {
+    module_load_include('inc', 'fboauth', 'includes/fboauth.profile');
+    fboauth_profile_create_user($profile_field_values, $fbuser);
+    $form = _fboauth_set_register_profile_fields($form, $profile_field_values);
+  }
+
+  // Load additional data for fields from the user fields.
+  module_load_include('inc', 'fboauth', 'includes/fboauth.field');
+  fboauth_field_create_user($profile_field_values, $fbuser);
+  $form = _fboauth_set_register_user_fields($form, $profile_field_values);
+  
+  // Pass in the FBID as a hidden value so the hook_user implementation that associates
+  // the FB user and the Drupal user can access it.
+  $form['fboauth_fbid'] = array(
+    '#type' => 'value',
+    '#value' => $fbuser->id,
+  );
+}
+
+/**
+ * Make sure that fboauth's user register form alter hook fires after the Profile module's
+ * form alter hook so that the form elements we need are created (and can thus have their
+ * #default_values adjusted).
+ * Implements hook_module_implements_alter().
+ */
+function fboauth_module_implements_alter(&$implementations, $hook) {
+  if ($hook === "form_alter") {
+    $temp = $implementations['fboauth'];
+    unset($implementations['fboauth']);
+    $implementations['fboauth'] = $temp;
+  }
+}
diff --git a/includes/fboauth.fboauth.inc b/includes/fboauth.fboauth.inc
index a262c07..69e1e95 100644
--- a/includes/fboauth.fboauth.inc
+++ b/includes/fboauth.fboauth.inc
@@ -96,6 +96,12 @@ function fboauth_action_connect($app_id, $access_token) {
     }
     // Register a new user only if allowed.
     elseif (variable_get('user_register', 1)) {
+      // If accounts aren't automatically created, then save the fbuser to the session and go to the
+      // user registration page.
+      if (!variable_get('fboauth_auto_create_account', 1)) {
+        $_SESSION['fboauth_fbuser'] = $fbuser;
+        drupal_goto('user/register');
+      }
       $account = fboauth_create_user($fbuser);
       // Load the account fresh just to have a fully-loaded object.
       $account = user_load($account->uid);
diff --git a/includes/fboauth.field.inc b/includes/fboauth.field.inc
index faae994..268efa1 100644
--- a/includes/fboauth.field.inc
+++ b/includes/fboauth.field.inc
@@ -203,3 +203,29 @@ function fboauth_field_convert_date($facebook_property_name, $fbuser, $field, $i
   }
   return $value;
 }
+
+/**
+* Recursively traverses a Drupal form array (specified by $form), searching for any
+* field specified in $profile_field_values, and sets the default_value for every one
+* it finds.
+* @param $form
+*   The current form array that is being recursed through (either the entire form
+*   or some part of it).
+* @param $profile_field_values
+*   An associative array that maps names of profile fields to values returned from
+*   the API call to Facebook. @see $edit as used by hook_user.
+* @return The $form that was passed in, with modified #default_values.
+*/
+function _fboauth_set_register_user_fields(&$form, &$profile_field_values) {
+  foreach ($form as $key => $value) {
+    if ($key == '#field_name' && in_array($value, array_keys($profile_field_values))) {
+      // TODO: Is there a better way to handle this?  I'm not terribly familiar with the Field API.
+      $form['#default_value'] = $profile_field_values[$value]['und'][0]['value'];
+    }
+    elseif (is_array($value)) {
+      $form[$key] = _fboauth_set_register_user_fields($value, $profile_field_values);
+    }
+  }
+
+  return $form;
+}
diff --git a/includes/fboauth.pages.inc b/includes/fboauth.pages.inc
index 4799573..8973f89 100644
--- a/includes/fboauth.pages.inc
+++ b/includes/fboauth.pages.inc
@@ -27,6 +27,12 @@ function fboauth_settings_form($form, &$form_state) {
     '#description' => t('To use Facebook connect, a Facebook Application must be created. Set up your app in <a href="http://www.facebook.com/developers/apps.php">my apps</a> on Facebook.') . ' ' . t('Enter your App Secret here.'),
     '#default_value' => variable_get('fboauth_secret', ''),
   );
+  $form['fboauth_auto_create_account'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Automatically create account when users register through Facebook'),
+      '#description' => t('If checked, then the user account will automatically be created when the user registers using Facebook, using whatever profile fields are configured.  Otherwise, the normal user registration form is displayed with profile fields pre-filled with Facebook values, and the actual user account is not created until that form is submitted.'),
+      '#default_value' => variable_get('fboauth_auto_create_account', TRUE),
+  );
 
   $form['fboauth_basic_mapping'] = array(
     '#type' => 'fieldset',
@@ -132,6 +138,7 @@ function fboauth_settings_form_validate($form, &$form_state) {
 function fboauth_settings_form_submit($form, &$form_state) {
   variable_set('fboauth_id', $form_state['values']['fboauth_id']);
   variable_set('fboauth_secret', $form_state['values']['fboauth_secret']);
+  variable_set('fboauth_auto_create_account', $form_state['values']['fboauth_auto_create_account']);
 
   variable_set('fboauth_user_email', $form_state['values']['fboauth_user_email']);
   variable_set('fboauth_user_username', $form_state['values']['fboauth_user_username']);
diff --git a/includes/fboauth.profile.inc b/includes/fboauth.profile.inc
index dffca8c..5e0685a 100644
--- a/includes/fboauth.profile.inc
+++ b/includes/fboauth.profile.inc
@@ -136,3 +136,30 @@ function fboauth_profile_create_user(&$edit, $fbuser) {
     }
   }
 }
+
+/**
+* Recursively traverses a Drupal form array (specified by $form), searching for any
+* field specified in $profile_field_values, and sets the default_value for every one
+* it finds.
+* @param $form
+*   The current form array that is being recursed through (either the entire form
+*   or some part of it).
+* @param $profile_field_values
+*   An associative array that maps names of profile fields to values returned from
+*   the API call to Facebook. @see $edit as used by hook_user.
+* @return The $form that was passed in, with modified #default_values.
+*/
+function _fboauth_set_register_profile_fields(&$form, &$profile_field_values) {
+  foreach ($form as $key => $value) {
+    if (!is_numeric($key) && in_array($key, array_keys($profile_field_values))) {
+      if (is_array($form[$key])) {
+        $form[$key]['#default_value'] = $profile_field_values[$key];
+      }
+    }
+    elseif (is_array($value)) {
+      $form[$key] = _fboauth_set_register_profile_fields($value, $profile_field_values);
+    }
+  }
+
+  return $form;
+}
-- 
1.7.2.5

