Only in public_html/sites/all/modules/salesforce/: .DS_Store
Only in public_html/sites/all/modules/salesforce/: ._salesforce.module
Only in public_html/sites/all/modules/salesforce/includes: ._salesforce.php
Binary files salesforce_orig/includes/._salesforce_api.inc and public_html/sites/all/modules/salesforce/includes/._salesforce_api.inc differ
diff -urp salesforce_orig/includes/salesforce_api.inc public_html/sites/all/modules/salesforce/includes/salesforce_api.inc
--- salesforce_orig/includes/salesforce_api.inc 2007-11-09 17:47:16.000000000 -0600
+++ public_html/sites/all/modules/salesforce/includes/salesforce_api.inc 2007-12-05 11:28:41.000000000 -0600
@@ -70,15 +70,20 @@ function salesforce_contact($op, $accoun
switch ($op) {
case 'insert': case 'update':
- $contact = new sObject('Contact', null,
- array(
- 'Company' => $account->company,
+
+ $fields = array(
'FirstName' => $account->first_name,
'LastName' => $account->last_name,
'Phone' => $account->phone,
'Fax' => $account->fax,
'Email' => $account->mail,
- ));
+ );
+
+ if (!variable_get('salesforce_contact_sync', 0) && !variable_get('salesforce_lead_sync', 0)) {
+ $fields['Company'] = $account->company;
+ }
+
+ $contact = new sObject('Contact', null, $fields);
// add any additional params to the contact object
foreach ($params as $param => $param_value) {
@@ -147,6 +152,36 @@ function salesforce_contact($op, $accoun
return array('error' => $error);
}
break;
+
+ case 'insert from remote':
+ // New user is being created from new contact on salesforce
+ db_query('INSERT INTO {salesforce_users} (uid,contact_id,account_id,created) VALUES (%d,"%s","%s",%d)', $account->uid, $account->contact_id, $account->account_id, time());
+ break;
+
+ case 'update from remote':
+ // Information was updated in salesforce, we need to mirror it locally, called by cron.php
+ $contact = salesforce_contact_select($account,array('FirstName','LastName','Phone','Fax','Email'));
+
+ if ($account->mail != $contact['Email'] ) {
+ user_save($account, array('mail' => $contact['Email'], 'status' => $status, 'update_from_salesforce' => TRUE));
+ }
+
+ $fields = array(
+ 'first_name' => $contact['FirstName'],
+ 'last_name' => $contact['LastName'],
+ 'phone' => $contact['Phone'],
+ 'fax' => $contact['Fax'],
+ 'update_from_salesforce' => TRUE
+ );
+
+ if (!variable_get('salesforce_contact_sync', 0) && !variable_get('salesforce_lead_sync', 0)) {
+ $fields['company'] = $account->company;
+ }
+
+ user_save($account, $fields, 'Profile Information');
+ break;
+
+
}
}
@@ -154,7 +189,7 @@ function salesforce_contact($op, $accoun
* handle leads in salesforce
*/
function salesforce_lead($op, $account, $params = array()) {
- // grab a salesforce api connection
+ // create a salesforce api client
$salesforce = salesforce();
// avoid fatal error on salesforce query with null element in query
@@ -168,15 +203,19 @@ function salesforce_lead($op, $account,
switch ($op) {
case 'insert': case 'update': default:
// create the main salesforce object
- $lead = new sObject('Lead', null,
- array(
- 'Company' => $account->company,
+ $fields = array(
'FirstName' => $account->first_name,
'LastName' => $account->last_name,
'Phone' => $account->phone,
'Fax' => $account->fax,
'Email' => $account->mail,
- ));
+ );
+
+ if (!variable_get('salesforce_contact_sync', 0) && !variable_get('salesforce_lead_sync', 0)) {
+ $fields['Company'] = $account->company;
+ }
+
+ $lead = new sObject('Lead', null, $fields);
// add any additional params to the lead object
foreach ($params as $param => $param_value) {
@@ -255,6 +294,42 @@ function salesforce_lead($op, $account,
return array('error' => $error);
}
break;
+
+ // New user is being created from new contact on salesforce
+ case 'insert from remote':
+ db_query('INSERT INTO {salesforce_users} (uid,lead_id,account_id,created) VALUES (%d,"%s","%s",%d)', $account->uid, $account->lead_id, $account->account_id, time());
+ break;
+
+ // Information was updated in salesforce, we need to mirror it locally, called by cron.php
+ case 'update from remote':
+ $lead = salesforce_lead_select($account,array('FirstName','LastName','Phone','Fax','Email','IsConverted','ConvertedAccountId','ConvertedContactId'));
+ // Otherwise we can update their profile, status, etc. as needed.
+ $status = variable_get('salesforce_lead_account_status', 0);
+ // Has this Lead been converted to a Contact?
+ if ($lead['IsConverted'] == 'true') {
+ $status = 1;
+ db_query('UPDATE {salesforce_users} SET lead_id="", contact_id="%s", account_id="%s" WHERE uid=%d', $lead['ConvertedContactId'], $lead['ConvertedAcountId'], $account->uid);
+ }
+
+ if ($account->mail != $lead['Email'] ) {
+ user_save($account, array('mail' => $lead['Email'], 'status' => $status, 'update_from_salesforce' => TRUE));
+ }
+
+ $fields = array(
+ 'first_name' => $lead['FirstName'],
+ 'last_name' => $lead['LastName'],
+ 'phone' => $lead['Phone'],
+ 'fax' => $lead['Fax'],
+ 'update_from_salesforce' => TRUE
+ );
+
+ if (!variable_get('salesforce_contact_sync', 0) && !variable_get('salesforce_lead_sync', 0)) {
+ $fields['company'] = $account->company;
+ }
+
+ user_save($account, $fields, 'Profile Information');
+ break;
+
}
}
@@ -284,7 +359,7 @@ function salesforce_event($op, $subject,
$event = new sObject('Event', NULL, array(
'WhoId' => $id,
$activityDate,
- 'Subject' => t('%subject - %date', array('%subject' => $subject, '%date' => format_date(time(), 'large'))),
+ 'Subject' => t('@subject - @date', array('@subject' => $subject, '@date' => format_date(time(), 'large'))),
'Description' => $message,
'DurationInMinutes' => 1,
));
@@ -329,27 +404,50 @@ function salesforce_event($op, $subject,
/**
* select from the salesforce contact table
*/
-function salesforce_account_select($account = NULL, $params = array(), $cache = true) {
+function salesforce_contact_select($account = NULL, $params = array(), $cache = true) {
$salesforce = salesforce();
$account = _salesforce_select_account($account);
// make sure we're dealing with a contact
if (!$account->salesforce['contact_id']) return array('error' => 'NO_CONTACT_ID');
- $defaults = array('accountId');
+ $defaults = array('Id','AccountId');
$params = array_merge($defaults, $params);
// query salesforce for the contact's account_id
- $contact = $salesforce->query("SELECT ". implode(',', $params) ." FROM contact WHERE id = '". $account->salesforce['contact_id'] ."'");
- $id = $contact['records']->values['AccountId'];
+ $contact = $salesforce->query("SELECT ". implode(',', $params) ." FROM contact WHERE Id = '". $account->salesforce['contact_id'] ."'");
+
+ $id = $contact['records']->id;
if ($id) {
if ($cache) {
- _salesforce_insert('account_id', $id, $account);
+ _salesforce_insert('account_id', $contact['records']->values['AccountId'], $account);
}
return $contact['records']->values;
}
}
/**
+ * Select from the salesforce lead table
+ */
+function salesforce_lead_select($account = NULL, $params = array(), $cache = true) {
+ $salesforce = salesforce();
+ $account = _salesforce_select_account($account);
+
+ // make sure we're dealing with a lead
+ if (!$account->salesforce['lead_id']) return array('error' => 'NO_LEAD_ID');
+
+ $defaults = array('Id');
+ $params = array_merge($defaults,$params);
+
+ $lead = $salesforce->query("SELECT ". implode(',', $params) ." FROM lead WHERE id = '". $account->salesforce['lead_id'] ."'");
+ //$lead = $salesforce->query("SELECT id, FirstName, LastName, Email, Phone, Fax, IsConverted, ConvertedAccountId, ConvertedContactId FROM lead WHERE id = '". $account->salesforce['lead_id'] ."'");
+
+ if (count($lead['records'])) {
+ return $lead['records']->values;
+ }
+}
+
+
+/**
* retreive contract information from an account
*/
function salesforce_contract_select($account = NULL, $params = array(), $defaults = true) {
@@ -359,7 +457,7 @@ function salesforce_contract_select($acc
// first we need to make sure we have an account_id to work with
if (!$account->salesforce['account_id']) {
- $result = salesforce_account_select($account);
+ $result = salesforce_contact_select($account);
$account->salesforce['account_id'] = $result['AccountId'];
if (!$account->salesforce['account_id']) return array('error' => 'NO_ACCOUNT_ID_FOUND');
}
@@ -382,3 +480,39 @@ function salesforce_contract_select($acc
return $contracts;
}
+
+/**
+ * get a list of all udpated objects of type within specified date range
+ */
+function salesforce_get_updated($type, $startDate, $endDate='') {
+ $salesforce = salesforce();
+ $endDate = ( !$endDate ) ? time() : $endDate;
+ $res = $salesforce->getUpdated($type, gmdate('c',$startDate), gmdate('c',$endDate));
+
+ $updated = array();
+ if (count($res['ids']) > 1) {
+ foreach($res['ids'] as $id) {
+ $updated[$id] = salesforce_user_load($id);
+ }
+ } else if (count($res)) {
+ $updated[$res['ids']] = salesforce_user_load($res['ids']);
+ }
+ return (count($updated)) ? $updated : false;
+}
+
+/**
+ * Load a user object if their is a user that matches salesforce lead_id, or contact_id
+ *
+ * @param $id
+ * Salesforce lead or contact id to look up.
+ * @return
+ * $user object if present, else FALSE
+ */
+function salesforce_user_load($id) {
+ $uid = db_result(db_query('SELECT uid FROM {salesforce_users} WHERE lead_id="%s" OR contact_id="%s"', $id, $id));
+ if ($uid) {
+ return user_load(array('uid' => $uid));
+ } else {
+ return FALSE;
+ }
+}
\ No newline at end of file
diff -urp salesforce_orig/salesforce.install public_html/sites/all/modules/salesforce/salesforce.install
--- salesforce_orig/salesforce.install 2007-11-03 09:07:40.000000000 -0500
+++ public_html/sites/all/modules/salesforce/salesforce.install 2007-12-04 16:36:07.000000000 -0600
@@ -44,6 +44,21 @@ function salesforce_install() {
drupal_set_message(t('salesforce.module - logs table did not install'), 'error');
}
+ db_query('CREATE TABLE IF NOT EXISTS {salesforce_sync_log} (
+ id INT NOT NULL AUTO_INCREMENT,
+ type VARCHAR(50),
+ sfid VARCHAR(50),
+ nid INT,
+ created_at INT(10),
+ PRIMARY KEY(id)
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8');
+
+ if (!db_error()) {
+ drupal_set_message(t('salesforce.module - sync_log table installed successfully'));
+ } else {
+ drupal_set_message(t('salesforce.module - sync_log table did not install'), 'error');
+ }
+
break;
}
diff -urp salesforce_orig/salesforce.module public_html/sites/all/modules/salesforce/salesforce.module
--- salesforce_orig/salesforce.module 2007-11-12 12:37:19.000000000 -0600
+++ public_html/sites/all/modules/salesforce/salesforce.module 2007-12-05 13:43:55.000000000 -0600
@@ -137,6 +137,28 @@ function salesforce_admin_settings() {
'#collapsible' => true
);
+ $form['salesforce_options']['salesforce_contact_sync'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Synchronize contacts in Salesforce'),
+ '#default_value' => variable_get('salesforce_contact_sync', 0),
+ '#description' => t('Allow Drupal to obtain information about Contacts from Salesforce and create Drupal user accounts for those Contacts. Once Drupal knows about a contact if it is updated in Salesforce it will be updated in Drupal.')
+ );
+
+ $form['salesforce_options']['salesforce_lead_sync'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Synchronize leads in Salesforce'),
+ '#default_value' => variable_get('salesforce_lead_sync', 0),
+ '#description' => t('Allow Drupal to obtain information about Leads from Salesforce and create Drupal user accounts for those Leads. Once Drupal knows about a lead if it is updated in Salesforce it will be updated in Drupal.')
+ );
+
+ $form['salesforce_options']['salesforce_lead_account_status'] = array(
+ '#type' => 'radios',
+ '#title' => t('Lead account status'),
+ '#default_value' => variable_get('salesforce_lead_account_status', 0),
+ '#options' => array(t('Blocked'),t('Active')),
+ '#description' => t('when creating a new user account from a Salesforce lead the account will be given this status.')
+ );
+
$form['salesforce_options']['salesforce_leads_create_forms'] = array(
'#type' => 'textarea',
'#title' => t('Create Leads on form processes'),
@@ -160,12 +182,113 @@ function salesforce_admin_settings() {
* Implementation of hook_cron().
*/
function salesforce_cron() {
+
$result = db_query("SELECT sid, type, type_id, message, timestamp, status FROM {salesforce_log} WHERE status = 1 ORDER BY timestamp DESC");
if (db_num_rows($result) > 0) {
while ($row = db_fetch_object($result)) {
_salesforce_cron_run($row);
}
}
+
+ /**
+ * TODO:
+ * All of this should be put into the salesforce_sync_api.inc file once that becomes part of
+ * the core module
+ */
+
+ $time = time();
+ $salesforce = salesforce();
+
+ // Check for updated or deleteds leads and log them in the sync_log for later processing
+ if (variable_get('salesforce_lead_sync', 0)) {
+ // updated
+ $res = $salesforce->getUpdated('Lead', gmdate('c', variable_get('salesforce_last', time())-600), gmdate('c', time()));
+ if ($res) {
+ foreach((array)$res['ids'] as $id) {
+ db_query('INSERT INTO {salesforce_sync_log} (type,sfid,created_at) VALUES ("%s","%s",%d)',
+ 'lead_update', $id, time()
+ );
+ }
+ }
+ unset($res);
+
+ // deleted
+ $res = $salesforce->getDeleted('Lead', gmdate('c', variable_get('salesforce_last', time())-600), gmdate('c', time()));
+ if ($res) {
+ // returns are in a different format if there is just one
+ if (count($res) == 1) {
+ $tmp = $res['deletedRecords'];
+ $res = array('deletedRecords' => array($tmp));
+ }
+ foreach((array)$res['deletedRecords'] as $record) {
+ echo 'adding delete log - ';
+ db_query('INSERT INTO {salesforce_sync_log} (type,sfid,created_at) VALUES ("%s","%s",%d)',
+ 'lead_delete', $record['id'], time()
+ );
+ }
+ }
+ unset($res);
+ }
+
+ // Check for updated or deleted contacts and log them in the sync_log for later processing
+ if (variable_get('salesforce_contact_sync', 0)) {
+ // updated
+ $res = $salesforce->getUpdated('Contact', gmdate('c', variable_get('salesforce_last', time())-600), gmdate('c', time()));
+ if ($res) {
+ foreach((array)$res['ids'] as $id) {
+ db_query('INSERT INTO {salesforce_sync_log} (type,sfid,created_at) VALUES ("%s","%s",%d)',
+ 'contact_update', $id, time()
+ );
+ }
+ }
+ unset($res);
+
+ // deleted
+ $res = $salesforce->getDeleted('Contact', gmdate('c', variable_get('salesforce_last', time())-600), gmdate('c', time()));
+ if ($res) {
+ // returns are in a different format if there is just one
+ if (count($res) == 1) {
+ $tmp = $res['deletedRecords'];
+ $res = array('deletedRecords' => array($tmp));
+ }
+ foreach((array)$res['deletedRecords'] as $record) {
+ db_query('INSERT INTO {salesforce_sync_log} (type,sfid,created_at) VALUES ("%s","%s",%d)',
+ 'contact_delete', $record['id'], time()
+ );
+ }
+ }
+ unset($res);
+ }
+
+ // Then get 10 records form the log, and processes them during this cron run. This is to prevent timing out.
+ $res = db_query('SELECT * FROM {salesforce_sync_log} WHERE type="lead_update" OR type="lead_delete" OR type="contact_update" OR type="contact_delete" LIMIT 10');
+ while ($row = db_fetch_object($res)) {
+ switch($row->type) {
+ case 'lead_update':
+ _salesforce_cron_user_update(array($row->sfid => salesforce_user_load($row->sfid)), 'lead_id');
+ break;
+
+ case 'lead_delete':
+ $user = salesforce_user_load($row->sfid);
+ user_delete(array(),$user->uid);
+ watchdog('salesforce', t('Deleted user %user because Lead was deleted in Salesforce', $user->name), WATCHDOG_NOTICE);
+ break;
+
+ case 'contact_update':
+ _salesforce_cron_user_update(array($row->sfid => salesforce_user_load($row->sfid)), 'contact_id');
+ break;
+
+ case 'contact_delete':
+ $user = salesforce_user_load($row->sfid);
+ db_query('UPDATE {users} SET status=0 WHERE uid=%d', $user->uid);
+ watchdog('salesforce', t('Blocked user because Contact was deleted in Salesforce'), WATCHDOG_NOTICE, url('user/'. $user->uid));
+ break;
+ }
+ db_query('DELETE FROM {salesforce_sync_log} WHERE type="%s" AND sfid="%s"', $row->type, $row->sfid);
+ }
+
+ // Log current time for next run
+ variable_set('salesforce_last', $time);
}
/**
@@ -188,11 +311,23 @@ function salesforce_user($op, &$edit, &$
if ($edit['create_lead']) {
// must reload the object with user_load() to grab the updated profile fields
salesforce_lead('insert', user_load(array('uid' => $account->uid)), array('Description' => t('new site user: @date', array('@date' => format_date(time(), 'large')))));
+
+ } else if ($edit['contact_id'] || $edit['lead_id']) {
+ // user is being created form salesforce contact/lead
+ $account->contact_id = $edit['contact_id'];
+ $account->lead_id = $edit['lead_id'];
+ $account->account_id = $edit['account_id'];
+
+ if ($account->contact_id) {
+ salesforce_contact('insert from remote', $account);
+ } else if ($account->lead_id) {
+ salesforce_lead('insert from remote', $account);
+ }
}
break;
case 'update':
- if (_salesforce_is_form('leads', 'user_edit')) {
+ if (_salesforce_is_form('leads', 'user_edit') && !$edit['update_from_salesforce']) {
// must reload the object with user_load() to grab the updated profile fields
$updated_account = user_load(array('uid' => $account->uid));
if ($account->salesforce['contact_id']) {
@@ -208,6 +343,21 @@ function salesforce_user($op, &$edit, &$
}
}
break;
+
+ case 'delete':
+ // Remove their information from salesforce_users table
+ db_query('DELETE FROM {salesforce_users} WHERE uid=%d', $account->uid);
+ break;
+
+ case 'register':
+ // Add these fields to the registration form so we can make use of them later.
+ $form = array();
+ $form['account_id'] = array('#type' => 'hidden', '#value' => '');
+ $form['lead_id'] = array('#type' => 'hidden', '#value' => '');
+ $form['contact_id'] = array('#type' => 'hidden', '#value' => '');
+ return $form;
+ break;
+
case 'view':
break;
}
@@ -293,20 +443,21 @@ function salesforce_contact_form($form_i
* all forms set to use lead / event actions receive these submit functions
* separated right now just because.. TODO: should probably be reduced 1 one function but we're waiting..
*/
-function salesforce_form_lead_submit() {
- $message =_salesforce_is_form('leads', $_POST['edit']['form_id'], true);
+function salesforce_form_lead_submit($form_id, $form_values) {
+ $message =_salesforce_is_form('leads', $form_id, true);
// TODO: ? (currently not needed but.. hmm...)
}
-function salesforce_form_event_submit() {
+function salesforce_form_event_submit($form_id, $form_values) {
global $user;
// only track logged in users since we need an account to associated them with
if ($user->uid == 0) return;
// grab our message to display as the description of this event in salesforce
- $message =_salesforce_is_form('events', $_POST['edit']['form_id'], true);
+ $message =_salesforce_is_form('events', $form_id, true);
+
// insert our event and yet again i find myself having to reload the user object to get my stuff? wtf?
- $result = salesforce_event('insert', $_POST['edit']['form_id'], $message, user_load(array('mail' => $_POST['edit']['mail'])));
+ $result = salesforce_event('insert', $form_id, $message, user_load(array('mail' => $form_values['mail'])));
}
/**
@@ -438,7 +589,7 @@ function _salesforce_admin_list($op) {
$sf = 'https://na1.salesforce.com/';
if ($op == 'lead' || $op == 'contact') {
- $result = db_query("SELECT s.uid FROM {salesforce_users} s WHERE %s != ''", 's.'. $op .'_id');
+ $result = db_query("SELECT * FROM {salesforce_users} s WHERE %s != ''", 's.'. $op .'_id');
if (db_num_rows($result) > 0) {
$cols = array(array('data' => t('User'), 'class' => 'user'), array('data' => t('Name')), array('data' => t('%i', array('%i' => ucfirst($op) .' ID')), 'class' => 'id'));
if ($op == 'contact') {
@@ -446,9 +597,9 @@ function _salesforce_admin_list($op) {
}
while ($row = db_fetch_object($result)) {
- if ($op == 'contact') {
+ if ($op == 'contact' && !$row->account_id) {
// we do this incase we don't have a cached account id
- salesforce_account_select(user_load(array('uid' => $row->uid)));
+ salesforce_contact_select(user_load(array('uid' => $row->uid)));
}
$account = user_load(array('uid' => $row->uid));
// remove the extra 3 chars that are not used in this case
@@ -522,6 +673,62 @@ function _salesforce_cron_run($row) {
}
/**
+ * Apply updated salesforce information to a local user account
+ */
+function _salesforce_cron_user_update($updated, $type='contact_id') {
+ foreach($updated as $id => $user) {
+ // if they already have an account locally we just update it.
+ if ($user && $id) {
+ if ($type == 'contact_id') {
+ salesforce_contact('update from remote', $user);
+ } else if ($type == 'lead_id') {
+ salesforce_lead('update from remote', $user);
+ }
+ watchdog('salesforce', t('Updated @user from Salesforce', array('@user' => $user->name)));
+
+ } else if ($id) {
+ // This is a record that exists on salesforce but not locally so we need to create one.
+ $account->salesforce[$type] = $id;
+
+ // TODO: Rather than select each one individually can we select all of them at once? This would be faster
+ // and require less calls to salesforce
+ $fields = array('FirstName', 'LastName', 'Phone', 'Fax', 'Email');
+ if ($type == 'contact_id') {
+ $contact = salesforce_contact_select($account, $fields);
+ } else if ($type == 'lead_id') {
+ $contact = salesforce_lead_select($account, $fields);
+ }
+
+ $values = array();
+ $values['name'] = $contact['FirstName'] . $contact['LastName'];
+ $values['mail'] = $contact['Email'];
+ $values['pass'] = user_password();
+ $values['notify'] = 1;
+ $values['create_lead'] = 0;
+ $values['first_name'] = $contact['FirstName'];
+ $values['last_name'] = $contact['LastName'];
+ $values['phone'] = $contact['Phone'];
+ $values['fax'] = $contact['Fax'];
+ $values[$type] = $id;
+ $values['account_id'] = $contact['AccountId'];
+
+ // Make sure this is a unique username
+ $i = 1;
+ $name = $values['name'];
+ while (db_num_rows(db_query('SELECT uid FROM {users} WHERE name="%s"', $values['name'])) > 0) {
+ $values['name'] = $name .'_'. $i;
+ $i++;
+ }
+
+ // Register the user account. Doing it this way allows Drupal to call all the necessary hooks
+ user_register_submit('user_register', $values);
+ watchdog('salesforce', t('Inserted user @user from Salesforce', array('@user' => $contact['FirstName'].$contact['LastName'])));
+ }
+ }
+ return true;
+}
+
+/**
* used for inserting a single column into the salesforce_users table
*/
function _salesforce_insert($col, $value, $account = NULL) {