You are here

function sf_entity_import in Salesforce Suite 7.2

Same name and namespace in other branches
  1. 7 sf_entity/sf_entity.module \sf_entity_import()

Imports data from Salesforce into a Drupal entity

Parameters

$sf_data: The Salesforce object OR The Salesforce ID of the object to be imported.

string $name: The name of the fieldmap to use to create the import object.

int $id: The id of the entity to update. If left NULL, a new entity will be created.

array $options: Additional options to control how the import should be done.

Return value

The id of the imported entity or FALSE on failure.

1 call to sf_entity_import()
sf_entity_salesforce_form_submit in sf_entity/sf_entity.module
Form submit handler for the [entity-name]/%/salesforce form.
1 string reference to 'sf_entity_import'
sf_notifications_update_record in sf_notifications/sf_notifications.module
Helper function for _sf_notifications_handle_message() - attempt to update (or insert if $object_record['oid'] is empty) the local object data, given the salesforce object_record.

File

sf_entity/sf_entity.module, line 928
Integrates fieldable entities with the Salesforce API.

Code

function sf_entity_import($sf_data, $name, $id = NULL, $options = array()) {

  // Connect to Salesforce and retrieve the object.
  $sf = salesforce_api_connect();
  if (!isset($sf) || !is_object($sf)) {
    if (isset($id)) {

      // Let modules react to a failure to update this entity.
      module_invoke_all('salesforce_api_import_connect_fail', $name, $id);
    }
    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_salesforce_fieldmap_load($name);

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

  // Load the entity to update, if there is one.
  if (!empty($id)) {
    $entities = entity_load($map->drupal_entity, array(
      $id,
    ));
  }
  else {
    $entity = $entities = NULL;
  }
  if (is_array($entities)) {
    $entity = current($entities);
  }
  else {
    $entity = $entities;
  }
  $create = FALSE;
  if (empty($id) || empty($entity)) {

    // Look for any matching records which we might want to update instead of creating duplicates.
    $matches = salesforce_api_search_for_duplicates('import', $map->drupal_entity, $map->drupal_bundle, $sf_data, $name);
    if (!empty($matches)) {
      $id = reset($matches);
      if (!empty($id)) {
        $entities = entity_load($map->drupal_entity, array(
          $id,
        ));
        if (is_array($entities)) {
          $entity = current($entities);
        }
        else {
          $entity = $entities;
        }
      }
    }
    if (empty($entity)) {
      $create = TRUE;
      $ids = array(
        NULL,
        NULL,
        $map->drupal_bundle,
      );
      $entity = entity_create_stub_entity($map->drupal_entity, $ids);
      $entity->is_new = TRUE;
    }
  }
  list($id, $vid, $bundle) = entity_extract_ids($map->drupal_entity, $entity);
  $core_types = array(
    'node',
    'user',
    'taxonomy_term',
  );
  if (isset($entity->is_new) && $entity->is_new == TRUE && in_array($map->drupal_entity, $core_types)) {
    _sf_entity_import_preprocess_entity($entity, $map->drupal_entity, $map->drupal_bundle);
  }
  $changed_fields = 0;

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

    // Don't check for fixed or PHP values.
    if (!is_array($drupal_fieldname) && isset($entity->{$drupal_fieldname})) {
      $previous_value = $entity->{$drupal_fieldname};
    }

    // If a handler is specified for importing a value from Salesforce....
    if (is_array($drupal_fieldname)) {

      // There is no logical way to import Salesforce values into Drupal fixed
      // or PHP values.
      continue;
    }
    elseif (isset($drupal_object_definition['fields'][$drupal_fieldname]['import'])) {
      $drupal_field_import_handler = $drupal_object_definition['fields'][$drupal_fieldname]['import'];

      // Previous values for FieldAPI fields are a special case. Handle here for now.
      // @todo: Come up with a more elegant solution.
      if ($drupal_field_import_handler == 'sf_entity_import_field_default') {
        list($fieldapi_fieldname, $column) = explode(':', $drupal_fieldname, 2);
        $previous_value = $entity->{$fieldapi_fieldname};
      }
      $drupal_field_definition = $drupal_object_definition['fields'][$drupal_fieldname];
      $sf_field_definition = $salesforce_object_definition['fields'][$sf_fieldname];

      // Let the handler function set the value for the field on the node.
      $drupal_field_import_handler($entity, $drupal_fieldname, $drupal_field_definition, $sf_data, $sf_fieldname, $sf_field_definition);
    }
    elseif (isset($sf_data->{$sf_fieldname})) {

      // Otherwise set the value of the mapped field in Drupal to the value of the field in Salesforce,
      // if the field exists on the Drupal entity.
      if (isset($entity->{$drupal_fieldname})) {
        $entity->{$drupal_fieldname} = $sf_data->{$sf_fieldname};
      }
    }

    // Compare the new values to the previous values.
    if (isset($previous_value)) {
      if (isset($entity->{$drupal_fieldname}) && $entity->{$drupal_fieldname} != $previous_value) {
        $changed_fields++;
      }
      elseif (isset($fieldapi_fieldname) && isset($entity->{$fieldapi_fieldname}) && $entity->{$fieldapi_fieldname} != $previous_value) {
        $changed_fields++;
      }
    }
  }

  // Clone the entity in order to do comparison, to ensure that it is not getting altered by the pre-import hook.
  $comparison_entity = clone $entity;

  // Allow modules to alter the data and fieldmap prior to import.
  foreach (module_implements('salesforce_api_pre_import') as $module) {
    $function = $module . '_salesforce_api_pre_import';
    $continue = $function($entity, $name, $sf_data);
    if ($continue === FALSE) {
      return;
    }
  }
  if ($changed_fields == 0 && $comparison_entity == $entity) {

    // No fields changed, so don't save anything.
    // Return the entity ID to signal success.
    // @todo: Add logging (at the lowest level)?
    return $id;
  }
  _sf_entity_import_process_entity($entity, $map->drupal_entity, $map->drupal_bundle);
  $entity->sf_entity_skip_export = TRUE;

  // It would be nice if we could just call entity_save($entity), but there is
  // no entity_save. Fortunately core modules all implement their save
  // functions in almost the exact same way, and they all call entity_invoke()
  // so that our hook_entity_update and hook_entity_insert will fire properly.
  $function = $map->drupal_entity . '_save';
  if (function_exists($function)) {
    $function($entity);
  }
  else {
    if (isset($entity->is_new) || empty($id)) {
      module_invoke_all('entity_insert', $entity, $map->drupal_entity);
    }
    else {
      module_invoke_all('entity_update', $entity, $map->drupal_entity);
    }
  }
  list($id, $vid, $bundle) = entity_extract_ids($map->drupal_entity, $entity);

  // If the entity id has been set...
  if (!empty($id)) {

    // Then check whether the mapping is configured to auto-sync on create or update, or the option for linkage is set.
    if ($map->automatic & SALESFORCE_AUTO_SYNC_CREATE && $create || $map->automatic & SALESFORCE_AUTO_SYNC_UPDATE && !$create || !empty($options['extra-linked']) && $options['extra-linked'] == TRUE) {

      // If so, then store the Salesforce ID for the entity if it is available.
      // The SFID in the entity object itself takes precedence over the one that comes from Salesforce.
      $sfid = '';
      if (isset($entity->salesforce) && !empty($entity->salesforce->sfid) && is_sfid($entity->salesforce->sfid)) {
        $sfid = $entity->salesforce->sfid;
      }
      elseif (isset($sf_data->Id) && is_sfid($sf_data->Id)) {
        $sfid = $sf_data->Id;
      }
      if (!empty($sfid)) {
        salesforce_api_id_save($id, $sfid, $name, $map->drupal_entity, $map->drupal_bundle, 'import');
      }
    }
  }

  // Allow modules to respond after an import.
  module_invoke_all('salesforce_api_post_import', $entity, $name, $sf_data, $create);
  unset($entity->sf_entity_skip_export);

  // Return the Drupal ID of the imported entity.
  return $id;
}