Index: send.inc =================================================================== --- send.inc (revision 19626) +++ send.inc (revision 19627) @@ -238,7 +238,6 @@ global $user; $sender = array('first_name' => '', 'last_name'=> ''); - _send_crm_contact($user->mail, $sender); $mode = 'teaser'; $node = count($nids) ? node_load($nids[0]) : null; @@ -415,26 +414,16 @@ if (!$values['sid']) { $values['sid'] = db_next_id("{send}_sid"); } + + // ensure that a contact exists + $contact_id = _send_crm_contact($values['sender_mail'], $values, $user, 'sender'); // log send action db_query("INSERT INTO {send} - ( sid ,module ,uid ,mail ,timestamp ,message, subject, name ) - VALUES ( %d ,'%s' ,%d ,'%s' ,%d ,'%s', '%s', '%s')" - , $values['sid'], $module, $uid, $sender['mail'], time(), $message, $subject, $sender['name']); - - // log a CRM activity - if ($contact = _send_crm_contact($mail, $values, $user, 'sender')) { - $activity = array( - 'entity_table' => 'civicrm_contact', - 'entity_id' => $contact->id, - 'module' => 'send', - 'activity_type' => t('Sent %subject',array('%subject' => $subject)), - 'activity_date' => date('YmdHis',time()), - 'activity_id' => $values['sid'], - ); - crm_create_activity_history($activity); - } - + ( sid ,module ,uid ,mail ,timestamp ,message, subject, name, contact_id ) + VALUES ( %d ,'%s' ,%d ,'%s' ,%d ,'%s', '%s', '%s', %d)" + , $values['sid'], $module, $uid, $sender['mail'], time(), $message, $subject, $sender['name'], $contact_id); + // get delivery callback if(!$deliver = module_invoke($module, 'send', 'deliver', $module)) { $deliver = module_invoke('send', 'send', 'deliver','send'); @@ -480,15 +469,10 @@ switch ($rtype) { case 'user': - // try to log message as a crm activity for recipient + // ensure that contact exists if (is_array($r) && isset($r['mail'])) { $recipient_user = user_load(array('mail'=>$r['mail'])); - if ($contact = _send_crm_contact($r['mail'], $r, $recipient_user)) { - crm_create_activity_history($arr = array_merge($activity, array( - 'entity_id' => $contact->id, - 'activity_type' => t('Received %subject', array('%subject' => $subject)), - ))); - } + $recipient_contact_id = _send_crm_contact($r['mail'], $r, $recipient_user); $rid = $recipient_user->uid; if (!$r['name']) { @@ -529,16 +513,16 @@ // log the recipient if there are no nodes in the message if (!count($values['nids'])) { db_query("INSERT INTO {send_recipient} - ( sid ,nid ,rid ,rtype ,mail, name, rcount ) - VALUES ( %d ,%d ,%d ,'%s', '%s', '%s', %d )", - $values['sid'], 0, $rid, $rtype, $r_mail, $r_name, $count ); + (sid ,nid ,rid ,rtype ,mail, name, rcount, contact_id) + VALUES (%d ,%d ,%d ,'%s', '%s', '%s', %d, %d)", + $values['sid'], 0, $rid, $rtype, $r_mail, $r_name, $count, $recipient_contact_id); } // log each node/user combination foreach ($values['nids'] as $nid) { db_query("INSERT INTO {send_recipient} - ( sid ,nid ,rid ,rtype ,mail, name, rcount ) - VALUES ( %d ,%d ,%d ,'%s', '%s', '%s', %d )", - $values['sid'], $nid, $rid, $rtype, $r_mail, $r_name, $count ); + (sid ,nid ,rid ,rtype ,mail, name, rcount, contact_id) + VALUES (%d ,%d ,%d ,'%s', '%s', '%s', %d, %d)", + $values['sid'], $nid, $rid, $rtype, $r_mail, $r_name, $count, $recipient_contact_id); } } @@ -559,7 +543,7 @@ } return _send_confirm($values); } - + function _send_deliver($sender, $recipient, $values) { if (mimemail($sender, $recipient, $values['subject'], $values['body'])) { drupal_set_message(t('Message sent to %mail',array('%mail'=>$recipient['mail']))); @@ -708,7 +692,7 @@ } /** - * load and/or update contact info in CiviCRM + * update contact info in CiviCRM * * $params can contain name/value pairs for civicrm's data fields, optionally * prepended by "{$scope}_". The contact record will be created and/or filled @@ -719,7 +703,7 @@ if (!module_exists('civicrm')) return false; if ($scope) $scope .= '_'; - civicrm_initialize(true); + civicrm_initialize(); // fields allowed in the contact record $contact_fields = array('first_name', 'last_name', 'email', 'source', 'prefix', 'suffix', @@ -730,29 +714,45 @@ // create an array of CRM data from $params. Strip out the part of // the variable that conveys scope (sender_ , recipient_) if you have to $record = array(); + $search = array( + 'return.contact_id' => true, + 'return.contact_type' => true, + 'returnFirst' => true, + ); foreach ($params as $key => $value) { - if (!in_array($name = str_replace($scope, '', $key), $contact_fields)) continue; + if (!in_array($name = str_replace($scope, '', $key), $contact_fields)) { + continue; + } $record[$name] = $params[$key]; + $search['return.'. $name] = 1; } // find contact - $search = array(); - if ($user && $id = crm_uf_get_match_id($user->uid)) { - $search['id'] = $id; + require_once('api/UFGroup.php'); + if ($user && $contact_id = crm_uf_get_match_id($user->uid)) { + $search['contact_id'] = $contact_id; } elseif ($mail) { $search['email'] = $mail; } else { - return; // we don't have enough to work with here + watchdog('send', 'Not enough data to perform CiviCRM lookup', WATCHDOG_WARNING); + return; } - if ($res = crm_contact_search($search)) $contact = current($res[0]); + require_once('api/v2/Contact.php'); + if (civicrm_error($contact = civicrm_contact_get($search))) { + watchdog('send', 'CiviCRM API error: civicrm_contact_get. '. var_export($search, true) . var_export($contact, true), WATCHDOG_ERROR); + return; + } + if($contact['contact_id']) { + + // Do we need to update the contact? $updates = array(); foreach ($record as $key => $value) { // populate contact info if it's not there already - if (!isset($contact[$key]) && $value) { + if ($value && $value != $contact[$key]) { $updates[$key] = $value; } // update our referenced array with CRM info @@ -760,24 +760,37 @@ $record[$key] = $contact[$key]; } } - $contact = crm_get_contact($contact); - if (count($updates)) { - $contact = crm_update_contact($contact, $updates); + $contact = array_merge($contact, $updates); + if (civicrm_error($contact = civicrm_contact_add($contact))) { + watchdog('send', 'CiviCRM API error: civicrm_contact_add', WATCHDOG_ERROR); + return; + } } + } else { - // no contact. let's create one - $contact = array_merge(array('email' => $mail), $record); - $contact = crm_create_contact($contact); + + // No contact. Let's create one. + $contact = array_merge(array('email' => $mail, 'contact_type' => 'Individual', 'dupe_check' => true), $record); + if (civicrm_error($contact = civicrm_contact_add($contact))) { + if (strpos($contact['error_message'], 'matching contact') === false) { + watchdog('send', 'CiviCRM API error: civicrm_contact_add', WATCHDOG_ERROR); + return; + } + else { + $contact['contact_id'] = trim(array_shift(explode(',', array_pop(explode(':', $contact['error_message']))))); + } + } } // save data to the referenced $params array if it's not already set foreach ($record as $key => $value) { if (!$params[$scope.$key])$params[$scope.$key] = $value; } + + return $contact['contact_id']; - return $contact; } function _send_previous_recipients($user) { Index: Send.tpl =================================================================== --- Send.tpl (revision 0) +++ Send.tpl (revision 19627) @@ -0,0 +1,71 @@ +{*debug*} +{if ($sent)} +
+

