http://www.mediawiki.org/wiki/Special:Code/MediaWiki/67585
Revision: 67585 Author: tomasz Date: 2010-06-08 03:31:47 +0000 (Tue, 08 Jun 2010) Log Message: ----------- Checking in development copy for tracking Added Paths: ----------- civicrm/trunk/sites/all/modules/civicrm_batchmerge/ civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge.info civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge.module civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge_merge.php Added: civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge.info =================================================================== --- civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge.info (rev 0) +++ civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge.info 2010-06-08 03:31:47 UTC (rev 67585) @@ -0,0 +1,7 @@ +name = CiviCRM BatchMerge +description = "Merge CiviCRM records in bulk instead of one at a time" +package = CiviCRM +version = 2.x-dev +core = 6.x +dependencies[] = civicrm + Property changes on: civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge.info ___________________________________________________________________ Added: svn:executable + * Added: civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge.module =================================================================== --- civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge.module (rev 0) +++ civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge.module 2010-06-08 03:31:47 UTC (rev 67585) @@ -0,0 +1,329 @@ +<?php + +/** + * Implementation of hook_menu() + */ +function civicrm_batchmerge_menu() { + $items = array(); + + $items['civicrm/batchmerge'] = array( + 'title' => t("Merge a Batch of Records"), + 'access callback' => true, //change to array('administer CiviCRM'), + 'type' => MENU_CALLBACK, + 'page callback' => 'civicrm_batchmerge_page', + ); + + return $items; +} + +/** + * Menu callback + * + */ +function civicrm_batchmerge_page() { + $output = drupal_get_form('civicrm_batchmerge_form'); + + return $output; +} + +/** + * Form for collecting data and beginning batch merge + */ +function civicrm_batchmerge_form() { + $form['civicrm_batchmerge_size'] = array( + '#type' => 'select', + '#title' => t('Maximum Number of Records to Match'), + '#required' => TRUE, + '#default_value' => 1, + '#options' => array( + 1 => 1, + 20 => 20, + 100 => 100, + 500 => 500, + 1000 => 1000, + 2000 => 2000, + 5000 => 5000, + 8000 => 8000), + ); + + $form['civicrm_batchmerge_options'] = array( + '#type' => 'select', + '#title' => t('Match Levels'), + '#required' => TRUE, + '#default_value' => 'easy', + '#options' => array( + 'easy' => t("Easy: Exact email and sort name match"), + 'medium' => t('Medium: Not yet available'), + 'hard' => t('Hard: Not yet available'), + ), + ); + + $form['civicrm_batchmerge_prevID'] = array( + '#prefix' => t('For merging one record during testing'), + '#title' => t('Old ID'), + '#type' => 'textfield', + '#description' => t('Enter lesser id'), + ); + + $form['civicrm_batchmerge_newID'] = array( + '#prefix' => t('For merging one record during testing'), + '#title' => t('New ID'), + '#type' => 'textfield', + '#description' => t('Enter greater id'), + ); + + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Merge') + ); + + return $form; +} + +/** + * Process batch merge based on user-supplied parameters + */ +function civicrm_batchmerge_form_submit($form_id, $form_values) { + civicrm_initialize(true); + + // the class based on Civi's merge class + require_once 'civicrm_batchmerge_merge.php'; + + $merge = new CRM_Contact_BatchMerge; + + $rows = array(); + $resultMsg = ''; + $batchSize = $level = $oid = $cid = ''; + + $batchSize = $form_values['values']['civicrm_batchmerge_size']; + $level = $form_values['values']['civicrm_batchmerge_options']; + $oid = $form_values['values']['civicrm_batchmerge_prevID']; + $cid = $form_values['values']['civicrm_batchmerge_newID']; + + //if values for singles are included + if ($batchSize == '1' && $cid != '' && $oid != '') { + // ignore bad input + if(!is_numeric($batchSize) || !is_numeric($oid) || !is_numeric($cid)) { + drupal_set_message("Only integers are accepted. Please try again."); + return; + } + + // merge single transaction + $single = _civicrm_batchmerge_single($merge, $cid, $oid); + + $resultMsg = ($single) ? "Merge Complete" : "There was an error processing the merge. Please try again."; + drupal_set_message($resultMsg); + return; + } + + // process "easy" merges + if (is_numeric($batchSize) && $batchSize > '1' && $level == 'easy') { + $multiple = _civicrm_batchmerge_multiple_easy($merge, $batchSize); + + $resultMsg = ($multiple) ? "Merge Complete" : "There was an error processing the merge. Please try again."; + drupal_set_message($resultMsg); + return; + + } + + if ($level != 'easy') { + drupal_set_message("Other merge types are not yet available. Please choose Easy."); + return; + } + + + drupal_set_message("There was an error processing your request. Please fill out the form and try again."); + return; +} + +/** + * Merge single value + */ +function _civicrm_batchmerge_single($merge, $cid, $oid) { + //get the merge data values + $rows = $merge->matchValues($cid, $oid); + + //var_dump($rows); + + //merge data + $mergeRes = $merge->mergeValues($rows); + + drupal_set_message($mergeRes); + watchdog('batchmerge', $mergeRes); + + return true; + +} + +/** + * Match based on exact email address and sort name + */ +function _civicrm_batchmerge_multiple_easy($merge, $batchSize = '1000') { + + $matches = array(); + $rows = array(); + + //match based on email address + $matches = _civicrm_batchmerge_get_email_matches($batchSize); + + if (!empty($matches)) { + //match based on "sort name" field + foreach ($matches as $key => $currMatch) { + $matchRes = _civicrm_batchmerge_match_name($currMatch['id'], $currMatch['match_id']); + + //if it doesn't match both, ignore + if (!$matchRes) { + unset($matches[$key]); + } + } + } + + if (!empty($matches)) { + foreach ($matches as $mergeMe) { + $cid = $mergeMe['id']; + $oid = $mergeMe['match_id']; + $rows[] = $merge->matchValues($cid, $oid); + //for testing + //drupal_set_message($cid . " AND " . $oid); + + //merge data + $mergeRes = $merge->mergeValues($rows); + watchdog('batchmerge', $mergeRes); + } + } + + return true; +} + + +/** + * Returns array of ids with exact email matches + * @param number of matches to return + */ +function _civicrm_batchmerge_get_email_matches($batchSize = 1000) { + $sql = 'SELECT near.contact_id, far.contact_id AS match_id + FROM civicrm_email AS near, civicrm_email AS far + WHERE near.email = far.email + AND near.contact_id != far.contact_id + AND near.contact_id < far.contact_id + ORDER BY near.contact_id, far.contact_id + LIMIT ' . $batchSize; + $result =& CRM_Core_DAO::executeQuery( $sql, CRM_Core_DAO::$_nullArray ); + + $matchArray = array(); + $i = 0; + while ($result->fetch()) { + $matchArray[$i]['id'] = $result->contact_id; + $matchArray[$i]['match_id'] = $result->match_id; + $i++; + } + + return $matchArray; +} + +/** + * Checks to see if sort name matches + * @param two contact ids to compare + */ +function _civicrm_batchmerge_match_name($primary_cid, $name_cid) { + + if (!is_numeric($primary_cid) || !is_numeric($name_cid)) + return array(); + + $sql = 'SELECT sort_name FROM civicrm_contact WHERE id = ' . $primary_cid; + $res =& CRM_Core_DAO::executeQuery( $sql, CRM_Core_DAO::$_nullArray ); + $res->fetch(); + $primaryName = $res->sort_name; + + $sql = 'SELECT sort_name FROM civicrm_contact WHERE id = ' . $name_cid; + $res =& CRM_Core_DAO::executeQuery( $sql, CRM_Core_DAO::$_nullArray ); + $res->fetch(); + $matchName = $res->sort_name; + + return ($primaryName == $matchName) ? true : false; +} + + +/** + * TODO: The following two functions (and another adapted for scoring) from + * the CiviMerge module + * will help when creating "medium" and "hard" level matches + */ +function _civicrm_batchmerge_get_similar_name($cid, $characters = 100) { + if (!is_numeric($cid)) + return array(); + + + $sql = 'SELECT sort_name FROM civicrm_contact WHERE id = ' . $cid; + $res =& CRM_Core_DAO::executeQuery( $sql, CRM_Core_DAO::$_nullArray ); + $res->fetch(); + $sort_name = $res->sort_name; + + //$sql = 'SELECT id FROM civicrm_contact far WHERE sort_name LIKE "%1%%"'; + $sql = 'SELECT id FROM civicrm_contact far WHERE sort_name LIKE "' . $sort_name . '"'; + $sort_name = substr($sort_name, 0, $characters); + $params = array(1 => array($sort_name, 'String')); + $res =& CRM_Core_DAO::executeQuery($sql, $params); + + $ret = array(); + while ($res->fetch()) { + $ret[] = $res->id; + } + + return $ret; +} + + +function _civicrm_batchmerge_get_similar_location($cid, $table, $field) { + if (!is_numeric($cid)) + return array(); + + $sql = 'SELECT far.contact_id AS contact_id FROM ' . $table . ' far '; + $sql .= 'INNER JOIN ' . $table . ' near ON far.' . $field . ' = near.' . $field . ' '; + $sql .= 'WHERE near.contact_id = ' . $cid; + $res =& CRM_Core_DAO::executeQuery( $sql, CRM_Core_DAO::$_nullArray ); + $ret = array(); + while ($res->fetch()) { + $ret[] = $res->contact_id; + } + + return $ret; +} + +/** + * TODO: This function will swap the old and new records + * if the old record has been reviewed + * It does not yet RETURN the swap, recommend returning + * true or false and moving the inversion into the calling function + * WM wants to verify address information to decide which ones to + * invert and which to keep + */ +function _civicrm_batchmerge_compare_tags($cid, $oid) { + // this is specific to WM, need to change the order of tagged records + //so old Reviewed records replace newer unreviewed records + require_once 'api/v2/EntityTag.php'; + require_once 'api/v2/Tag.php'; + + $tagCID = array( 'contact_id' => $cid ); + $resultCID = & civicrm_entity_tag_get( $tagCID ); + $tagOID = array( 'contact_id' => $oid ); + $resultOID = & civicrm_entity_tag_get( $tagOID ); + + //TODO Do not hard code the tag ID + $invertCID = $invertOID = false; + + foreach($resultCID as $tags) { + $invertCID = in_array(7, $tags); + } + + foreach($resultOID as $tagsOld) { + $invertOID = in_array(7, $tags); + } + + if($invertOID == true && $invertCID == false) { + $temp = $cid; + $cid = $oid; + $oid = $temp; + } +} Property changes on: civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge.module ___________________________________________________________________ Added: svn:executable + * Added: civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge_merge.php =================================================================== --- civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge_merge.php (rev 0) +++ civicrm/trunk/sites/all/modules/civicrm_batchmerge/civicrm_batchmerge_merge.php 2010-06-08 03:31:47 UTC (rev 67585) @@ -0,0 +1,418 @@ +<?php + +/* + * Developed for the Wikimedia Foundation + * to batch merge duplicate contacts + * based on CiviCRM class CRM_Contact_Merge + * copyright CiviCRM 2010 +*/ + +require_once 'CRM/Core/Form.php'; +require_once 'CRM/Dedupe/Merger.php'; +require_once 'CRM/Contact/BAO/Contact.php'; +require_once 'CRM/Contact/Form/Merge.php'; + +class CRM_Contact_BatchMerge { + // the id of the contact that there's a duplicate for + // this one will inherit the $_oid's properties and remain in the system + var $_cid = null; + + // the id of the other contact - the duplicate one that will get deleted + var $_oid = null; + + var $_contactType = null; + + // variable to keep track of location types need overwriting + protected $_overwriteLocTypeIds = array(); + + + function matchValues($cid, $oid) { + require_once 'api/v2/Contact.php'; + require_once 'CRM/Core/BAO/CustomGroup.php'; + require_once 'CRM/Core/OptionGroup.php'; + require_once 'CRM/Core/OptionValue.php'; + + if(!isset($cid) && !isset($oid)) { + return; + } + + $this->_cid = $cid; + $this->_oid = $oid; + + $diffs = CRM_Dedupe_Merger::findDifferences($cid, $oid); + + $mainParams = array('contact_id' => $cid, 'return.display_name' => 1); + $otherParams = array('contact_id' => $oid, 'return.display_name' => 1); + + // API 2 has to have the requested fields spelled out + foreach (CRM_Dedupe_Merger::$validFields as $field) { + $mainParams["return.$field"] = $otherParams["return.$field"] = 1; + } + + $main =& civicrm_contact_get($mainParams); + $other =& civicrm_contact_get($otherParams); + + //CRM-4524 + $main = reset( $main ); + $other = reset( $other ); + + $this->_contactType = $main['contact_type']; + + if (!isset($diffs['contact'])) + $diffs['contact'] = array(); + + //these were not returning as diffs from newer ids + $diffs['contact'][] = 'individual_prefix_id'; + $diffs['contact'][] = 'greeting_type_id'; + + foreach ($diffs['contact'] as $field) { + foreach (array('other', 'main') as $moniker) { + $contact =& $$moniker; + $value = CRM_Utils_Array::value( $field, $contact ); + $value = str_replace('-', '', $value); + //do not replace old values with blanks + if ($value != '') { + $rows["move_$field"] = $value; + } + } + + } + + // move any locations from the old record that have not been updated in the newer one + //TODO: This will include address types from the old one only if they don't exists in the newer + //but if the type exists in the new one, it will be overwritten in the old. + //Should some of the data be merged if missing from new? + //Will we always want the newer one saved? + require_once 'api/v2/Location.php'; + $locations['main'] =& civicrm_location_get($mainParams); + $locations['other'] =& civicrm_location_get($otherParams); + + $typeNames = CRM_Core_PseudoConstant::locationType(); + + $locationMatch = array(); + + foreach($locations['main'] as $currLocation) { + $locationMatch[] = $currLocation['location_type_id']; + } + + foreach($locations['other'] as $currLocation) { + $currType = $currLocation['location_type_id']; + + //do not add older addresses if there is one in the newer + if (!in_array($currType, $locationMatch)) { + + $locationType = $typeNames[$currType]; + + $params = array(); + + $params = array( + 'contact_id' => $cid, + 'location_type' => $locationType, + 'location_type_id' => $currLocation['location_type_id'], + 'email' => ($currLocation['email']) ? $currLocation['email'] : array(), + 'address' => ($currLocation['address']) ? $currLocation['address'] : array(), + 'phone' => ($currLocation['phone']) ? $currLocation['phone'] : array(), + 'im' => ($currLocation['im']) ? $currLocation['im'] : array(), + 'openid' => ($currLocation['openid']) ? $currLocation['openid'] : array(), + ); + + $rows['location'][$currType] = $params; + } + + } + + // handle custom fields + $mainTree =& CRM_Core_BAO_CustomGroup::getTree($this->_contactType, $this, $this->_cid, -1); + $otherTree =& CRM_Core_BAO_CustomGroup::getTree($this->_contactType, $this, $this->_oid, -1); + + if (!isset($diffs['custom'])) + $diffs['custom'] = array(); + + foreach ($otherTree as $gid => $group) { + $foundField = false; + if ( ! isset( $group['fields'] ) ) { + continue; + } + + foreach ($group['fields'] as $fid => $field) { + if (in_array($fid, $diffs['custom'])) { + if (!$foundField) { + $foundField = true; + } + if ( is_array( $mainTree[$gid]['fields'][$fid]['customValue'] ) ) { + foreach ( $mainTree[$gid]['fields'][$fid]['customValue'] as $valueId => $values ) { + $rows["move_custom_$fid"]['main'] = CRM_Core_BAO_CustomGroup::formatCustomValues( $values, + $field ); + } + } + if ( is_array( $otherTree[$gid]['fields'][$fid]['customValue'] ) ) { + foreach ( $otherTree[$gid]['fields'][$fid]['customValue'] as $valueId => $values ) { + $rows["move_custom_$fid"]['other'] = CRM_Core_BAO_CustomGroup::formatCustomValues( $values, + $field ); + $value = $values['data'] ? $values['data'] : $this->_qfZeroBug; + } + } + + $rows["move_custom_$fid"] = "1"; + } + } + } + + // add the related tables and unset the ones that don't sport any of the duplicate contact's info + $relTables = CRM_Dedupe_Merger::relTables(); + $activeRelTables = CRM_Dedupe_Merger::getActiveRelTables($oid); + foreach ($relTables as $name => $null) { + if (!in_array($name, $activeRelTables)) { + unset($relTables[$name]); + continue; + } + } + + foreach ($relTables as $name => $null) { + $rows["move_$name"] = "1"; + unset($rows[$name]); + } + + $rows["move_$name"] = "1"; + + return $rows; + } + + /** + * Take the rows created by the matchValues function + * Merge the older into the newer + * TODO: Needs more error checking and return error messages when + * something fails + */ + public function mergeValues($rows) { + if (empty($rows)) + return "There is no data to merge"; + + $formValues = $rows; + + // user can't choose to move cases without activities (CRM-3778) + if ( $formValues['move_rel_table_cases'] == '1' && + array_key_exists('move_rel_table_activities', $formValues) ) { + $formValues['move_rel_table_activities'] = '1'; + } + + $relTables =& CRM_Dedupe_Merger::relTables(); + $moveTables = array(); + foreach ($formValues as $key => $value) { + if ($value == $this->_qfZeroBug) $value = '0'; + if ((in_array(substr($key, 5), CRM_Dedupe_Merger::$validFields) or substr($key, 0, 12) == 'move_custom_') and $value != null) { + $submitted[substr($key, 5)] = $value; + } elseif (substr($key, 0, 14) == 'move_location_' and $value != null) { + $locations[substr($key, 14)] = $value; + } elseif (substr($key, 0, 15) == 'move_rel_table_' and $value == '1') { + $moveTables = array_merge($moveTables, $relTables[substr($key, 5)]['tables']); + } + } + + // FIXME: fix gender, prefix and postfix, so they're edible by createProfileContact() + $names['gender'] = array('newName' => 'gender_id', 'groupName' => 'gender'); + $names['individual_prefix'] = array('newName' => 'prefix_id', 'groupName' => 'individual_prefix'); + $names['individual_suffix'] = array('newName' => 'suffix_id', 'groupName' => 'individual_suffix'); + $names['greeting_type'] = array('newName' => 'greeting_type_id', 'groupName' => 'greeting_type'); + CRM_Core_OptionGroup::lookupValues($submitted, $names, true); + + // FIXME: fix custom fields so they're edible by createProfileContact() + $cgTree =& CRM_Core_BAO_CustomGroup::getTree($this->_contactType, $this, null, -1); + foreach ($cgTree as $key => $group) { + if (!isset($group['fields'])) continue; + foreach ($group['fields'] as $fid => $field) { + $cFields[$fid]['attributes'] = $field; + } + } + + if (!isset($submitted)) $submitted = array(); + + foreach ($submitted as $key => $value) { + if (substr($key, 0, 7) == 'custom_') { + $fid = (int) substr($key, 7); + $htmlType = $cFields[$fid]['attributes']['html_type']; + switch ( $htmlType ) { + case 'File': + $customFiles[] = $fid; + unset($submitted["custom_$fid"]); + break; + case 'Select Country': + case 'Select State/Province': + $submitted[$key] = CRM_Core_BAO_CustomField::getDisplayValue($value, $fid, $cFields); + break; + + case 'CheckBox': + case 'Multi-Select': + case 'Multi-Select Country': + case 'Multi-Select State/Province': + // Merge values from both contacts for multivalue fields, CRM-4385 + // get the existing custom values from db. + require_once 'CRM/Core/BAO/CustomValueTable.php'; + $customParams = array( 'entityID' => $this->_cid, $key => true ); + $customfieldValues = CRM_Core_BAO_CustomValueTable::getValues( $customParams ); + if ( CRM_Utils_array::value( $key, $customfieldValues ) ) { + $existingValue = explode( CRM_Core_DAO::VALUE_SEPARATOR, $customfieldValues[$key] ); + if ( is_array( $existingValue ) && !empty( $existingValue ) ) { + $mergeValue = $submmtedCustomValue = array( ); + if ( $value ) { + $submmtedCustomValue = explode( CRM_Core_DAO::VALUE_SEPARATOR, $value ); + } + + //hack to remove null and duplicate values from array. + foreach ( array_merge( $submmtedCustomValue, $existingValue ) as $k => $v ) { + if ( $v != '' && !in_array( $v, $mergeValue ) ) { + $mergeValue[] = $v; + } + } + + //keep state and country as array format. + //for checkbox and m-select format w/ VALUE_SEPERATOR + if ( in_array( $htmlType, array( 'CheckBox', 'Multi-Select' ) ) ) { + $submitted[$key] = + CRM_Core_BAO_CustomOption::VALUE_SEPERATOR . + implode( CRM_Core_BAO_CustomOption::VALUE_SEPERATOR, + $mergeValue ) . + CRM_Core_BAO_CustomOption::VALUE_SEPERATOR; + } else { + $submitted[$key] = $mergeValue; + } + } + } else if ( in_array( $htmlType, array( 'Multi-Select Country', 'Multi-Select State/Province' ) ) ) { + //we require submitted values should be in array format + if ( $value ) { + $mergeValueArray = explode( CRM_Core_DAO::VALUE_SEPARATOR, $value ); + //hack to remove null values from array. + $mergeValue = array( ); + foreach ( $mergeValueArray as $k => $v ) { + if ( $v != '' ) { + $mergeValue[] = $v; + } + } + $submitted[$key] = $mergeValue; + } + } + break; + + default: + break; + } + } + } + + + //move locations that were in the old record and not in the new + if ($formValues['location']) { + foreach ($formValues['location'] as $locations) { + $newLocation =& civicrm_location_add( $locations ); + + //the API is not saving the address information + // use local function to save it to db + + //add things we need + $insertData = $locations['address']; + $insertData['contact_id'] = $this->_cid; + + //delete things we don't need + unset($insertData['display']); + unset($insertData['id']); + + //save + $compensate = self::_civicrm__batchmerge_address_set($insertData); + } + } + + // handle the related tables + if (isset($moveTables)) { + CRM_Dedupe_Merger::moveContactBelongings($this->_cid, $this->_oid, $moveTables); + } + + // move file custom fields + // FIXME: move this someplace else (one of the BAOs) after discussing + // where to, and whether CRM_Core_BAO_File::delete() shouldn't actually, + // like, delete a file... + require_once 'CRM/Core/BAO/File.php'; + require_once 'CRM/Core/DAO/CustomField.php'; + require_once 'CRM/Core/DAO/CustomGroup.php'; + require_once 'CRM/Core/DAO/EntityFile.php'; + require_once 'CRM/Core/Config.php'; + + if (!isset($customFiles)) $customFiles = array(); + + foreach ($customFiles as $customId) { + list($tableName, $columnName, $groupID) = CRM_Core_BAO_CustomField::getTableColumnGroup($customId); + + // get the contact_id -> file_id mapping + $fileIds = array(); + $sql = "SELECT entity_id, {$columnName} AS file_id FROM {$tableName} WHERE entity_id IN ({$this->_cid}, {$this->_oid})"; + $dao =& CRM_Core_DAO::executeQuery($sql, CRM_Core_DAO::$_nullArray); + while ($dao->fetch()) { + $fileIds[$dao->entity_id] = $dao->file_id; + } + $dao->free(); + + // delete the main contact's file + CRM_Core_BAO_File::delete($fileIds[$this->_cid], $this->_cid, $customId); + + // move the other contact's file to main contact + $sql = "UPDATE {$tableName} SET {$columnName} = {$fileIds[$this->_oid]} WHERE entity_id = {$this->_cid}"; + CRM_Core_DAO::executeQuery($sql, CRM_Core_DAO::$_nullArray); + $sql = "UPDATE civicrm_entity_file SET entity_id = {$this->_cid} WHERE entity_table = '{$tableName}' AND file_id = {$fileIds[$this->_oid]}"; + CRM_Core_DAO::executeQuery($sql, CRM_Core_DAO::$_nullArray); + } + + // move other's belongings and delete the other contact + CRM_Dedupe_Merger::moveContactBelongings($this->_cid, $this->_oid); + $otherParams = array('contact_id' => $this->_oid); + civicrm_contact_delete($otherParams); + + if (isset($submitted)) { + $submitted['contact_id'] = $this->_cid; + CRM_Contact_BAO_Contact::createProfileContact($submitted, CRM_Core_DAO::$_nullArray, $this->_cid); + } + + $resultsMsg = "Merged " . $this->_oid . " into " . l($this->_cid, 'civicrm/contact/view', array('query' => 'reset=1&cid='.$this->_cid)); + return $resultsMsg; + } + + /** + * Add an address to a contact. + * Adapted from David Strauss' CiviCRM api module + */ + public function _civicrm__batchmerge_address_set($address) { + $db = new civicrm_api_db(); + + if (!array_key_exists('location_type_id', $address)) { + $address['location_type_id'] = civicrm_api_default_location_type_id(); + } + + if (array_key_exists('country', $address)) { + $address['country_id'] = civicrm_api_country_id($address['country']); + unset($address['country']); + } + + if (!array_key_exists('country_id', $address) || !$address['country_id']) { + $address['country_id'] = civicrm_api_country_id('US'); + } + + if (array_key_exists('state_province', $address)) { + $id = civicrm_api_state_province_id($address['country_id'], $address['state_province']); + if ($id) { + $address['state_province_id'] = $id; + } + unset($address['state_province']); + } + + $primary = db_result(db_query('SELECT COUNT(*) FROM civicrm_address WHERE contact_id = %d AND is_primary = 1 AND location_type_id <> %d', array($address['contact_id'], $address['location_type_id']))); + if ($primary > 0 && $address['is_primary']) { + db_query('UPDATE civicrm_address SET is_primary = 0 WHERE contact_id = %d', $address['contact_id']); + } + else if ($primary == 0) { + $address['is_primary'] = 1; + } + + // Insert the new address + $columns = implode(',', array_keys($address)); + $placeholders = db_placeholders($address, 'text'); + db_query('INSERT INTO civicrm_address (' . $columns . ') VALUES (' . $placeholders . ')', $address); + } +} _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs