You are here

salesforce_api.install in Salesforce Suite 6.2

Installs any global tables needed for Salesforce integration.

File

salesforce_api/salesforce_api.install
View source
<?php

/**
 * @file
 * Installs any global tables needed for Salesforce integration.
 */

/**
 * Implementation of hook_install().
 */
function salesforce_api_install() {
  drupal_install_schema('salesforce_api');
  variable_set('salesforce_api_enabled_objects', array(
    'Campaign',
    'Contact',
    'Lead',
  ));
}

/**
 * Implementation of hook_uninstall().
 */
function salesforce_api_uninstall() {
  drupal_uninstall_schema('salesforce_api');
  db_query("DELETE FROM {variable} WHERE name LIKE 'salesforce%%'");
  db_query("DELETE FROM {cache} WHERE cid = 'salesforce_api_sf_objects'");
}

/**
 * Implementation of hook_enable().
 */
function salesforce_api_enable() {
  drupal_set_message(t('Salesforce API: Before making any Salesforce connections, please <a href="!url">enter your Salesforce API credentials</a>', array(
    '!url' => url(SALESFORCE_PATH_ADMIN),
  )), 'warning');
  drupal_set_message(t('Salesforce API: The default Salesforce objects have been enabled, to export/import any other objects see the <a href="!url">Object setup</a> page.', array(
    '!url' => url(SALESFORCE_PATH_OBJECT),
  )), 'warning');
}

/**
 * Implementation of hook_schema().
 */
function salesforce_api_schema() {
  require_once drupal_get_path('module', 'salesforce_api') . '/salesforce_api.module';
  $schema['salesforce_object_map'] = array(
    'description' => t('Drupal to Salesforce object mapping table'),
    'fields' => array(
      'name' => array(
        'description' => 'Foreign key for salesforce_field_map - the fieldmap that corresponds to this record.',
        'type' => 'varchar',
        'length' => 64,
      ),
      'oid' => array(
        'description' => 'Specific Drupal object identifier (e.g. node id or comment id)',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'sfid' => array(
        'description' => 'Salesforce object identifier (e.g. 000000000000000000)',
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '',
      ),
      'drupal_type' => array(
        'description' => 'Drupal object type (e.g. "node", "comment")',
        'type' => 'varchar',
        'length' => 128,
        'not null' => TRUE,
        'default' => '',
      ),
      'created' => array(
        'description' => 'The UNIX timestamp when the mapping was created.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'last_import' => array(
        'description' => 'The Unix timestamp when the record was last imported from Salesforce to Drupal.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'last_export' => array(
        'description' => 'The Unix timestamp when the record was last exported from Drupal to Salesforce.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'indexes' => array(
      'sfid' => array(
        'sfid',
      ),
      'name' => array(
        'name',
      ),
    ),
    'primary key' => array(
      'drupal_type',
      'oid',
    ),
  );

  // Salesforce Field Map schema
  $schema['salesforce_field_map'] = array(
    'description' => t('Drupal to Salesforce field mappings'),
    'export' => array(
      'key' => 'name',
      'identifier' => 'salesforce_field_map',
      'default hook' => 'default_salesforce_field_maps',
      'export callback' => 'salesforce_api_salesforce_field_map_export',
      'api' => array(
        'owner' => 'salesforce_api',
        'api' => 'salesforce_api',
        'minimum_version' => 1,
        'current_version' => 1,
      ),
    ),
    'fields' => array(
      // "name" field is only in schema for ctools exportable support and not in
      // use via any UI at the moment. Implementing modules can assign
      // meaningful names if they wish to do so, but it is not required for our
      // purposes.
      'fieldmap' => array(
        'description' => 'The primary identifier for a fieldmap.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'no export' => TRUE,
      ),
      'name' => array(
        'description' => 'Unique ID for this object. Used to identify it programatically (initially implemented for ctools support only).',
        'type' => 'varchar',
        'length' => 64,
      ),
      'automatic' => array(
        'description' => 'Indicates whether this action/map is automatic or triggered.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => SALESFORCE_AUTO_SYNC_OFF,
        'size' => 'small',
      ),
      'drupal' => array(
        'description' => 'The kind of Drupal object this map is for.',
        'type' => 'varchar',
        'length' => 40,
        'not null' => TRUE,
        'default' => '',
      ),
      'salesforce' => array(
        'description' => 'The kind of Salesforce object this map is for.',
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '',
      ),
      'description' => array(
        'description' => 'Name or brief description of this fieldmap',
        'type' => 'varchar',
        'length' => 255,
        'not null' => FALSE,
        'default' => '',
      ),
      'fields' => array(
        'description' => 'Serialized fieldmap',
        'type' => 'text',
        'not null' => TRUE,
        'serialize' => TRUE,
      ),
    ),
    'primary key' => array(
      'fieldmap',
    ),
    'unique keys' => array(
      'name' => array(
        'name',
      ),
    ),
  );
  return $schema;
}

/**
 * Implementation of hook_requirements().
 *
 * Check the Salesforce API configuration to see if we have valid credentials.
 */
function salesforce_api_requirements($phase) {
  $req = array();
  if ($phase == 'runtime') {
    require_once drupal_get_path('module', 'salesforce_api') . '/salesforce_api.module';
    $username = variable_get('salesforce_api_username', FALSE);
    if (!salesforce_api_toolkit_installed()) {
      $description = t('Salesforce module installed, but missing Salesforce PHP Toolkit. Please make sure Salesforce PHP Toolkit is available at ' . SALESFORCE_DIR_SOAPCLIENT . '/SforceEnterpriseClient.php');
      $severity = REQUIREMENT_WARNING;
    }
    elseif (!$username) {
      $description = l(t('Salesforce module installed but not configured. Please enter your credentials.'), SALESFORCE_PATH_ADMIN);
      $severity = REQUIREMENT_WARNING;
    }
    elseif (!salesforce_api_connect()) {
      $description = t('Unable to connect to Salesforce using <a href="!url">current credentials</a>.', array(
        '!url' => url(SALESFORCE_PATH_ADMIN),
      ));
      $severity = REQUIREMENT_WARNING;
    }
    elseif (!salesforce_api_encryption_available(array(
      'check_config' => FALSE,
    ))) {
      $description = t('Encryption is unavailable. Using encryption is <strong>highly recommended</strong> in order to better secure your data.');
      $severity = REQUIREMENT_WARNING;
    }
    elseif (!salesforce_api_encryption_available(array(
      'check_config' => TRUE,
    ))) {
      $description = t('SalesForce encryption is enabled but not configured securely.');
      $severity = REQUIREMENT_WARNING;
    }
    else {
      $description = t('Salesforce libraries and credentials OK.');
      $severity = REQUIREMENT_OK;
    }
    if (!empty($description)) {
      $req[] = array(
        'title' => t('Salesforce Configuration'),
        'value' => l('Salesforce Admin', SALESFORCE_PATH_ADMIN),
        'description' => $description,
        'severity' => $severity,
      );
      return $req;
    }
  }
}

/**
 * We have fundamentally changed the schema of SF module. Primary identifier is
 * now "name". Although the value of name is not particularly important, it must
 * be set and it must be unique. In this update function, we are doing a few
 * things:
 * 1) Add "name" columns to salesforce_field_map and salesforce_object_map
 * 2) Assign unique values to "name" column in salesforce_field_map
 * 3) Assign "name" values to columns in salesforce_object_map
 * 4) Drop "fieldmap" column from salesforce_object_map
 *
 */
function salesforce_api_update_6201() {
  module_enable(array(
    'ctools',
  ));
  if (!module_exists('ctools')) {
    drupal_set_message(t('This version of SalesForce module depends on <a href="@ctools">Chaos Tool Suite</a>, which is not available. Please install Chaos Tool Suite, then run update again.', array(
      '@ctools' => url('http://drupal.org/project/ctools'),
    )), 'error');
    return array(
      array(
        'success' => FALSE,
        'query' => 'Chaos Tool Suite not found.',
      ),
    );
  }
  $ret[] = array(
    'success' => TRUE,
    'query' => 'Chaos Tool Suite enabled.',
  );
  db_add_column($ret, 'salesforce_field_map', 'description', 'varchar(255)');
  db_add_column($ret, 'salesforce_field_map', 'name', 'varchar(255)');
  db_add_column($ret, 'salesforce_object_map', 'name', 'varchar(255)');
  $result = db_query('SELECT fieldmap FROM {salesforce_field_map}');
  while ($fieldmap = db_result($result)) {
    $name = md5($fieldmap);
    $sql = 'UPDATE {salesforce_object_map} SET name = "%s" WHERE fieldmap = %d';
    $update_result = db_query($sql, $name, $fieldmap);
    $ret[] = array(
      'success' => $update_result !== FALSE,
      'query' => check_plain($sql),
    );
    $sql = 'UPDATE {salesforce_field_map} SET name = "%s" WHERE fieldmap = %d';
    $update_result = db_query($sql, $name, $fieldmap);
    $ret[] = array(
      'success' => $update_result !== FALSE,
      'query' => check_plain($sql),
    );
  }
  db_add_index($ret, 'salesforce_object_map', 'name', array(
    'name',
  ));
  db_add_unique_key($ret, 'salesforce_field_map', 'name', array(
    'name',
  ));
  $ret[] = update_sql('ALTER TABLE {salesforce_object_map} DROP COLUMN fieldmap');

  // Set the WSDL directory
  if (!($dir = variable_get('salesforce_api_dir_wsdl', FALSE))) {
    $dir = SALESFORCE_DIR_WSDL;
    $wsdl = $dir . '/enterprise.wsdl';
    if (file_exists($wsdl)) {
      variable_set('salesforce_api_dir_wsdl', $dir);
    }
    else {
      variable_set('salesforce_api_dir_wsdl', SALESFORCE_DIR_SOAPCLIENT);
    }
  }
  return $ret;
}

/**
 * Try to fix existing maps based on the new cck support
 */
function salesforce_api_update_6202() {
  $fieldmaps = salesforce_api_salesforce_field_map_load_all();
  $ret = array();
  $changes = array();
  module_enable(array(
    'sf_contrib',
  ));
  $ret[] = array(
    'success' => TRUE,
    'query' => t('Enabled SF Contrib module', array(
      '@map' => $new_map->name,
    )),
  );
  foreach (content_types() as $type) {

    // Add each of the fields to the node object definition.
    foreach ((array) $type['fields'] as $field) {
      if (empty($field['columns']['value'])) {
        $changes[$field['field_name']] = array(
          'old' => $field['field_name'],
          'new' => $field['field_name'] . ':' . key($field['columns']),
        );
      }
      if ($field['type'] == 'date' && !empty($field['todate'])) {
        $changes[$field['field_name'] . '_todate'] = array(
          'old' => $field['field_name'] . '_todate',
          'new' => $field['field_name'] . ':value2',
        );
      }
    }
  }
  foreach ($fieldmaps as $map) {
    $new_map = $map;
    $updates = FALSE;
    foreach ($map->fields as $i => $field) {
      if (!empty($changes[$field])) {
        $new_map->fields[$i] = $changes[$field]['new'];
        $updates = TRUE;
      }
    }
    if ($updates) {
      salesforce_api_fieldmap_save($new_map);
      $ret[] = array(
        'success' => TRUE,
        'query' => t('Updated fieldmap @map', array(
          '@map' => $new_map->name,
        )),
      );
    }
  }
  return $ret;
}
function salesforce_api_update_6203() {
  $ret = array();
  db_change_field($ret, 'salesforce_field_map', 'automatic', 'automatic', array(
    'type' => 'int',
    'size' => 'small',
    'not null' => TRUE,
    'default' => SALESFORCE_AUTO_SYNC_OFF,
  ));
  update_sql(sprintf('UPDATE {salesforce_field_map} SET automatic = %d', SALESFORCE_AUTO_SYNC_CREATE | SALESFORCE_AUTO_SYNC_UPDATE));
  return $ret;
}

/**
 * Remove erroneous sf_user_skip_export elements from database.
 */
function salesforce_api_update_6204(&$sandbox) {
  $ret = array();
  if (empty($sandbox['uids'])) {
    $where = " data like '%%sf_user_skip_export%%'";
    $sandbox['n_users'] = 0;
    $sandbox['uids'] = array();
    $result = db_query('SELECT uid FROM {users} WHERE ' . $where);
    while ($uid = db_result($result)) {
      $sandbox['uids'][] = $uid;
      $sandbox['n_users']++;
    }
    if (empty($sandbox['n_users'])) {
      return array(
        array(
          'success' => TRUE,
          'query' => t('No updates to process.'),
        ),
      );
    }
    $sandbox['position'] = 0;
  }
  $uid = $sandbox['uids'][$sandbox['position']];
  $account = user_load($uid);
  $account->sf_user_skip_export = TRUE;
  user_save($account, array(
    'sf_user_skip_export' => NULL,
  ));
  $sandbox['position']++;
  $finished = $sandbox['position'] / $sandbox['n_users'];
  if ($finished >= 1) {
    return array(
      array(
        'success' => TRUE,
        'query' => t('Fixed !n user accounts.', array(
          '!n' => $sandbox['n_users'],
        )),
      ),
    );
  }
  else {
    return array(
      '#finished' => $finished,
    );
  }
}

/**
 * Alter {salesforce_object_map} to add last_import and last_export fields.
 * @TODO: Update existing items in {salesforce_object_map} with best guesses of
 * last import/export times.
 */
function salesforce_api_update_6205(&$sandbox) {
  $ret = array();
  db_add_field($ret, 'salesforce_object_map', 'created', array(
    'type' => 'int',
    'not null' => TRUE,
    'description' => 'The UNIX timestamp when the mapping was created.',
  ));
  db_add_field($ret, 'salesforce_object_map', 'last_import', array(
    'type' => 'int',
    'not null' => TRUE,
    'description' => 'The UNIX timestamp when the last import occurred for this item.',
  ));
  db_add_field($ret, 'salesforce_object_map', 'last_export', array(
    'type' => 'int',
    'not null' => TRUE,
    'description' => 'The UNIX timestamp when the last export occurred for this item.',
  ));
  return $ret;
}

Functions

Namesort descending Description
salesforce_api_enable Implementation of hook_enable().
salesforce_api_install Implementation of hook_install().
salesforce_api_requirements Implementation of hook_requirements().
salesforce_api_schema Implementation of hook_schema().
salesforce_api_uninstall Implementation of hook_uninstall().
salesforce_api_update_6201 We have fundamentally changed the schema of SF module. Primary identifier is now "name". Although the value of name is not particularly important, it must be set and it must be unique. In this update function, we are doing a few things: 1)…
salesforce_api_update_6202 Try to fix existing maps based on the new cck support
salesforce_api_update_6203
salesforce_api_update_6204 Remove erroneous sf_user_skip_export elements from database.
salesforce_api_update_6205 Alter {salesforce_object_map} to add last_import and last_export fields. @TODO: Update existing items in {salesforce_object_map} with best guesses of last import/export times.