Sent messages

+
+ + {strip} + + + + + + + {/strip} + {foreach from=$sent item=message} + {strip} + + + + + + + {/strip} + {/foreach} +
{ts}Date{/ts}{ts}Subject{/ts}{ts}Message{/ts}{ts}Node / To{/ts}
{$message.date}{$message.subject}{$message.message} + {foreach from=$message.to item=recipient} + + {/foreach} +
{$recipient.node_link}{$recipient.recipient_link}
+
+
+
+{/if} +{if ($received)} +
+

Received messages

+
+ + {strip} + + + + + + + + {/strip} + {foreach from=$received item=message} + {strip} + + + + + + + + {/strip} + {/foreach} +
{ts}Date{/ts}{ts}From{/ts}{ts}Subject{/ts}{ts}Message{/ts}{ts}Node{/ts}
{$message.date}{$message.sender_link}{$message.subject}{$message.message}{$message.node_link}
+
+
+{/if} + +{if !$received && !$sent} +
+
+
{ts}status{/ts}
+
{ts}This contact has not sent or received any "Send to a friend" messages{/ts}
+
+
+{/if} Index: send.module =================================================================== --- send.module (revision 19626) +++ send.module (revision 19627) @@ -46,6 +46,16 @@ 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ); + if (module_exists('civicrm')) { + $items[] = array( + 'path' => 'civicrm/contact/view/send', + 'title' => t('Send history'), + 'callback' => 'send_civicrm_send', + 'description' => t('View send history'), + 'access' => user_access('view all activities'), + 'type' => MENU_CALLBACK, + ); + } foreach (send_modules() as $module => $name) { $items[] = array( 'path' => 'admin/content/send/'. $module, @@ -277,3 +287,109 @@ return call_user_func_array($func, $args); } } + +/** + * Implements: hook_civicrm_links + * This hook retrieves injects information into CiviCRM forms + * + * @param string $op the type of operation being performed + * @param string $objectName the name of the object + * @param int $objectId the unique identifier for the object + * + * @return array|null an array of arrays, each element is a tuple consisting of url, img, title + */ +function send_civicrm_links( $op, $objectName, $objectId ) { + $links = array(); + if ($objectName == 'Contact' && $op == 'tabs.contact.activity') { + // Adds a new tab. + if (user_access('view all activities')) { + $links[] = array( + 'id' => 'Send', + 'title' => t('Send'), + 'url' => url('civicrm/contact/view/send/'. $objectId), + 'weight' => 10, + ); + } + } + return $links; +} + +/** + * Callback to view a contact's send history + * @param integer $contact_id + * a civicrm contact id + */ +function send_civicrm_send($contact_id) { + + civicrm_initialize(); + + // Get all info as sender. + $sent = array(); + $results = db_query('SELECT sid, timestamp, subject, message FROM {send} WHERE contact_id = %d ORDER BY timestamp DESC', $contact_id); + while ($send = db_fetch_array($results)) { + + $send['date'] = format_date($send['timestamp']); + $send['subject'] = check_plain($send['subject']); + $send['message'] = check_plain($send['message']); + $sent[$send['sid']] = $send; + + $result = db_query('SELECT nid, contact_id FROM {send_recipient} WHERE sid = %d', $send['sid']); + $sent[$send['sid']]['to'] = array(); + while ($to = db_fetch_array($result)) { + + // Get link to node. + $node_title = db_result(db_query('SELECT title FROM {node} WHERE nid = %d', $to['nid'])); + $to['node_link'] = l($node_title, 'node/'. $to['nid']); + + // Get link to recipient. + $search = array( + 'contact_id' => $to['contact_id'], + 'return.display_name' => 1, + ); + require_once('api/v2/Contact.php'); + if (civicrm_error($recipient = civicrm_contact_get($search))) { + watchdog('send', 'CiviCRM API error: civicrm_contact_get:'. var_export($search, true), WATCHDOG_ERROR); + continue; + } + $to['recipient_link'] = l($recipient['display_name'], 'civicrm/contact/view', array(), 'reset=1&cid='. $to['contact_id']); + + $sent[$send['sid']]['to'][] = $to; + } + } + + // Get all info as recipient. + $received = array(); + $results = db_query('SELECT s.sid, r.nid, s.timestamp, s.contact_id, s.subject, s.message FROM {send_recipient} r INNER JOIN {send} s ON s.sid = r.sid WHERE r.contact_id = %d', $contact_id); + while ($recipient = db_fetch_array($results)) { + + // Get link to node. + $node_title = db_result(db_query('SELECT title FROM {node} WHERE nid = %d', $recipient['nid'])); + $recipient['node_link'] = l($node_title, 'node/'. $recipient['nid']); + + // Get link to sender. + $search = array( + 'contact_id' => $recipient['contact_id'], + 'return.display_name' => 1, + ); + require_once('api/v2/Contact.php'); + if (civicrm_error($sender = civicrm_contact_get($search))) { + watchdog('send', 'CiviCRM API error: civicrm_contact_get:'. var_export($search, true), WATCHDOG_ERROR); + continue; + } + $recipient['sender_link'] = l($sender['display_name'], 'civicrm/contact/view', array(), 'reset=1&cid='. $recipient['contact_id']); + + $recipient['date'] = format_date($recipient['timestamp']); + $received[$recipient['sid']] = $recipient; + + } + + $template =& CRM_Core_Smarty::singleton(); + $template->template_dir = array_merge((array)$template->template_dir, array(realpath(dirname(__FILE__)))); + $template->assign('sent', $sent); + $template->assign('received', $received); + $template->assign('tplFile', 'Send.tpl'); + + echo $template->fetch('Send.tpl'); + die; + +} Index: send.install =================================================================== --- send.install (revision 19626) +++ send.install (revision 19627) @@ -13,6 +13,7 @@ timestamp INT, subject VARCHAR(200), message TEXT, + contact_id INT DEFAULT NULL PRIMARY KEY(sid) ) /*!40100 DEFAULT CHARACTER SET utf8 */;"); @@ -23,7 +24,8 @@ rtype VARCHAR(50), rcount INT, mail VARCHAR(100), - name VARCHAR(200) + name VARCHAR(200), + contact_id INT DEFAULT NULL ) /*!40100 DEFAULT CHARACTER SET utf8 */;"); db_query("CREATE TABLE {send_setting} ( @@ -47,6 +49,7 @@ timestamp INT, subject VARCHAR(200), message TEXT, + contact_id INT DEFAULT NULL, PRIMARY KEY(sid) )"); @@ -57,7 +60,8 @@ rtype VARCHAR(50), rcount INT, mail VARCHAR(100), - name VARCHAR(200) + name VARCHAR(200), + contact_id INT DEFAULT NULL )"); db_query("CREATE TABLE {send_setting} ( @@ -151,3 +155,138 @@ return $ret; } + +function send_update_3() { + + // Add civicrm contact_id columns. + $ret = array(); + db_add_column($ret, 'send', 'contact_id', 'INT', array('default' => "NULL")); + db_add_column($ret, 'send_recipient', 'contact_id', 'INT', array('default' => "NULL")); + + // Add index on contact_id. + switch ($GLOBALS['db_type']) { + case 'mysql': + case 'mysqli': + $ret[] = update_sql("ALTER TABLE {send} ADD INDEX index_send_contact_id (contact_id)"); + $ret[] = update_sql("ALTER TABLE {send_recipient} ADD INDEX index_send_recipient_contact_id (contact_id)"); + $ret[] = update_sql("ALTER TABLE {send_recipient} ADD INDEX index_send_recipient_sid (sid)"); + break; + case 'pgsql': + $ret[] = update_sql("CREATE INDEX index_send_contact_id ON {send} (contact_id)"); + $ret[] = update_sql("CREATE INDEX index_send_recipient_contact_id ON {send_recipient} (contact_id)"); + $ret[] = update_sql("CREATE INDEX index_send_recipient_sid ON {send_recipient} (sid)"); + break; + } + return $ret; +} + +// Populate our new contact_id field. +function send_update_4() { + $ret = array(); + if (module_exists('civicrm')) { + + civicrm_initialize(true); + require_once('api/UFGroup.php'); + require_once('api/v2/Contact.php'); + + // Using the API to search by email is _really_ _really_ _really_ slow. + // Test to see if we can do a manual query instead. + if (isset($GLOBALS['db_url']['civicrm'])) { + db_set_active("civicrm"); + + // Is the schema 1.x or 2.x ? + $version = db_num_rows(db_query('SHOW COLUMNS FROM civicrm_email LIKE "contact_id"')) +1; + if ($version == 2) { + $email_sql = 'SELECT contact_id FROM civicrm_email WHERE email LIKE "%s"'; + } + else { + $email_sql = 'SELECT civicrm_contact.id as contact_id + FROM civicrm_contact + LEFT JOIN civicrm_location ON ( civicrm_location.entity_table = "civicrm_contact" AND + civicrm_contact.id = civicrm_location.entity_id AND + civicrm_location.is_primary = TRUE ) + LEFT JOIN civicrm_email ON ( civicrm_location.id = civicrm_email.location_id AND civicrm_email.is_primary = TRUE ) + WHERE civicrm_email.email LIKE "%s"'; + } + db_set_active(); + } + + // Process {send} table. + // This might time-out due to CRM-2955, so select only non-processed records + $result = db_query('SELECT DISTINCT uid, mail FROM {send} WHERE contact_id IS NULL'); + while($sender = db_fetch_object($result)) { + $contact_id = 0; + if ($sender->uid) { + $contact_id = (int)crm_uf_get_match_id($sender->uid); + } + elseif ($sender->mail) { + if ($email_sql) { + db_set_active('civicrm'); + $contact_id = (int)db_result(db_query($email_sql, $sender->mail)); + db_set_active(); + } + else { + $search = array( + 'return.contact_id' => 1, + 'email' => $sender->mail, + ); + + if (civicrm_error($contact = civicrm_contact_get($search))) { + continue; + } + $contact_id = (int)$contact['contact_id']; + } + } + + // Add ID + $ret[] = update_sql("UPDATE {send} SET contact_id = $contact_id WHERE uid = $sender->uid AND mail = '$sender->mail'"); + + } + + // Process {send_recipient} table. + // This might time-out due to CRM-2955, so select only non-processed records + $result = db_query('SELECT DISTINCT mail FROM {send_recipient} WHERE contact_id IS NULL'); + while($recipient = db_fetch_object($result)) { + $contact_id = 0; + + // Switch to CiviCRM db and do a manual query if possible. + if ($email_sql) { + db_set_active('civicrm'); + $contact_id = (int)db_result(db_query($email_sql, $recipient->mail)); + db_set_active(); + } + else { + $search = array( + 'return.contact_id' => 1, + 'email' => $recipient->mail, + ); + if (civicrm_error($contact = civicrm_contact_get($search))) { + continue; + } + $contact_id = (int)$contact['contact_id']; + } + + // Add ID + $ret[] = update_sql("UPDATE {send_recipient} SET contact_id = $contact_id WHERE mail = '{$recipient->mail}'"); + + } + + // remove old records from activity tables + if ($version == 2) { + db_set_active('civicrm'); + $activity_group = db_result(db_query('SELECT id FROM civicrm_option_group WHERE name="activity_type"')); + $activity_type = db_result(db_query('SELECT value FROM civicrm_option_value WHERE option_group_id = ' . $activity_group .' AND (name="send" OR name = "sent"')); + $ret[] = update_sql('DELETE FROM civicrm_activity WHERE activity_type_id = "'. $activity_type .'"'); + $ret[] = update_sql('DELETE FROM civicrm_activity_history WHERE module = "send"'); + $ret[] = update_sql('DELETE FROM civicrm_option_value WHERE option_group_id = ' . $activity_group .' AND name="send"'); + db_set_active(); + } + elseif ($version == 1) { + db_set_active('civicrm'); + $ret[] = update_sql('DELETE FROM civicrm_activity_history WHERE activity_type = "sent" OR module = "send"'); + db_set_active(); + } + + } + return $ret; +}