You are here

sf_user.module in Salesforce Suite 6.2

Same filename and directory in other branches
  1. 5.2 sf_user/sf_user.module

Integrates the core user object and profile module with the Salesforce API.

File

sf_user/sf_user.module
View source
<?php

/**
 * @file
 * Integrates the core user object and profile module with the Salesforce API.
 */

/**
 * Implementation of hook_menu().
 */
function sf_user_menu() {
  $items['user/%user/salesforce'] = array(
    'title' => 'Salesforce',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'sf_user_salesforce_form',
      1,
    ),
    'access callback' => 'sf_user_salesforce_form_access',
    'access arguments' => array(
      'administer salesforce',
    ),
    'type' => MENU_LOCAL_TASK,
  );
  return $items;
}

// Access callback for the user/%user/salesforce menu item.
function sf_user_salesforce_form_access() {
  return user_access('administer salesforce') and salesforce_api_fieldmap_options('user');
}

/**
 * Implementation of hook_form_alter().
 */
function sf_user_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'salesforce_api_settings_form') {
    $form['sf_user'] = array(
      '#type' => 'fieldset',
      '#title' => t('User integration'),
      '#description' => t('Placeholder for any user integration settings.'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#weight' => -1,
      // The admin form is getting cluttered. This is going to be hidden until
      // there is actually something here:
      '#access' => FALSE,
    );
  }
}

/**
 * Implementation of hook_user().
 */
function sf_user_user($op, &$edit, &$account, $category = NULL) {
  static $sf_user_skip_export;
  switch ($op) {
    case 'load':
      $account->salesforce = salesforce_api_id_load('user', $account->uid);
      break;
    case 'delete':
      $maps = salesforce_api_salesforce_field_map_load_by(array(
        'drupal' => 'user',
      ));
      $map = current($maps);
      if ($map->automatic & SALESFORCE_AUTO_SYNC_DELETE) {
        $continue = TRUE;
        $continues = module_invoke_all('salesforce_api_delete', $account->salesforce->sfid, $map, $account->uid);
        if (!empty($continues)) {
          foreach ($continues as $continue) {
            if ($continue === FALSE) {
              break;
            }
          }
        }
        if ($continue) {
          salesforce_api_delete_salesforce_objects($account->salesforce->sfid);
        }
      }
      salesforce_api_delete_object_map('user', $account->uid);
      break;
    case 'update':

      // Set a static variable during 'update' to prevent extranesous API calls.
      // In 'after_update', $account has been reloaded from the database, and
      // sf_user_skip_export will have been unset. Also set the same property in
      // $edit array to NULL so that it won't get written to the database, and
      // to remove any "legacy" data.
      if ($account->sf_user_skip_export) {
        $sf_user_skip_export = TRUE;
        $edit['sf_user_skip_export'] = NULL;
      }
      break;
    case 'insert':
    case 'after_update':

      // When importing *from* Salesforce, don't export *back* to Salesforce.
      if (isset($account->sf_user_skip_export) || $sf_user_skip_export || isset($edit['sf_user_skip_export'])) {

        // We don't want this value to get into the $account->data array, so set
        // it to null in the $edit array to make sure that doesn't happen. This
        // will also unset any "legacy" data.
        $edit['sf_user_skip_export'] = NULL;
        unset($sf_user_skip_export);
        break;
      }
      $salesforce = (object) array(
        'name' => NULL,
        'sfid' => NULL,
      );
      if ($account->uid) {
        $salesforce = salesforce_api_id_load('user', $account->uid);
      }

      // If we have an existing link, attempt to load the assoc'd map.
      if (!empty($salesforce->name)) {
        $map = salesforce_api_fieldmap_load($salesforce->name);
      }

      // If the sf link wasn't found, or if it was found but assoc'd to a
      // non-existent map, grab any maps assoc'd with this node type.
      if (empty($salesforce->name) || empty($map)) {
        $maps = salesforce_api_salesforce_field_map_load_by(array(
          'drupal' => 'user',
        ));
        if (empty($maps)) {
          break;
        }
      }
      else {
        $maps = array(
          $map->name => $map,
        );
      }
      foreach ($maps as $map) {
        $auto_create = $map->automatic & SALESFORCE_AUTO_SYNC_CREATE;
        $auto_update = $map->automatic & SALESFORCE_AUTO_SYNC_UPDATE;
        if (!$auto_create && $op == 'insert' || !$auto_update && $op == 'after_update') {
          unset($maps[$map->name]);
        }
      }

      // If all our maps were unset, abort this procedure.
      if (empty($maps)) {
        break;
      }

      // Otherwise, use the first fieldmap.
      $map = reset($maps);
      $salesforce->name = $map->name;

      // Check if there is more than one fieldmap in the result.
      if (user_access('administer salesforce') and next($maps)) {
        if (!empty($map->description)) {
          $description = '(' . $map->description . ')';
        }
        drupal_set_message(t('Warning: more than one "automatic" salesforce mapping detected. Used fieldmap !map_name @map_description.', array(
          '!map_name' => l($map->name, SALESFORCE_PATH_FIELDMAPS . '/' . $map->name . '/edit'),
          '@map_description' => $description,
        )), 'warning');
      }

      // Finally export the user to salesforce
      try {
        sf_user_export($account->uid, $salesforce->name, $salesforce->sfid);
      } catch (Exception $e) {
        salesforce_api_log(SALESFORCE_LOG_SOME, 'Exception while attempting to export user: ' . $e
          ->getMessage(), array(), WATCHDOG_ERROR, l('user ' . $account->uid, 'user/' . $account->uid));
      }
      break;
  }
}

/**
 * Implementation of hook_fieldmap_objects().
 */
function sf_user_fieldmap_objects($type) {
  $objects = array();

  // Define the data fields available for Drupal objects.
  if ($type == 'drupal') {
    $objects['user'] = array(
      'label' => t('User account'),
      'fields' => array(
        'uid' => array(
          'label' => t('User ID'),
          'type' => SALESFORCE_FIELD_SOURCE_ONLY,
        ),
        'name' => array(
          'label' => t('Username'),
        ),
        'mail' => array(
          'label' => t('E-mail address'),
        ),
        'created' => array(
          'label' => t('Created timestamp'),
        ),
        'access' => array(
          'label' => t('Last access timestamp'),
        ),
        'login' => array(
          'label' => t('Last login timestamp'),
        ),
        'status' => array(
          'label' => t('Account status'),
        ),
        'picture' => array(
          'label' => t('Picture'),
        ),
      ),
    );

    // Add profile fields to the user object if the module is enabled.
    if (module_exists('profile')) {

      // Load all the profile fields from the database.
      $result = db_query("SELECT fid, name, title, category, type FROM {profile_fields} ORDER BY category, weight");

      // Loop through the fields and add them to the Drupal user object.
      while ($field = db_fetch_array($result)) {
        if ($field['type'] != 'date') {
          $objects['user']['fields'][$field['name']] = array(
            'label' => t('@category: @title', array(
              '@category' => $field['category'],
              '@title' => $field['title'],
            )),
            'group' => t('Profile fields'),
          );
        }
        else {
          $objects['user']['fields'][$field['name']] = array(
            'label' => t('@category: @title', array(
              '@category' => $field['category'],
              '@title' => $field['title'],
            )),
            'group' => t('Profile fields'),
            'export' => '_sf_user_export_profile_date',
          );
        }
      }
    }
  }
  return $objects;
}

