Skip to content

Commit

Permalink
Merge pull request #11691 from JKingsnorth/CRM-21773
Browse files Browse the repository at this point in the history
CRM-21773 Fix merging multi-value custom fields
  • Loading branch information
eileenmcnaughton authored Mar 5, 2018
2 parents 78a4b4c + 641a8cb commit 7fba879
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 23 deletions.
58 changes: 35 additions & 23 deletions CRM/Dedupe/Merger.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,25 @@ class CRM_Dedupe_Merger {
* @return array
*/
public static function relTables() {
static $relTables;

// Setting these merely prevents enotices - but it may be more appropriate not to add the user table below
// if the url can't be retrieved. A more standardised way to retrieve them is.
// CRM_Core_Config::singleton()->userSystem->getUserRecordUrl() - however that function takes a contact_id &
// we may need a different function when it is not known.
$title = $userRecordUrl = '';
if (!isset(Civi::$statics[__CLASS__]['relTables'])) {

$config = CRM_Core_Config::singleton();
if ($config->userSystem->is_drupal) {
$userRecordUrl = CRM_Utils_System::url('user/%ufid');
$title = ts('%1 User: %2; user id: %3', array(1 => $config->userFramework, 2 => '$ufname', 3 => '$ufid'));
}
elseif ($config->userFramework == 'Joomla') {
$userRecordUrl = $config->userSystem->getVersion() > 1.5 ? $config->userFrameworkBaseURL . "index.php?option=com_users&view=user&task=user.edit&id=" . '%ufid' : $config->userFrameworkBaseURL . "index2.php?option=com_users&view=user&task=edit&id[]=" . '%ufid';
$title = ts('%1 User: %2; user id: %3', array(1 => $config->userFramework, 2 => '$ufname', 3 => '$ufid'));
}
// Setting these merely prevents enotices - but it may be more appropriate not to add the user table below
// if the url can't be retrieved. A more standardised way to retrieve them is.
// CRM_Core_Config::singleton()->userSystem->getUserRecordUrl() - however that function takes a contact_id &
// we may need a different function when it is not known.
$title = $userRecordUrl = '';

$config = CRM_Core_Config::singleton();
if ($config->userSystem->is_drupal) {
$userRecordUrl = CRM_Utils_System::url('user/%ufid');
$title = ts('%1 User: %2; user id: %3', array(1 => $config->userFramework, 2 => '$ufname', 3 => '$ufid'));
}
elseif ($config->userFramework == 'Joomla') {
$userRecordUrl = $config->userSystem->getVersion() > 1.5 ? $config->userFrameworkBaseURL . "index.php?option=com_users&view=user&task=user.edit&id=" . '%ufid' : $config->userFrameworkBaseURL . "index2.php?option=com_users&view=user&task=edit&id[]=" . '%ufid';
$title = ts('%1 User: %2; user id: %3', array(1 => $config->userFramework, 2 => '$ufname', 3 => '$ufid'));
}

if (!$relTables) {
$relTables = array(
'rel_table_contributions' => array(
'title' => ts('Contributions'),
Expand Down Expand Up @@ -155,8 +155,12 @@ public static function relTables() {

// Allow hook_civicrm_merge() to adjust $relTables
CRM_Utils_Hook::merge('relTables', $relTables);

// Cache the results in a static variable
Civi::$statics[__CLASS__]['relTables'] = $relTables;
}
return $relTables;

return Civi::$statics[__CLASS__]['relTables'];
}

/**
Expand Down Expand Up @@ -273,11 +277,12 @@ public static function locTables() {
* We treat multi-valued custom sets as "related tables" similar to activities, contributions, etc.
* @param string $request
* 'relTables' or 'cidRefs'.
* @return array
* @see CRM-13836
*/
public static function getMultiValueCustomSets($request) {
static $data = NULL;
if ($data === NULL) {

if (!isset(Civi::$statics[__CLASS__]['multiValueCustomSets'])) {
$data = array(
'relTables' => array(),
'cidRefs' => array(),
Expand All @@ -296,8 +301,12 @@ public static function getMultiValueCustomSets($request) {
'url' => CRM_Utils_System::url('civicrm/contact/view', 'reset=1&force=1&cid=$cid' . $urlSuffix),
);
}

// Store the result in a static variable cache
Civi::$statics[__CLASS__]['multiValueCustomSets'] = $data;
}
return $data[$request];

return Civi::$statics[__CLASS__]['multiValueCustomSets'][$request];
}

/**
Expand Down Expand Up @@ -495,12 +504,15 @@ public static function moveContactBelongings($mainId, $otherId, $tables = FALSE,

$mainId = (int) $mainId;
$otherId = (int) $otherId;
$multi_value_tables = array_keys(CRM_Dedupe_Merger::getMultiValueCustomSets('cidRefs'));

$sqls = array();
foreach ($affected as $table) {
// skipping non selected custom table's value migration
if ($customTableToCopyFrom !== NULL && in_array($table, $customTables) && !in_array($table, $customTableToCopyFrom)) {
continue;
// skipping non selected single-value custom table's value migration
if (!in_array($table, $multi_value_tables)) {
if ($customTableToCopyFrom !== NULL && in_array($table, $customTables) && !in_array($table, $customTableToCopyFrom)) {
continue;
}
}

// Call custom processing function for objects that require it
Expand Down
29 changes: 29 additions & 0 deletions tests/phpunit/CRM/Dedupe/MergerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,14 @@ public function testMigrationOfUnselectedCustomDataOnEmptyCustomRecord() {
$createGroup = $this->setupCustomGroupForIndividual();
$customField1 = $this->setupCustomField('TestField', $createGroup);

// Create multi-value custom field
$multiGroup = $this->CustomGroupMultipleCreateByParams();
$multiField = $this->customFieldCreate(array(
'custom_group_id' => $multiGroup['id'],
'label' => 'field_1' . $multiGroup['id'],
'in_selector' => 1,
));

// Contacts setup
$this->setupMatchData();
$originalContactID = $this->contacts[0]['id'];
Expand All @@ -558,17 +566,24 @@ public function testMigrationOfUnselectedCustomDataOnEmptyCustomRecord() {
$this->callAPISuccess('Contact', 'create', array(
'id' => $duplicateContactID,
"custom_{$customField1['id']}" => 'abc',
"custom_{$multiField['id']}" => 'def',
));
$this->assertCustomFieldValue($duplicateContactID, 'abc', "custom_{$customField1['id']}");
$this->assertCustomFieldValue($duplicateContactID, 'def', "custom_{$multiField['id']}");

// Merge, and ensure that no value was migrated
$this->mergeContacts($originalContactID, $duplicateContactID, array(
"move_custom_{$customField1['id']}" => NULL,
"move_rel_table_custom_{$multiGroup['id']}" => NULL,
));
$this->assertCustomFieldValue($originalContactID, '', "custom_{$customField1['id']}");
$this->assertCustomFieldValue($originalContactID, '', "custom_{$multiField['id']}");

// cleanup created custom set
$this->callAPISuccess('CustomField', 'delete', array('id' => $customField1['id']));
$this->callAPISuccess('CustomGroup', 'delete', array('id' => $createGroup['id']));
$this->callAPISuccess('CustomField', 'delete', array('id' => $multiField['id']));
$this->callAPISuccess('CustomGroup', 'delete', array('id' => $multiGroup['id']));
}

/**
Expand All @@ -583,6 +598,14 @@ public function testMigrationOfSomeCustomDataOnEmptyCustomRecord() {
$customField1 = $this->setupCustomField('Test1', $createGroup);
$customField2 = $this->setupCustomField('Test2', $createGroup);

// Create multi-value custom field
$multiGroup = $this->CustomGroupMultipleCreateByParams();
$multiField = $this->customFieldCreate(array(
'custom_group_id' => $multiGroup['id'],
'label' => 'field_1' . $multiGroup['id'],
'in_selector' => 1,
));

// Contacts setup
$this->setupMatchData();
$originalContactID = $this->contacts[0]['id'];
Expand All @@ -593,22 +616,28 @@ public function testMigrationOfSomeCustomDataOnEmptyCustomRecord() {
'id' => $duplicateContactID,
"custom_{$customField1['id']}" => 'abc',
"custom_{$customField2['id']}" => 'def',
"custom_{$multiField['id']}" => 'ghi',
));
$this->assertCustomFieldValue($duplicateContactID, 'abc', "custom_{$customField1['id']}");
$this->assertCustomFieldValue($duplicateContactID, 'def', "custom_{$customField2['id']}");
$this->assertCustomFieldValue($duplicateContactID, 'ghi', "custom_{$multiField['id']}");

// Perform merge
$this->mergeContacts($originalContactID, $duplicateContactID, array(
"move_custom_{$customField1['id']}" => NULL,
"move_custom_{$customField2['id']}" => 'def',
"move_rel_table_custom_{$multiGroup['id']}" => '1',
));
$this->assertCustomFieldValue($originalContactID, '', "custom_{$customField1['id']}");
$this->assertCustomFieldValue($originalContactID, 'def', "custom_{$customField2['id']}");
$this->assertCustomFieldValue($originalContactID, 'ghi', "custom_{$multiField['id']}");

// cleanup created custom set
$this->callAPISuccess('CustomField', 'delete', array('id' => $customField1['id']));
$this->callAPISuccess('CustomField', 'delete', array('id' => $customField2['id']));
$this->callAPISuccess('CustomGroup', 'delete', array('id' => $createGroup['id']));
$this->callAPISuccess('CustomField', 'delete', array('id' => $multiField['id']));
$this->callAPISuccess('CustomGroup', 'delete', array('id' => $multiGroup['id']));
}

/**
Expand Down

0 comments on commit 7fba879

Please sign in to comment.