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

Reply via email to