From 3b9d4007540d19d58c1fed209e88a01fd5084026 Mon Sep 17 00:00:00 2001 From: Jamie McClelland Date: Tue, 11 Jul 2023 13:18:24 -0400 Subject: [PATCH] hide view only custom fields on merge screen And, ensure they are not merged. View only fields with values on the duplicate that is being discarded will be discarded. --- CRM/Dedupe/Merger.php | 28 +++++++++++-------- tests/phpunit/CRM/Dedupe/MergerTest.php | 36 +++++++++++++++++++++++++ tests/phpunit/api/v3/JobTest.php | 5 ++-- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/CRM/Dedupe/Merger.php b/CRM/Dedupe/Merger.php index f1e54bbaa1..b1e5e44dcc 100644 --- a/CRM/Dedupe/Merger.php +++ b/CRM/Dedupe/Merger.php @@ -1642,12 +1642,16 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m $checkPermissions ? CRM_Core_Permission::EDIT : FALSE ); + $ignoredCustomFields = self::ignoredFields('custom'); foreach ($otherTree as $gid => $group) { if (!isset($group['fields'])) { continue; } foreach ($group['fields'] as $fid => $field) { + if (in_array($group['name'] . '.' . $field['name'], $ignoredCustomFields)) { + continue; + } $mainContactValue = $mainTree[$gid]['fields'][$fid]['customValue'] ?? NULL; $otherContactValue = $otherTree[$gid]['fields'][$fid]['customValue'] ?? NULL; if (in_array($fid, $compareFields['custom'])) { @@ -2031,8 +2035,6 @@ ORDER BY civicrm_custom_group.weight, $submitted = []; } - // Move view only custom fields CRM-5362 - $viewOnlyCustomFields = []; foreach ($submitted as $key => $value) { if (strpos($key, 'custom_') === 0) { $fieldID = (int) substr($key, 7); @@ -2041,20 +2043,13 @@ ORDER BY civicrm_custom_group.weight, $htmlType = (string) $fieldMetadata['html_type']; $isSerialized = CRM_Core_BAO_CustomField::isSerialized($fieldMetadata); $isView = (bool) $fieldMetadata['is_view']; - if ($isView) { - $viewOnlyCustomFields[$key] = $value; + if (!$isView) { + $submitted = self::processCustomFields($mainId, $key, $submitted, $value, $fieldID, $isView, $htmlType, $isSerialized); } - $submitted = self::processCustomFields($mainId, $key, $submitted, $value, $fieldID, $isView, $htmlType, $isSerialized); } } } - // special case to set values for view only, CRM-5362 - if (!empty($viewOnlyCustomFields)) { - $viewOnlyCustomFields['entityID'] = $mainId; - CRM_Core_BAO_CustomValueTable::setValues($viewOnlyCustomFields); - } - // dev/core#996 Ensure that the earliest created date is stored against the kept contact id $mainCreatedDate = civicrm_api3('Contact', 'getsingle', [ 'id' => $mainId, @@ -2761,7 +2756,18 @@ ORDER BY civicrm_custom_group.weight, 'postal_greeting_display', 'addressee_display', ], + 'custom' => [], ]; + + $readOnlyCustomFields = \Civi\Api4\CustomField::get(FALSE) + ->addSelect('custom_group_id.name', 'name') + ->addWhere('is_view', '=', TRUE) + ->addWhere('custom_group_id.extends', 'IN', ['Individual', 'Household', 'Organization', 'Contact']) + ->execute(); + foreach ($readOnlyCustomFields as $field) { + $keysToIgnore['custom'][] = $field['custom_group_id.name'] . '.' . $field['name']; + } + return $keysToIgnore[$type]; } diff --git a/tests/phpunit/CRM/Dedupe/MergerTest.php b/tests/phpunit/CRM/Dedupe/MergerTest.php index e4466f3e9c..0ef8d6cd6c 100644 --- a/tests/phpunit/CRM/Dedupe/MergerTest.php +++ b/tests/phpunit/CRM/Dedupe/MergerTest.php @@ -1046,6 +1046,42 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase { $this->callAPISuccess('CustomGroup', 'delete', ['id' => $activityGroup['id']]); } + /** + * Verifies that when two contacts with view only custom fields are merged, + * the view only field of the record being deleted is not merged, it is + * simply deleted (it should also not be visible on the page). + */ + public function testMigrationOfViewOnlyCustomData() { + // Create Custom Fields + $createGroup = $this->setupCustomGroupForIndividual(); + $customField = $this->setupCustomField('TestField', $createGroup); + + // Contacts setup + $this->setupMatchData(); + $originalContactID = $this->contacts[0]['id']; + $duplicateContactID = $this->contacts[1]['id']; + + // Update the text custom fields for duplicate contact + $this->callAPISuccess('Contact', 'create', [ + 'id' => $duplicateContactID, + "custom_{$customField['id']}" => 'abc', + ]); + $this->assertCustomFieldValue($duplicateContactID, 'abc', "custom_{$customField['id']}"); + + // Change custom field to view only. + $this->callAPISuccess('CustomField', 'update', ['id' => $customField['id'], 'is_view' => TRUE]); + + // Merge, and ensure that no value was migrated + $this->mergeContacts($originalContactID, $duplicateContactID, [ + "move_custom_{$customField['id']}" => NULL, + ]); + $this->assertCustomFieldValue($originalContactID, '', "custom_{$customField['id']}"); + + // cleanup created custom set + $this->callAPISuccess('CustomField', 'delete', ['id' => $customField['id']]); + $this->callAPISuccess('CustomGroup', 'delete', ['id' => $createGroup['id']]); + } + /** * Calls merge method on given contacts, with values given in $params array. * diff --git a/tests/phpunit/api/v3/JobTest.php b/tests/phpunit/api/v3/JobTest.php index dd55035dee..d1b1dee9ed 100644 --- a/tests/phpunit/api/v3/JobTest.php +++ b/tests/phpunit/api/v3/JobTest.php @@ -1070,7 +1070,8 @@ class api_v3_JobTest extends CiviUnitTestCase { } /** - * Test the batch merge copes with view only custom data field. + * Test the batch merge copes with view only custom data field. View Only custom fields + * should never be merged. */ public function testBatchMergeCustomDataViewOnlyField(): void { CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'edit my contact']; @@ -1085,7 +1086,7 @@ class api_v3_JobTest extends CiviUnitTestCase { $this->assertCount(1, $result['values']['merged']); $mouseParams['return'] = 'custom_' . $customField['id']; $mouse = $this->callAPISuccess('Contact', 'getsingle', $mouseParams); - $this->assertEquals('blah', $mouse['custom_' . $customField['id']]); + $this->assertEquals('', $mouse['custom_' . $customField['id']]); } /** -- 2.25.1