Index: sf_webform.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/sf_webform/sf_webform.install,v
retrieving revision 1.2
diff -u -p -r1.2 sf_webform.install
--- sf_webform.install	7 Aug 2009 14:38:57 -0000	1.2
+++ sf_webform.install	4 Jan 2011 21:31:07 -0000
@@ -36,10 +36,8 @@ function sf_webform_schema() {
         'default' => '0',
       ),
       'fmid' => array(
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => '0',
+        'type' => 'varchar',
+        'length' => 64,
       ),
     'type' => array(
       'type' => 'int',
@@ -53,3 +51,29 @@ function sf_webform_schema() {
   
   return $schema;
 }
+
+/**
+ * Update schema to reflect fieldmap machine-names instead of numeric indexes. 
+ */
+function sf_webform_update_1() {
+  $return = array();
+  $result = db_query('SELECT `nid`, `fmid`, `type`, `name` FROM {salesforce_webform} sf_w LEFT JOIN salesforce_field_map sf_f ON sf_f.fieldmap = sf_w.fmid');
+  db_change_field($return, 'salesforce_webform', 'fmid', 'fmid', array('type' => 'varchar', 'length' => 64));
+  while ($row = db_fetch_array($result)) {
+    if (empty($row['name'])) {
+      // if 'name' doesn't exist, try to load a fieldmap from defaults
+      $map = salesforce_api_salesforce_field_map_load_by(array('fieldmap' => $row['fmid']));
+      if (empty($map->name)) {
+        db_query('DELETE FROM {salesforce_webform} WHERE fmid = "%s"', $row['fmid']);
+        $return[] = array('success' => TRUE, 'query' => t('Deleted reference to nonexistent fieldmap !fmid', array('!fmid' => $row['fmid'])));
+        continue;
+      }
+      $row['name'] = $map->name;
+    }
+    db_query('UPDATE {salesforce_webform} SET fmid = "%s" WHERE fmid = "%s"', $row['name'], $row['fmid']);
+    $return[] = array('success' => TRUE, 'query' => t('Updated reference to fieldmap !name', array('!name' => $row['name'])));
+  }
+  return $return;
+}
+
+
Index: sf_webform.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/sf_webform/sf_webform.module,v
retrieving revision 1.12
diff -u -p -r1.12 sf_webform.module
--- sf_webform.module	8 Nov 2010 21:59:08 -0000	1.12
+++ sf_webform.module	4 Jan 2011 21:31:07 -0000
@@ -30,7 +30,7 @@ function sf_webform_menu()  {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('sf_webform_associate_webform_node', 4),
     'access arguments' => array('administer salesforce'),
-    'type' => MENU_CALLBACK,
+    'type' => MENU_LOCAL_TASK,
   );
   $items["node/%webform_menu/webform_salesforce"] = array(
     'title' => 'Salesforce Export',
@@ -83,8 +83,8 @@ function sf_webform_form_alter(&$form, $
 
   elseif ($form_id == "salesforce_api_fieldmap_edit_form") {
     $map = salesforce_api_fieldmap_load($form['fieldmap_index']['#value']);
-    if (!empty($map['fields']) && preg_match('/^node_webform_(\d+)$/', $map['drupal'], $matches)) {
-      $nid = $matches[1];
+    if (!empty($map->fields) && strpos($map->drupal, 'node_webform_') === 0) {
+      $nid = (int)str_replace('node_webform_', '', $map->drupal);
       $webform_node = node_load($nid);
       // show the fieldmap and edit link
       $form['webform_fieldmap'] = array(
@@ -95,7 +95,7 @@ function sf_webform_form_alter(&$form, $
         '#collapsed' => FALSE,
       );
       $form['webform_fieldmap']['information'] = array(
-        '#value' => t('This fieldmap is associated with webform node %title (nid %nid) - !link', array("%title" => $webform_node->title, "%nid" => $webform_node->nid, '!link' => l("edit", SALESFORCE_PATH_FIELDMAPS ."/".  $map['fieldmap'] ."/webform", $options = array("query" => "edit=1&destination=". SALESFORCE_PATH_FIELDMAPS ."/". $map['fieldmap'] ."/edit"))))
+        '#value' => t('This fieldmap is associated with webform node %title (nid %nid) - !link', array("%title" => $webform_node->title, "%nid" => $webform_node->nid, '!link' => l("edit", SALESFORCE_PATH_FIELDMAPS ."/".  $map->name ."/webform", $options = array("query" => "edit=1&destination=". SALESFORCE_PATH_FIELDMAPS ."/". $map->name ."/edit"))))
       );
     }
   }
@@ -207,7 +207,7 @@ function sf_webform_salesforce_form($for
     // check for user access processing for this webform
     $access = _sf_webform_get_access($node->salesforce, $submission->uid);
 
-    if ($access && $exported && empty($salesforce_submission['sfid'])) {
+    if ($access && $exported && empty($salesforce_submission->sfid)) {
       $submissions[$submission->sid] = '';
       $form['id'][$submission->sid] = array('#value' => $submission->sid);
       $form['date'][$submission->sid] = array('#value' => $date);
@@ -215,8 +215,8 @@ function sf_webform_salesforce_form($for
       $form['operation'][$submission->sid] = array('#value' => l("View", "node/". $node->nid ."/submission/". $submission->sid));
     }
     elseif ($access && !$exported) {
-      if (empty($salesforce_submission['sfid']) && $salesforce_submission['sfid'] == 0) $submissions[$submission->sid] = '';
-      if (!$show_all && $salesforce_submission['sfid']) continue;
+      if (empty($salesforce_submission->sfid) && $salesforce_submission->sfid == 0) $submissions[$submission->sid] = '';
+      if (!$show_all && $salesforce_submission->sfid) continue;
       $form['id'][$submission->sid] = array('#value' => $submission->sid);
       $form['date'][$submission->sid] = array('#value' => $date);
       $form['remote_addr'][$submission->sid] = array('#value' => $submission->remote_addr);
@@ -303,7 +303,7 @@ function sf_webform_salesforce_bulk_form
       // check for user access processing for this webform
       $access = _sf_webform_get_access($node->salesforce, $submission->uid);
 
-      if ($access && $exported && empty($salesforce_submission['sfid'])) {
+      if ($access && $exported && empty($salesforce_submission->sfid)) {
         $submissions[$submission->sid] = '';
         $form['webform_node'][$nid]['id'][$submission->sid] = array('#value' => $submission->sid);
         $form['webform_node'][$nid]['date'][$submission->sid] = array('#value' => $date);
@@ -311,8 +311,8 @@ function sf_webform_salesforce_bulk_form
         $form['webform_node'][$nid]['operation'][$submission->sid] = array('#value' => l("View", "node/". $node->nid ."/submission/". $submission->sid));
       }
       elseif ($access && !$exported) {
-        if (empty($salesforce_submission['sfid']) && $salesforce_submission['sfid'] == 0) $submissions[$submission->sid] = '';
-        if ($salesforce_submission['sfid']) continue;
+        if (empty($salesforce_submission->sfid) && $salesforce_submission->sfid == 0) $submissions[$submission->sid] = '';
+        if ($salesforce_submission->sfid) continue;
         $form['webform_node'][$nid]['id'][$submission->sid] = array('#value' => $submission->sid);
         $form['webform_node'][$nid]['date'][$submission->sid] = array('#value' => $date);
         $form['webform_node'][$nid]['remote_addr'][$submission->sid] = array('#value' => $submission->remote_addr);
@@ -437,7 +437,9 @@ function sf_webform_webform_submit($form
   $node = $form['#parameters'][2];
 
   // return if the user login status does not match the fieldmap selection
-  if (!_sf_webform_get_access($node->salesforce, $user->uid)) return;
+  if (!_sf_webform_get_access($node->salesforce, $user->uid)) {
+    return;
+  }
 
   $fieldmap = _sf_webform_get_fieldmap_id($node->salesforce);
   $action = variable_get('sf_webform_export_settings', SALESFORCE_WEBFORM_EXPORT_SUBMISSION_CRON);
@@ -470,7 +472,6 @@ function sf_webform_webform_submit($form
  * @return bool
  */
 function _sf_webform_get_access($salesforce, $uid) {
-
   // if process is anon only and user is not logged in then skip process
   if (!isset($salesforce[SALESFORCE_WEBFORM_EXPORT_LOGIN_AUTH]) && !isset($salesforce[SALESFORCE_WEBFORM_EXPORT_LOGIN_BOTH]) && $uid != 0)  {
     return FALSE;
@@ -488,20 +489,11 @@ function _sf_webform_get_access($salesfo
  * Redirect form map id when submitted
  */
 function sf_webform_fieldmap_add_form_submit($form, &$form_state) {
-  if (preg_match('/^node_webform_(\d+)$/', $form_state['values']['drupal_object'], $matches)) {
-    // get the fieldmap id from the redirect url
-    $redirect = split("/", $form_state['redirect']);
-    if (!isset($redirect[4]) || !is_numeric($redirect[4])) {
-      drupal_set_message(t('Unable to create association between webform and fieldmap.  Please try again.'), 'error');
-      $form_state['redirect'] = SALESFORCE_PATH_FIELDMAPS;
-    }
-    else {
-      $index = $redirect[4];
-      $nid = $matches[1];
-      _sf_webform_set_webform_index($nid, $index, SALESFORCE_WEBFORM_EXPORT_LOGIN_BOTH);
-      $form_state['redirect'] = SALESFORCE_PATH_FIELDMAPS .'/'. $index .'/webform';
-    }
-
+  if (strpos($form_state['values']['drupal'], 'node_webform_') === 0) {
+    $map = $form_state['values']['fieldmap'];
+    $nid = (int)str_replace('node_webform_', '', $map->drupal);
+    _sf_webform_set_webform_index($nid, $map->name, SALESFORCE_WEBFORM_EXPORT_LOGIN_BOTH);
+    $form_state['redirect'] = array(SALESFORCE_PATH_FIELDMAPS . '/' . $map->name . '/webform');
   }
 }
 
@@ -526,37 +518,81 @@ function sf_webform_fieldmap_objects($ty
 /**
  * Form to relate webform nodes to fieldmaps.
  */
-function sf_webform_associate_webform_node(&$form_state, $index) {
+function sf_webform_associate_webform_node(&$form_state, $name) {
+  $fieldmap =  salesforce_api_fieldmap_load($name);
+  $sf_webform_info = _sf_webform_get_webform_fieldmap_info($fieldmap->fieldmap);
+
+  // If we found the sf_webform info, load the webform node from that
+  if ($sf_webform_info['nid']) {
+    $node = node_load($sf_webform_info['nid']);
+  }
+  // Otherwise, load the webform node from the fieldmap
+  else {
+    $sf_webform_info['nid'] = (int)str_replace('node_webform_', '', $fieldmap->drupal);
+    $node = node_load($sf_webform_info['nid']);
+  }
+  // If we didn't find a webform associated with this fieldmap, hay problemas
+  if (empty($sf_webform_info['nid']) || empty($node)) {
+    drupal_set_message('Error loading webform.', 'error');
+    drupal_goto(SALESFORCE_PATH_FIELDMAPS);
+    exit;
+  }
 
-  $fieldmap = _sf_webform_get_webform_fieldmap_info($index);
-  $node = node_load($fieldmap['nid']);
   $form['webform'] = array(
     '#type' => 'fieldset',
     '#title' => t('Webform: %title', array('%title' => check_plain($node->title))),
     '#weight' => 0,
     '#collapsible' => TRUE,
     '#collapsed' => FALSE,
-  );
-
-  $form['webform']['fieldmap_index'] = array('#type' => 'hidden', '#value' => $index);
+    'fieldmap' => array('#type' => 'value', '#value' => $fieldmap),
+    'webform_nid' => array('#type' => 'value', '#value' => $sf_webform_info['nid'])
+    );
+  
+  $options = array(
+      SALESFORCE_WEBFORM_EXPORT_LOGIN_BOTH => t('Both anonymous & authenticated users'),
+      SALESFORCE_WEBFORM_EXPORT_LOGIN_ANON => t('Anonymous users only'),
+      SALESFORCE_WEBFORM_EXPORT_LOGIN_AUTH => t('Authenticated users only')
+      );
 
-  // Get all webform nodes that are not associated with a node already.
-  $form['webform']['webform_nid'] = array(
-    '#type' => 'hidden',
-    '#title' => t('Webform node'),
-    '#default_value' => isset($fieldmap['nid']) ? $fieldmap['nid'] : 0,
-    '#description' => t('Select the webform node that this fieldmap should export/import'),
-  );
+  $default = isset($sf_webform_info['type']) ? $sf_webform_info['type'] : SALESFORCE_WEBFORM_EXPORT_LOGIN_BOTH;
 
+  // TODO: Add support for all existing roles.
+  // We can create at most one fieldmap per role per webform. If a fieldmap
+  // already exists for this webform for both anon and auth users, then we
+  // cannot create another fieldmap.
+  $existing_fieldmaps = _sf_webform_get_webform_fieldmapid($node->nid);
+  // Of course, we exclude the current fieldmap when considering existing maps.
+  unset($existing_fieldmaps[$sf_webform_info['type']]);
+  
+  if (isset($existing_fieldmaps[SALESFORCE_WEBFORM_EXPORT_LOGIN_BOTH])
+  || count($existing_fieldmaps) > 1) {
+    drupal_set_message(t('Unable to add additional fieldmap for this webform. A fieldmap has already been created for both anonymous and authenticated users. Please edit an existing fieldmap or create a new webform.'), 'error');
+    drupal_goto(SALESFORCE_PATH_FIELDMAPS);
+    exit;
+  }
+  // If a single other fieldmap exists -- regardless of whether it is for auth 
+  // or anon users, then we cannot create a fieldmap for BOTH auth and anon. 
+  // Therefore, unset the option. Further, if $existing_fieldmaps is not empty 
+  // and we made it past the first condition, we know there is exactly one 
+  // existing fieldmap. Therefore, we unset that option and assign the default 
+  // value to remaining option.
+  // TODO: work out how to swap roles between two maps. IE. if map A exists for 
+  // auth and map B for anon, and i want map B to be auth, how do i do it? As 
+  // far as the UI is concerned, a matrix of existing fieldmaps to existing 
+  // roles would probably be the best way forward. Either that or re-think why 
+  // fieldmaps are restricted to one per role.
+  else {
+    if (!empty($existing_fieldmaps)) {
+      unset($options[SALESFORCE_WEBFORM_EXPORT_LOGIN_BOTH]);
+      unset($options[key($existing_fieldmaps)]);
+      $default = key($options);
+    }
+  }
   $form['webform']['login_status'] = array(
     '#type' => 'radios',
     '#title' => t('User login status'),
-    '#default_value' => isset($fieldmap['type']) ? $fieldmap['type'] : SALESFORCE_WEBFORM_EXPORT_LOGIN_BOTH,
-    '#options' => array(
-      SALESFORCE_WEBFORM_EXPORT_LOGIN_BOTH => t('Both anonymous & authenticated users'),
-      SALESFORCE_WEBFORM_EXPORT_LOGIN_ANON => t('Anonymous users only'),
-      SALESFORCE_WEBFORM_EXPORT_LOGIN_AUTH => t('Authenticated users only')
-      ),
+    '#default_value' => $default,
+    '#options' => $options,
     '#description' => t('Select the user login status when this fieldmap should be used.'),
   );
 
@@ -569,57 +605,18 @@ function sf_webform_associate_webform_no
 }
 
 /**
- * Validate webform to fieldmap association
- * only 1 association declared for both login states allowed
- */
-function sf_webform_associate_webform_node_validate($form, &$form_state) {
-
-  $fieldmap = _sf_webform_get_webform_fieldmap_info($form_state['values']['fieldmap_index']);
-
-  $existing_fieldmaps = _sf_webform_get_webform_fieldmapid($form_state['values']['webform_nid']);
-  // Remove the old setting for this fieldmap from the array of existing ones.
-  unset($existing_fieldmaps[$fieldmap['type']]);
-  $existing_types = array_keys($existing_fieldmaps);
-
-  if (!empty($fieldmap)) {
-    // If the type not same as existing.
-    if ($fieldmap['type'] != $form_state['values']['login_status']) {
-
-      // If an existing fieldmap contains ‘both’ do not allow any additional fieldmaps.
-      if (in_array(SALESFORCE_WEBFORM_EXPORT_LOGIN_BOTH, $existing_types)) {
-        form_set_error('login_status', t('A fieldmap has already been created for both anonymous and authenticated users.'), $reset = FALSE);
-      }
-
-      // Do not allow any new fieldmaps with same type.
-      if (in_array($form_state['values']['login_status'], $existing_types)) {
-        form_set_error('login_status', t('This webform is already associated to a fieldmap for this login status'), $reset = FALSE);
-      }
-
-      // If existing types not empty and new type is 'both'.
-      if (!empty($existing_types) && $form_state['values']['login_status'] == SALESFORCE_WEBFORM_EXPORT_LOGIN_BOTH)  {
-        form_set_error('login_status', t('A fieldmap has already been created for both anonymous and authenticated users.'), $reset = FALSE);
-      }
-    }
-  }
-}
-
-/**
  * Create association between webform node and salesforce fieldmap id
  */
 function sf_webform_associate_webform_node_submit($form, &$form_state) {
-
-  $map = salesforce_api_fieldmap_load($form_state['values']['fieldmap_index']);
+  $map = $form_state['values']['fieldmap'];
 
   // If the fieldmap is being edited then delete existing field association.
-  _sf_webform_remove_webform_index($form_state['values']['webform_nid'], $form_state['values']['fieldmap_index']);
+  _sf_webform_remove_webform_index($form_state['values']['webform_nid'], $map->name);
 
-  $map['fields'] = array();
+  // Save the updated webform fieldmap info.
+  _sf_webform_set_webform_index($form_state['values']['webform_nid'], $map->name, $form_state['values']['login_status']);
 
-  // Save the updated fieldmap.
-  //salesforce_api_fieldmap_save($map);
-  _sf_webform_set_webform_index($form_state['values']['webform_nid'], $map['fieldmap'], $form_state['values']['login_status']);
-
-  $form_state['redirect'] = SALESFORCE_PATH_FIELDMAPS .'/'. $map['fieldmap'] .'/edit';
+  $form_state['redirect'] = SALESFORCE_PATH_FIELDMAPS .'/'. $map->name .'/edit';
 }
 
 /**
@@ -655,31 +652,23 @@ function sf_webform_nodeapi(&$node, $op,
  *   TRUE or FALSE indicating the success of the operation.
  */
 function sf_webform_export($node = NULL, $form_state = NULL, $sfid = NULL, $sid = NULL, $display_errors = FALSE) {
-  global $user;
   $include_file = FALSE;
 
   // Attempt to connect to Salesforce.
   $sf = salesforce_api_connect();
 
-  if (!is_null($sid)) {
-    // if manually exporting or via cron
-    // access webform submission functions webform_submissions.inc. to load submission
-    module_load_include('inc', 'webform', 'includes/webform.submissions');
-    // map elements to correct object fields
-
-    $submission = webform_get_submission($node->nid, $sid);
-    $fieldmap = _sf_webform_get_fieldmap_id($node->salesforce, $submission);
+  module_load_include('inc', 'webform', 'includes/webform.submissions');
+  if (empty($sid) && !empty($form_state['values']['details']['sid'])) {
+    $sid = $form_state['values']['details']['sid'];
   }
   else {
-    $sid = $form_state['values']['details']['sid'];
-    $fieldmap = _sf_webform_get_fieldmap_id($node->salesforce);
+    watchdog('Salesforce - Webform', t('Critical error when trying to export salesforce webform submission. Could not find a submission to export for webform node @nid.', array('@nid' => $node->nid)));
+    return;
   }
 
-  // Create an object for export based on the specified fieldmap.
-  $object = salesforce_api_fieldmap_export_create($fieldmap, $node);
-
-  // Load the fieldmap so we can get the object name.
-  $map = salesforce_api_fieldmap_load($fieldmap);
+  $submission = webform_get_submission($node->nid, $sid);
+  $index = _sf_webform_get_fieldmap_id($node->salesforce, $submission);
+  $map = salesforce_api_fieldmap_load($index);
 
   if (empty($map))  {
     // Otherwise log the error and return FALSE.
@@ -690,41 +679,13 @@ function sf_webform_export($node = NULL,
     return FALSE;
   }
 
-  // Add the form post to the object
-  if (!is_null($form_state))  {
-    // if the form is being submitted directly
-    $data = $form_state['values']['submitted'];
-
-    if ($uid_key = array_search(SALESFORCE_WEBFORM_FIELD_UID, $map['fields'])) {
-      // update object to get salesforce key for a particular user
-      $object->$uid_key = $user->uid;
-    }
-
-    if ($sfid_key = array_search(SALESFORCE_WEBFORM_FIELD_SFID, $map['fields'])) {
-      // update object to get salesforce key for a particular user
-      $user = user_load(array("uid" => $user->uid));
-      $object->$sfid_key = $user->salesforce['sfid'];
-    }
-  }
-  else {
-
-    // use submission data loaded from webform submission inc
-    $data = $submission->data;
-
-    if ($uid_key = array_search(SALESFORCE_WEBFORM_FIELD_UID, $map['fields'])) {
-      // update object to get salesforce key for a particular user
-      $object->$uid_key = $submission->uid;
-    }
-
-    if ($sfid_key = array_search(SALESFORCE_WEBFORM_FIELD_SFID, $map['fields'])) {
-      // update object to get salesforce key for a particular user
-      $webform_user = user_load(array("uid" => $submission->uid));
-      $object->$sfid_key = $webform_user->salesforce['sfid'];
-    }
-
-  }
+  // Create an object for export based on the specified fieldmap.
+  $drupal_data = $node;
+  // Add the submission to the webform node so that we can access it in our
+  // export function.
+  $drupal_data->submission = $submission;
+  $object = salesforce_api_fieldmap_export_create($map->name, $drupal_data);
 
-  $object = sf_webform_process_webform($data, $map, $object);
   // call sfwebform_action hooks for presave actions
   // NB: Calls to the presave hook must return true in order to continue the process
   foreach (module_implements("sfwebform_action") as $module) {
@@ -735,7 +696,7 @@ function sf_webform_export($node = NULL,
   if (empty($sfid)) {
     // Export the object to Salesforce.
     try {
-      $response = $sf->client->create(array($object), $map['salesforce']);
+      $response = $sf->client->create(array($object), $map->salesforce);
     }
     catch (Exception $e) {
       // Log the error message.
@@ -750,7 +711,7 @@ function sf_webform_export($node = NULL,
   }
   else {
     $object->Id = $sfid;
-    $response = $sf->client->update(array($object), $map['salesforce']);
+    $response = $sf->client->update(array($object), $map->salesforce);
   }
 
   // If the export was successful...
@@ -789,36 +750,30 @@ function sf_webform_export($node = NULL,
 function _sf_webform_get_fieldmap_id($fieldmap, $submission = NULL) {
   global $user;
 
-  // get all the possible fieldmaps for this webform node
-  $fieldmap_ids = array_keys($fieldmap);
-
   // if there is only one fieldmap id for this node return
-  if (sizeOf($fieldmap_ids) <= 1) {
-    return $fieldmap[current($fieldmap_ids)]['fmid'];
+  if (count($fieldmap) == 1) {
+    $map = current($fieldmap);
+    return $map['fmid'];
   }
-  else {
-    // if multiple fieldmaps exists for auth and anon
-    // webform submissions data, auth user
-    if (!is_null($submission))  {
-      if ($submission->uid != 0)  {
-        return $fieldmap[SALESFORCE_WEBFORM_EXPORT_LOGIN_AUTH]['fmid'];
-      }
-      else{
-        return $fieldmap[SALESFORCE_WEBFORM_EXPORT_LOGIN_ANON]['fmid'];
-      }
+
+  // if multiple fieldmaps exists for auth and anon
+  // webform submissions data, auth user
+  if (!is_null($submission))  {
+    if ($submission->uid != 0)  {
+      return $fieldmap[SALESFORCE_WEBFORM_EXPORT_LOGIN_AUTH]['fmid'];
     }
-    else {
-      // if user is logged in
-      if ($user->uid != 0) {
-        return $fieldmap[SALESFORCE_WEBFORM_EXPORT_LOGIN_AUTH]['fmid'];
-      }
-      else {
-        // if user is not logged in
-        return $fieldmap[SALESFORCE_WEBFORM_EXPORT_LOGIN_ANON]['fmid'];
-      }
+    else{
+      return $fieldmap[SALESFORCE_WEBFORM_EXPORT_LOGIN_ANON]['fmid'];
     }
   }
-  return;
+  // if user is logged in
+  if ($user->uid != 0) {
+    return $fieldmap[SALESFORCE_WEBFORM_EXPORT_LOGIN_AUTH]['fmid'];
+  }
+  else {
+    // if user is not logged in
+    return $fieldmap[SALESFORCE_WEBFORM_EXPORT_LOGIN_ANON]['fmid'];
+  }
 }
 
 /**
@@ -836,51 +791,130 @@ function _sf_webform_get_fieldmap_object
   if ($webform_node->type == "webform") {
     $objects['label'] = t('Webform:') .' '. $webform_node->title;
     foreach ($webform_node->webform['components'] as $component_id => $component) {
-      $objects['fields']['webform_'. $component_id] = array(
-        'label' => $component['name'],
-        'group' => t('Webform Fields'),
-      );
+      switch ($component['type']) {
+        case 'file':
+        case 'fieldset': {
+          break;
+        }
+        case 'grid': {
+          // TODO: HANDLE GRID 
+          break;
+        }
+        case 'select': {
+          $objects['fields']['webform_' . $component_id . ':key'] = array(
+            'label' => $component['name'] . ' (key)',
+            'group' => t('Webform Fields'),
+            'export' => 'sf_webform_export_component_select',
+            'webform_index' => $component_id,
+          );
+          $objects['fields']['webform_' . $component_id . ':label'] = array(
+            'label' => $component['name'] . ' (value)',
+            'group' => t('Webform Fields'),
+            'export' => 'sf_webform_export_component_select',
+            'webform_index' => $component_id
+          );
+          break;
+        }
+        default: {
+          $objects['fields']['webform_' . $component_id] = array(
+            'label' => $component['name'],
+            'group' => t('Webform Fields'),
+            'export' => 'sf_webform_export_component_default',
+            'webform_index' => $component_id,
+          );
+          break;
+        }
+      }
     }
     $objects['fields'][SALESFORCE_WEBFORM_FIELD_UID] = array(
       'label' => t('Signing User ID'),
       'group' => t('Webform Fields'),
+      'export' => 'sf_webform_export_component_uid',
     );
     $objects['fields'][SALESFORCE_WEBFORM_FIELD_SFID] = array(
       'label' => t('Signing User Salesforce ID'),
       'group' => t('Webform Fields'),
+      'export' => 'sf_webform_export_component_sfid',
     );
   }
   return $objects;
 }
 
-/**
- * Map form post to salesforce object
- *
- * @param $data
- *   The node to export.
- * @param $fieldmap
- *   The fieldmap to use to create the export object.
- * @param $object
- *	 The object to map the data to
- * @return
- *   object ready for submission to salesforce
- */
-function sf_webform_process_webform($data, $fieldmap, $object) {
-  foreach ($fieldmap['fields'] as $component => $form_key)  {
-    if (strpos($form_key, "webform") !== FALSE && empty($object->$component)) {
-      $key = explode("_", $form_key);
-
-      // TODO: find better method for dealing with submission arrays
-      if (is_array($data[$key[1]])) {
-        $object->$component = $data[$key[1]]['value'][0];
+function sf_webform_export_component_default($webform, $fieldname, $drupal_field_definition, $sf_field_definition) {
+  $data = $webform->submission->data;
+  $index = $drupal_field_definition['webform_index'];
+  if (empty($data[$index]) || !isset($data[$index]['value'])) {
+    return NULL;
+  }
+  $value = $data[$index]['value'];
+  
+  return _sf_webform_export_get_value($value, $sf_field_definition);
+}
+
+function sf_webform_export_component_select($webform, $fieldname, $drupal_field_definition, $sf_field_definition) {
+  list($fieldname, $column) = explode(':', $fieldname);
+  if (empty($column)) {
+    $column = 'key';
+  }
+  $data = $webform->submission->data;
+  $index = $drupal_field_definition['webform_index'];
+  if (empty($data[$index]) || !isset($data[$index]['value'])) {
+    return NULL;
+  }
+  $value = $data[$index]['value'];
+
+  // If the user wants to use the label text instead of the machine key, fetch
+  // it from the component definition and return that instead.
+  if ($column == 'label') {
+    $text = $webform->webform['components'][$index]['extra']['items'];
+    $rows = array_filter(explode("\n", trim($text)));
+    $options = array();
+    foreach ($rows as $row) {
+      list($key, $label) = explode('|', $row);
+      $options[$key] = $label;
+    }
+    $value = array_combine($value, $value);
+    $value = array_intersect_key($options, $value);
+    $value = array_values($value);
+  }
+  return _sf_webform_export_get_value($value, $sf_field_definition);
+}
+
+function _sf_webform_export_get_value($webform_value, $sf_field_definition) {
+  switch ($sf_field_definition['salesforce']['type']) {
+    case  'multipicklist': {
+      if(is_array($webform_value)) {
+        // SF wants a semicolon-delimited string for multipicklist values
+        $value = implode(';', $webform_value);
       }
-      else {
-        $object->$component = $data[$key[1]];
+      break;
+    }
+    case 'boolean': {
+      if (is_array($webform_value)) {
+        $value = current($webform_value);
+      }
+      // If we are dealing with a string, we try to assign sane values.
+      // This is not an ideal solution, but we cannot rely on webform admins to
+      // understand the difference between integer values and text.
+      if (in_array($webform_value, array('NO', 'No', 'no', 'FALSE', 'False', 'false', 'NULL', 'Null', 'null', '0', NULL, FALSE))) {
+        $value = 0;
       }
+      break;
+    }
+    default: {
+      $value = current($webform_value);
     }
   }
+  return $value;
+}
+
+function sf_webform_export_component_uid($webform, $fieldname, $drupal_field_definition, $sf_field_definition) {
+  return $webform->submission->uid;
+}
 
-  return $object;
+function sf_webform_export_component_sfid($webform, $fieldname, $drupal_field_definition, $sf_field_definition) {
+  $account = user_load($webform->submission->uid);
+  return $account->salesforce->sfid;
 }
 
 /**
@@ -941,7 +975,7 @@ function _sf_webform_get_webform_fieldma
  * @return array
  */
 function _sf_webform_get_webform_nid($fmid) {
-  return db_result(db_query("SELECT nid FROM {salesforce_webform} WHERE `fmid` = %d", $fmid));
+  return db_result(db_query("SELECT nid FROM {salesforce_webform} WHERE `fmid` = '%s'", $fmid));
 }
 
 /**
@@ -950,7 +984,7 @@ function _sf_webform_get_webform_nid($fm
  * @return array
  */
 function _sf_webform_get_webform_fieldmap_info($fmid) {
-  return db_fetch_array(db_query("SELECT fmid, nid, type FROM {salesforce_webform} WHERE `fmid` = %d", $fmid));
+  return db_fetch_array(db_query("SELECT fmid, nid, type FROM {salesforce_webform} WHERE `fmid` = '%s'", $fmid));
 }
 
 /**
@@ -960,7 +994,7 @@ function _sf_webform_get_webform_fieldma
  * @param $login_status
  */
 function _sf_webform_set_webform_index($nid, $fieldmap_index, $login_status) {
-  if (db_query("INSERT INTO {salesforce_webform} (`nid`, `fmid`, `type`) VALUES (%d, %d, %d);", $nid, $fieldmap_index, $login_status)) {
+  if (db_query("INSERT INTO {salesforce_webform} (`nid`, `fmid`, `type`) VALUES (%d, '%s', %d);", $nid, $fieldmap_index, $login_status)) {
     watchdog('Salesforce Webform', 'Webform node %nid successfully related to the fieldmap %fieldmap_index', array("%nid" => $nid, "%fieldmap_index" => $fieldmap_index));
   }
   else {
@@ -975,7 +1009,7 @@ function _sf_webform_set_webform_index($
  * @param $fieldmap_index
  */
 function _sf_webform_remove_webform_index($nid, $fieldmap_index) {
-  if (db_query("DELETE FROM {salesforce_webform} WHERE `fmid` = %d", $fieldmap_index))  {
+  if (db_query("DELETE FROM {salesforce_webform} WHERE `fmid` = '%s'", $fieldmap_index))  {
     watchdog('Salesforce Webform', 'Removed webform %nid link with %fieldmap_index', array("%nid" => $nid, "%fieldmap_index" => $fieldmap_index));
   }
   else {
@@ -1026,7 +1060,7 @@ function sf_webform_cron() {
       $webform_submissions = webform_get_submissions($node->nid);
       foreach ($webform_submissions as $sid => $submission) {
         $salesforce_submission = salesforce_api_id_load('webform', $sid);
-        if ($salesforce_submission['sfid']) continue;
+        if ($salesforce_submission->sfid) continue;
         $success = sf_webform_export($node, NULL, NULL, $sid);
         if ($success) {
           $count++;
@@ -1043,5 +1077,5 @@ function sf_webform_cron() {
  * Delete a webform / fieldmap association
  */
 function sf_webform_fieldmap_delete_form_submit($form, $form_state) {
-  return db_query("DELETE FROM {salesforce_webform} WHERE fmid = %d", $form_state['values']['fieldmap_index']);
+  return db_query("DELETE FROM {salesforce_webform} WHERE fmid = '%s'", $form_state['values']['fieldmap_index']);
 }