// Displays the Salesforce synchronization form.
function sf_user_salesforce_form(&$form_state, $account) {

  // Fail out if the user didn't exist!
  if (!$account->uid) {
    drupal_not_found();
  }
  if (isset($form_state['storage']['confirm'])) {
    $form['account'] = array(
      '#type' => 'value',
      '#value' => $account,
    );
    return confirm_form($form, 'Are you sure you want to unlink this user from Salesforce?', 'user/' . $account->uid . '/salesforce', 'Unlinking this object will remove the connection between the Drupal object and the Salesforce record. This action will <strong>not</strong> delete the Drupal object or the Salesforce record. This cannot be undone.', 'Unlink', 'Cancel');
  }

  // Set the user page title.
  drupal_set_title(check_plain($account->name));
  $form = array();
  $form['uid'] = array(
    '#type' => 'value',
    '#value' => $account->uid,
  );
  if ($account->salesforce->sfid) {

    // Retrieve the object from Salesforce.
    $sf_data = salesforce_api_retrieve(array(
      $account->salesforce->sfid,
    ), $account->salesforce->name);

    // Check to see if salesforce_api_retrieve returned an array of objects
    if (is_array($sf_data) && count($sf_data) > 0) {
      $sf_data = $sf_data[0];
    }
    if (!$sf_data && SALESFORCE_DELETED_POLICY_UPSERT == variable_get('salesforce_api_entity_deleted_policy', SALESFORCE_DELETED_POLICY_UPSERT)) {

      // Unlink the object
      salesforce_api_id_unlink(array(
        'oid' => $account->uid,
        'name' => $account->salesforce->name,
      ));
      $account = user_load($account->uid);
    }
    elseif (!$sf_data) {
      drupal_set_message(t('Unable to retrieve Salesforce data for record !sfid.', array(
        '!sfid' => $account->salesforce->sfid,
      )), 'warning');
    }
  }

  // Display an export button if the user hasn't been exported before.
  if (!$account->salesforce->sfid) {
    $form['export'] = array(
      '#type' => 'fieldset',
      '#title' => t('Export user to Salesforce'),
      '#description' => t('This user may be exported to Salesforce using any fieldmap listed below.'),
    );

    // Get an array of fieldmaps that export users of this type to Salesforce.
    $options = salesforce_api_fieldmap_options('user');

    // Add the export form
    $form['export']['name'] = array(
      '#type' => 'select',
      '#title' => t('Export fieldmap'),
      '#options' => $options,
    );
    $form['export']['manual_linking'] = array(
      '#type' => 'fieldset',
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#title' => t('Manual linking'),
    );
    $form['export']['manual_linking']['sfid'] = array(
      '#type' => 'textfield',
      '#title' => t('Salesforce ID'),
      '#description' => t('If this node already has a corresponding object
      in Salesforce, enter the Salesforce ID to manually link the entities.
      Salesforce record will be linked using the fieldmap selected above.
      <strong>Please ensure that the Salesforce object type matches that of
      fieldmap selected above.</strong>.<br /><br /><em>Create Link</em> will
      link two Drupal and Salesforce records, leaving field values unchanged.
      <br /><em>Export Node</em> will upsert the Drupal record, inserting or
      updating any Salesforce record as necessary.'),
      '#size' => 18,
      '#maxlength' => 18,
    );
    $form['export']['manual_linking']['link'] = array(
      '#type' => 'submit',
      '#value' => t('Create Link'),
    );
    $form['export']['export_user'] = array(
      '#type' => 'submit',
      '#value' => t('Export user'),
    );
  }
  else {

    // Otherwise add synchronization information.
    $form['sfid'] = array(
      '#type' => 'value',
      '#value' => $account->salesforce->sfid,
    );
    $form['name'] = array(
      '#type' => 'value',
      '#value' => $account->salesforce->name,
    );

    // Load the fieldmap data.
    $map = salesforce_api_fieldmap_load($account->salesforce->name);
    $sf_object_definition = salesforce_api_fieldmap_objects_load('salesforce', $map->salesforce);
    $export_data = salesforce_api_fieldmap_export_create($account->salesforce->name, $account);
    $header = array(
      t('Field name'),
      t('Drupal user value'),
      t('Salesforce @type value', array(
        '@type' => salesforce_api_fieldmap_object_label('salesforce', $map->salesforce),
      )),
    );
    $rows = array();
    foreach ($map->fields as $sf_fieldname => $drupal_fieldname) {
      $rows[] = array(
        $sf_object_definition['fields'][$sf_fieldname]['label'],
        $export_data->{$sf_fieldname},
        $sf_data->{$sf_fieldname},
      );
    }
    $form['mapped'] = array(
      '#type' => 'fieldset',
      '#title' => t('Mapped field values'),
      '#description' => t('<a href="!url">Edit this fieldmap</a>.', array(
        '!url' => url(SALESFORCE_PATH_FIELDMAPS . '/' . $account->salesforce->name . '/edit'),
      )),
    );
    $form['mapped']['fieldmap_values'] = array(
      '#value' => theme('table', $header, $rows),
    );
    $form['mapped']['export_values'] = array(
      '#type' => 'submit',
      '#value' => t('Export changes to Salesforce'),
      '#attributes' => array(
        'class' => 'sf-confirm',
      ),
    );
    $form['mapped']['import_values'] = array(
      '#type' => 'submit',
      '#value' => t('Import changes from Salesforce'),
      '#attributes' => array(
        'class' => 'sf-confirm',
      ),
    );
    $form['mapped']['unlink'] = array(
      '#type' => 'submit',
      '#value' => t('Unlink from Salesforce object...'),
      '#attributes' => array(
        'class' => 'sf-confirm',
      ),
    );

    // Create a table for the unmapped fields.
    $header = array(
      t('Field name'),
      t('Salesforce @type value', array(
        '@type' => salesforce_api_fieldmap_object_label('salesforce', $map->salesforce),
      )),
    );
    $rows = array();
    foreach ((array) $sf_data as $key => $value) {
      if (!isset($map->fields[$key]) && isset($sf_object_definition['fields'][$key])) {
        $rows[] = array(
          $sf_object_definition['fields'][$key]['label'],
          $value,
        );
      }
    }
    if (count($rows) > 0) {
      $form['unmapped'] = array(
        '#type' => 'fieldset',
        '#title' => t('Unmapped fields'),
        '#description' => t('These fields are available on Salesforce but are not currently mapped through the fieldmap used for this user. Some of these values may only be available when importing from Salesforce.'),
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
      );
      $form['unmapped']['unmmaped_fields'] = array(
        '#value' => theme('table', $header, $rows),
      );
    }
    $rows = array();
    foreach (salesforce_api_fieldmap_system_fields() as $key => $value) {
      $rows[] = array(
        $value['label'],
        $sf_data->{$key},
      );
    }
    $form['system'] = array(
      '#type' => 'fieldset',
      '#title' => t('System fields'),
      '#description' => t('These fields provide additional system information about the Salesforce object but cannot be exported to Salesforce.'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    $form['system']['system_fields'] = array(
      '#value' => theme('table', $header, $rows),
    );
    $form['raw'] = array(
      '#type' => 'fieldset',
      '#title' => t('Raw data'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    $form['raw']['data'] = array(
      '#value' => '<pre>' . print_r($sf_data, TRUE) . '</pre>',
    );
  }
  return $form;
}
function sf_user_salesforce_form_submit($form, &$form_state) {
  switch ($form_state['values']['op']) {

    // Export the user to Salesforce.
    case t('Export user'):
    case t('Export changes to Salesforce'):
      if (sf_user_export($form_state['values']['uid'], $form_state['values']['name'], $form_state['values']['sfid'])) {
        drupal_set_message(t('User successfully exported to Salesforce.'));
      }
      else {
        drupal_set_message(t('An error occurred while exporting the user to Salesforce.  Check the watchdog for more information.'), 'error');
      }
      break;

    // Import changes from Salesforce.
    case t('Import changes from Salesforce'):
      if (sf_user_import($form_state['values']['sfid'], $form_state['values']['name'], $form_state['values']['uid'])) {
        drupal_set_message(t('The user has been updated with values from Salesforce.'));
      }
      else {
        drupal_set_message(t('An error occurred while importing the changes from Salesforce.  Check the watchdog for more information.'), 'error');
      }
      break;
    case $form_state['values']['link']:
      if (!is_sfid($form_state['values']['sfid'])) {
        drupal_set_message(t('Invalid SFID provided.'), 'error');
        break;
      }
      salesforce_api_id_save('user', $form_state['values']['uid'], $form_state['values']['sfid'], $form_state['values']['fieldmap'], 'link');
      break;
    case $form_state['values']['unlink']:
    case t('Unlink'):
      if (!isset($form_state['storage']['confirm'])) {
        $form_state['storage']['confirm'] = TRUE;
        $form_state['rebuild'] = TRUE;
      }
      else {
        unset($form_state['storage']['confirm']);
        $account = $form_state['values']['account'];
        salesforce_api_id_unlink(array(
          'oid' => $account->uid,
          'name' => $account->salesforce->name,
        ));
        drupal_set_message(t('The user !uid has been unlinked from Salesforce record !sfid.', array(
          '!uid' => $account->uid,
          '!sfid' => $account->salesforce->sfid,
        )));
      }
      break;
  }
}

/**
 * Exports a user to Salesforce using the specified fieldmap and stores the
 *   ID of the Salesforce object for the user.
 *
 * @param $uid
 *   The uid of the user to export.
 * @param $name
 *   The name of the fieldmap to use to create the export object.
 * @param $sfid
 *   The Salesforce ID of the object you want to update.  If left NULL, a new
 *     object will be created at Salesforce.
 * @return
 *   TRUE or FALSE indicating the success of the operation.
 */
function sf_user_export($uid, $name, $sfid = NULL) {

  // Attempt to connect to Salesforce.
  $sf = salesforce_api_connect();
  if (!$sf) {

    // Let modules react to a failure to export this user.
    module_invoke_all('salesforce_api_export_connect_fail', $uid, $name, $sfid);
    if (user_access('administer salesforce')) {
      drupal_set_message(t('Unable to connect to Salesforce using <a href="!url">current credentials</a>.', array(
        '!url' => url(SALESFORCE_PATH_ADMIN),
      )));
    }
    return FALSE;
  }

  // Load the user.
  $account = user_load(array(
    'uid' => $uid,
  ));

  // Create an object for export based on the specified fieldmap.
  $object = salesforce_api_fieldmap_export_create($name, $account);

  // Load the fieldmap so we can get the object name.
  $map = salesforce_api_fieldmap_load($name);
  if (empty($sfid)) {

    // Look for any matching records which we might want to update instead of creating duplicates.
    $matches = salesforce_api_search_for_duplicates('export', 'user', $account, $name);
    if (!empty($matches)) {
      $object->Id = $sfid = reset($matches);
      $account->salesforce = array(
        'sfid' => $sfid,
        'name' => $name,
      );
      salesforce_api_id_save('user', $account->uid, $sfid, $name, 'export');
    }
  }
  else {
    $object->Id = $sfid;
  }
  $fieldmap_name = $name;
  foreach (module_implements('salesforce_api_pre_export') as $module) {
    $function = $module . '_salesforce_api_pre_export';
    $continue = $function($object, $map, $account->uid);
    if ($continue === FALSE) {
      return;
    }
  }

  // If any modules altered the fieldmap, ensure that the new fieldmap name
  // is used for the rest of the export.
  if ($map->name != $name) {
    $name = $map->name;
  }
  try {
    $response = $sf->client
      ->upsert('Id', array(
      $object,
    ), $map->salesforce);
  } catch (Exception $e) {
    salesforce_api_log(SALESFORCE_LOG_SOME, 'Exception while attempting to export user: %msg <pre>%e</pre>', array(
      '%msg' => $e
        ->getMessage(),
      '%e' => print_r($e, TRUE),
    ), WATCHDOG_ERROR, l('user ' . $account->uid, 'user/' . $account->uid));
  }

  // Check to see if response is an array of objects
  if (is_array($response) && count($response) > 0) {
    $response = $response[0];
  }

  // If we got errors, handle them before proceeding
  if (is_object($response->errors)) {

    // If we got "Entity is deleted" and we're configured to unlink and upsert,
    // do it. @see sf_node_export()
    if ($response->errors->statusCode == 'ENTITY_IS_DELETED' && ($response->errors->fields == 'Id' || empty($response->errors->fields)) && SALESFORCE_DELETED_POLICY_UPSERT == variable_get('salesforce_api_entity_deleted_policy', SALESFORCE_DELETED_POLICY_UPSERT)) {
      salesforce_api_id_unlink(array(
        'sfid' => $object->Id,
      ));
      $account->salesforce->sfid = $object->Id = NULL;

      // Look for any matching records which we might want to update instead of creating duplicates.
      $matches = salesforce_api_search_for_duplicates('export', 'user', $account, $name);
      if (!empty($matches)) {
        $object->Id = reset($matches);
      }
      salesforce_api_log(SALESFORCE_LOG_SOME, 'Salesforce entity deleted. Attempting to unlink and upsert. <pre>%response</pre>', array(
        '%response' => print_r($response, 1),
      ), WATCHDOG_ERROR, l('user ' . $uid, 'user/' . $uid));
      try {
        $response = $sf->client
          ->upsert('Id', array(
          $object,
        ), $map->salesforce);
      } catch (Exception $e) {
        salesforce_api_log(SALESFORCE_LOG_SOME, 'Exception while attempting to export user: %msg <pre>%e</pre>', array(
          '%msg' => $e
            ->getMessage(),
          '%e' => print_r($e, TRUE),
        ), WATCHDOG_ERROR, l('user ' . $account->uid, 'user/' . $account->uid));
      }
    }
  }

  // If the export was successful...
  if ($response->success) {

    // Store the Salesforce ID for the user and return TRUE.
    salesforce_api_id_save('user', $uid, $response->id, $name, 'export');
  }
  else {

    // Otherwise log the error and return FALSE.
    if (user_access('administer salesforce')) {
      if (function_exists('dsm')) {
        dsm($response);
      }
      else {
        if (user_access('administer salesforce')) {
          drupal_set_message(t('Salesforce Suite export error: <pre>%response</pre>', array(
            '%response' => print_r($response, 1),
          )), 'error');
        }
      }
    }
    salesforce_api_log(SALESFORCE_LOG_SOME, 'Salesforce returned an unsuccessful response: <pre>%response</pre>', array(
      '%response' => print_r($response, 1),
    ), WATCHDOG_ERROR, l('user ' . $account->uid, 'user/' . $account->uid));
  }
  module_invoke_all('salesforce_api_post_export', $object, $name, $uid, $response);
  return $response->success;
}

/**
 * Imports data from Salesforce into a user.
 *
 * @param $sf_data
 *   The Salesforce Object OR The Salesforce ID of the object to be imported.
 * @param $name
 *   The name of the fieldmap to use to create the export object.
 * @param $uid
 *   The uid of the user to update.  If left NULL, a new user will be created.
 * @return
 *   The uid of the imported user or FALSE on failure.
 */
function sf_user_import($sf_data, $name, $uid = NULL, $options = array()) {

  // Retrieve the object from Salesforce.
  $sf = salesforce_api_connect();
  if (!$sf) {
    if (user_access('administer salesforce')) {
      drupal_set_message(t('Unable to connect to Salesforce using <a href="!url">current credentials</a>.', array(
        '!url' => url(SALESFORCE_PATH_ADMIN),
      )));
    }
    return FALSE;
  }
  if (is_sfid($sf_data)) {
    $sf_data = salesforce_api_retrieve(array(
      $sf_data,
    ), $name);

    // Check to see if sf_data is an array of objects
    if (is_array($sf_data) && count($sf_data) > 0) {
      $sf_data = $sf_data[0];
    }
  }
  elseif (is_array($sf_data)) {
    $sf_data = (object) $sf_data;
  }
  if (empty($sf_data)) {
    return FALSE;
  }

  // Load the fieldmap data.
  $map = salesforce_api_fieldmap_load($name);

  // Load the object definitions.
  $drupal_object_definition = salesforce_api_fieldmap_objects_load('drupal', $map->drupal);
  $salesforce_object_definition = salesforce_api_fieldmap_objects_load('salesforce', $map->salesforce);

  // If a user was specified, attempt to load it.
  $account = user_load(array(
    'uid' => $uid,
  ));
  if (empty($uid) || empty($account)) {

    // Look for any matching records which we might want to update instead of creating duplicates.
    $matches = salesforce_api_search_for_duplicates('import', 'user', $sf_data, $name);
    if (!empty($matches)) {
      $uid = reset($matches);
      if (!empty($uid)) {
        $account = user_load($uid);
      }
    }
  }

  // Loop through the fields on the fieldmap.
  $changes = array();
  foreach ($map->fields as $sf_fieldname => $drupal_fieldname) {

    // If a handler is specified for importing a value from Salesforce.
    if (isset($drupal_object_definition['fields'][$drupal_fieldname]['import'])) {
      $drupal_field_import_handler = $drupal_object_definition['fields'][$drupal_fieldname]['import'];
      $drupal_field_definition = $drupal_object_definition['fields'][$drupal_fieldname];
      $sf_field_definition = $salesforce_object_definition['fields'][$sf_fieldname];

      // Get the value for the field from the handler function.
      $change = $drupal_field_import_handler($account, $drupal_fieldname, $drupal_field_definition, $sf_data, $sf_fieldname, $sf_field_definition);
      if (is_array($changes) && is_array($change)) {
        $changes = array_merge($changes, $change);
      }
      else {
        salesforce_api_log(SALESFORCE_LOG_ALL, t('@import_handler import handler did not return an array!'), array(
          '@import_handler' => $drupal_field_import_handler,
        ), WATCHDOG_ERROR);
      }
    }
    elseif (isset($sf_data->{$sf_fieldname}) && !empty($drupal_fieldname)) {
      $changes[$drupal_fieldname] = $sf_data->{$sf_fieldname};
    }
  }
  foreach (module_implements('salesforce_api_pre_import') as $module) {
    $function = $module . '_salesforce_api_pre_import';
    $continue = $function($account, $name, $sf_data, $changes);
    if ($continue === FALSE) {
      return;
    }
  }

  // Check for changes made to the account
  $num_changes = 0;
  foreach ($changes as $key => $value) {
    if (!empty($value)) {
      if (!isset($account->{$key})) {
        $num_changes++;
      }
      elseif ($account->{$key} != $value) {
        $num_changes++;
      }
    }
  }

  // If no changes have been made, there is no need to save
  if ($num_changes == 0) {

    // Nothing changed, so do not do the save
    // Return the user ID to signal a "successful" save
    return $account->uid;
  }

  //drupal_set_message('<pre>'. print_r($changes, TRUE) .'</pre>');

  // We don't want to trigger an export while we're running import.
  // sf_user_skip_export is a flag to tell hook_user not to export this object.
  $account->sf_user_skip_export = TRUE;

  // If the user exists, update the existing user.
  if ($account->uid) {
    $account = user_save($account, $changes);
    if ($account == FALSE) {

      // User account not saved
      if (user_access('administer salesforce')) {
        drupal_set_message(t('A user account could not be imported for update. A required field for Drupal may be missing. <pre>%sf_data</pre>', array(
          '%sf_data' => print_r($sf_data, TRUE),
        )), 'error');
      }
      salesforce_api_log(SALESFORCE_LOG_ALL, t('A user account could not be imported for update. A required field for Drupal may be missing. <pre>%sf_data</pre>', array(
        '%sf_data' => print_r($sf_data, TRUE),
      )), WATCHDOG_ERROR);
      return FALSE;
    }
    $create = FALSE;
  }
  else {

    // Pass a dummy account object for inserts.
    $account = (object) array(
      'sf_user_skip_export' => TRUE,
      'uid' => FALSE,
    );
    $account = user_save($account, $changes);
    if ($account == FALSE) {

      // User account not saved
      if (user_access('administer salesforce')) {
        drupal_set_message(t('A user account could not be imported for creation. A required field for Drupal may be missing. <pre>%sf_data</pre>', array(
          '%sf_data' => print_r($sf_data),
        )), 'error');
      }
      salesforce_api_log(SALESFORCE_LOG_ALL, t('A user account could not be imported for creation. A required field for Drupal may be missing. <pre>%sf_data</pre>'), array(
        '%sf_data' => print_r($sf_data, TRUE),
      ), WATCHDOG_ERROR);
      return FALSE;
    }
    $create = TRUE;
  }
  $sfid = $sf_data->Id;
  if ($map->automatic & SALESFORCE_AUTO_SYNC_CREATE && $create || $map->automatic & SALESFORCE_AUTO_SYNC_UPDATE && !$create || !empty($options['extra-linked']) && $options['extra-linked'] == TRUE) {

    // Store the Salesforce ID for the node and return TRUE.
    salesforce_api_id_save('user', $account->uid, $sfid, $name, 'import');
  }
  module_invoke_all('salesforce_api_post_import', $account, $name, $sf_data, $create, $changes);
  unset($account->sf_user_skip_export);
  return $account->uid;
}

/**
 * Implements hook_default_salesforce_field_maps
 *
 */
function sf_user_default_salesforce_field_maps($drupal = NULL, $sf = NULL) {
  return array(
    'salesforce_api_default_user_contact_field_map' => (object) array(
      'disabled' => FALSE,
      'name' => 'salesforce_api_default_user_contact_field_map',
      'automatic' => SALESFORCE_AUTO_SYNC_OFF,
      'drupal' => 'user',
      'salesforce' => 'Contact',
      'fields' => array(
        'LastName' => 'name',
        'Email' => 'mail',
      ),
      'description' => 'This is a simple example fieldmap to get you started using the Salesforce API.',
    ),
  );
}

/**
 * Custom export handler for user profile date field
 *
 * @param object $user
 *   The user object.
 * @param string $fieldname
 *   The name of the field being exported.
 * @param array $drupal_field_definition
 * @param array $sf_field_definition
 * @return
 *   An Atom-formatted date for Salesforce export,
 *   or NULL if no valid date.
 */
function _sf_user_export_profile_date($user, $fieldname, $drupal_field_definition, $sf_field_definition) {
  $date = $user->{$fieldname};

  // checks to see if the date is in valid format for profile.module
  if (isset($date) && _sf_user_profile_date_valid($date)) {
    $timestamp = mktime(0, 0, 0, $date['month'], $date['day'], $date['year']);
    return gmdate(DATE_ATOM, $timestamp);
  }
  else {
    return NULL;
  }
}

/**
 * Helper function to check user profile date field validity
 *
 * @param string $date
 *   The date to be checked.
 * @return boolean
 *   Whether date is valid for use with _sf_user_export_profile_date().
 */
function _sf_user_profile_date_valid($date) {
  $is_valid = is_array($date) && (isset($date['month']) && is_numeric($date['month'])) && (isset($date['day']) && is_numeric($date['day'])) && (isset($date['year']) && is_numeric($date['year'])) ? TRUE : FALSE;
  return $is_valid;
}

/**
 * Implementation of hook_views_api().
 */
function sf_user_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'sf_user') . '/includes',
  );
}

Functions

Namesort descending Description
sf_user_default_salesforce_field_maps Implements hook_default_salesforce_field_maps
sf_user_export Exports a user to Salesforce using the specified fieldmap and stores the ID of the Salesforce object for the user.
sf_user_fieldmap_objects Implementation of hook_fieldmap_objects().
sf_user_form_alter Implementation of hook_form_alter().
sf_user_import Imports data from Salesforce into a user.
sf_user_menu Implementation of hook_menu().
sf_user_salesforce_form
sf_user_salesforce_form_access
sf_user_salesforce_form_submit
sf_user_user Implementation of hook_user().
sf_user_views_api Implementation of hook_views_api().
_sf_user_export_profile_date Custom export handler for user profile date field
_sf_user_profile_date_valid Helper function to check user profile date field validity