Skip to content
Snippets Groups Projects
Commit 709650a0 authored by totten's avatar totten
Browse files

Merge pull request #8445 from eileenmcnaughton/merge_rc

CRM-18673 fix merge handling of identifal addresses
parents 88af9a95 d48ad2c0
Branches 4.7.8-rc
Tags 4.7.8
No related merge requests found
......@@ -868,20 +868,33 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m
// Rule: Catch address conflicts (same address type on both contacts)
if ($fieldName == 'address') {
$mainNewLocTypeId = $migrationInfo['location_blocks'][$fieldName][$fieldCount]['locTypeId'];
if (
isset($migrationInfo['main_details']['location_blocks']['address']) &&
!empty($migrationInfo['main_details']['location_blocks']['address'])
) {
$otherAddresses = $migrationInfo['other_details']['location_blocks']['address'];
$otherAddressLookup = array();
foreach ($otherAddresses as $otherAddressIndex => $otherAddress) {
$otherAddressLookup[$otherAddress['location_type_id']] = $otherAddressIndex;
}
// Look for this LocTypeId in the results
// @todo This can be streamlined using array_column() in PHP 5.5+
foreach ($migrationInfo['main_details']['location_blocks']['address'] as $addressKey => $addressRecord) {
if ($addressRecord['location_type_id'] == $mainNewLocTypeId) {
$otherAddressIndex = CRM_Utils_Array::value($addressRecord['location_type_id'], $otherAddressLookup);
$hasMatchingAddress = FALSE;
foreach ($otherAddresses as $otherAddress) {
if (self::addressIsSame($addressRecord, $otherAddress)) {
$hasMatchingAddress = TRUE;
}
}
if ($hasMatchingAddress) {
unset($migrationInfo[$key]);
}
elseif (!empty($otherAddresses[$otherAddressIndex]) && !self::addressIsSame($addressRecord, $otherAddresses[$otherAddressIndex])) {
$conflicts[$key] = NULL;
break;
}
}
}
}
// For other locations, don't merge/add if the values are the same
......@@ -926,6 +939,27 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m
return FALSE;
}
/**
* Compare 2 addresses to see if they are the same.
*
* @param array $mainAddress
* @param array $comparisonAddress
*
* @return bool
*/
static protected function addressIsSame($mainAddress, $comparisonAddress) {
$keysToIgnore = array('id', 'is_primary', 'is_billing', 'manual_geo_code', 'contact_id');
foreach ($comparisonAddress as $field => $value) {
if (in_array($field, $keysToIgnore)) {
continue;
}
if (!empty($value) && $mainAddress[$field] != $value) {
return FALSE;
}
}
return TRUE;
}
/**
* A function to build an array of information about location blocks that is
* required when merging location fields
......
......@@ -353,6 +353,58 @@ class api_v3_JobTest extends CiviUnitTestCase {
), 4);
}
/**
* Test the batch merge does not create duplicate emails.
*
* Test CRM-18546, a 4.7 regression whereby a merged contact gets duplicate emails.
*/
public function testBatchMergeMatchingAddress() {
for ($x = 0; $x <= 2; $x++) {
$this->individualCreate(array(
'api.address.create' => array(
'location_type_id' => 'Home',
'street_address' => 'Appt 115, The Batcave',
'city' => 'Gotham',
'postal_code' => 'Nananananana',
),
));
}
// Different location type, still merge, identical.
$this->individualCreate(array(
'api.address.create' => array(
'location_type_id' => 'Main',
'street_address' => 'Appt 115, The Batcave',
'city' => 'Gotham',
'postal_code' => 'Nananananana',
),
));
$this->individualCreate(array(
'api.address.create' => array(
'location_type_id' => 'Home',
'street_address' => 'Appt 115, The Batcave',
'city' => 'Gotham',
'postal_code' => 'Batman',
),
));
$result = $this->callAPISuccess('Job', 'process_batch_merge', array());
$this->assertEquals(3, count($result['values']['merged']));
$this->assertEquals(1, count($result['values']['skipped']));
$this->callAPISuccessGetCount('Contact', array('street_address' => 'Appt 115, The Batcave'), 2);
$contacts = $this->callAPISuccess('Contact', 'get', array('is_deleted' => 0));
$deletedContacts = $this->callAPISuccess('Contact', 'get', array('is_deleted' => 1));
$this->callAPISuccessGetCount('Address', array(
'street_address' => 'Appt 115, The Batcave',
'contact_id' => array('IN' => array_keys($contacts['values'])),
), 3);
$this->callAPISuccessGetCount('Address', array(
'street_address' => 'Appt 115, The Batcave',
'contact_id' => array('IN' => array_keys($deletedContacts['values'])),
), 2);
}
/**
* Test the batch merge by id range.
*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment