diff --git a/CRM/Dedupe/Merger.php b/CRM/Dedupe/Merger.php index 12c3903d8c28..e8eeb347e740 100644 --- a/CRM/Dedupe/Merger.php +++ b/CRM/Dedupe/Merger.php @@ -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'), @@ -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']; } /** @@ -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(), @@ -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]; } /** @@ -467,12 +476,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 diff --git a/tests/phpunit/CRM/Dedupe/MergerTest.php b/tests/phpunit/CRM/Dedupe/MergerTest.php index 4db2dbd9e59c..022875fbe819 100644 --- a/tests/phpunit/CRM/Dedupe/MergerTest.php +++ b/tests/phpunit/CRM/Dedupe/MergerTest.php @@ -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']; @@ -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'])); } /** @@ -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']; @@ -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'])); } /**