From 50bdbb5ba90a1f81ceaa61bcd8f31d0ecc925fc2 Mon Sep 17 00:00:00 2001 From: Seamus Lee Date: Wed, 23 Sep 2020 08:50:03 +1000 Subject: [PATCH] dev/core#1838 Ensure that no fatal error is triggered if you try to access a merged contact and the contact that it was merged into has been permanently deleted MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Move exception capturing into the page layer and extend unit test to cover page function Update status message as per Mikeý's comment --- CRM/Contact/Page/View.php | 8 +++++++- tests/phpunit/api/v3/ContactTest.php | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/CRM/Contact/Page/View.php b/CRM/Contact/Page/View.php index faeb0cb8cf..ce076fe83c 100644 --- a/CRM/Contact/Page/View.php +++ b/CRM/Contact/Page/View.php @@ -311,7 +311,13 @@ class CRM_Contact_Page_View extends CRM_Core_Page { } if ($isDeleted) { $title = "{$title}"; - $mergedTo = civicrm_api3('Contact', 'getmergedto', ['contact_id' => $contactId, 'api.Contact.get' => ['return' => 'display_name']]); + try { + $mergedTo = civicrm_api3('Contact', 'getmergedto', ['contact_id' => $contactId, 'api.Contact.get' => ['return' => 'display_name']]); + } + catch (CiviCRM_API3_Exception $e) { + CRM_Core_Session::singleton()->setStatus(ts('This contact was deleted during a merge operation. The contact it was merged into cannot be found and may have been deleted.')); + $mergedTo = ['count' => 0]; + } if ($mergedTo['count']) { $mergedToContactID = $mergedTo['id']; $mergedToDisplayName = $mergedTo['values'][$mergedToContactID]['api.Contact.get']['values'][0]['display_name']; diff --git a/tests/phpunit/api/v3/ContactTest.php b/tests/phpunit/api/v3/ContactTest.php index 4d99ff2562..df25b45c00 100644 --- a/tests/phpunit/api/v3/ContactTest.php +++ b/tests/phpunit/api/v3/ContactTest.php @@ -4166,6 +4166,30 @@ class api_v3_ContactTest extends CiviUnitTestCase { $this->assertEquals($mergedContactIds, array_keys($result)); } + /** + * Test retrieving merged contacts. + * + * The goal here is to start with a contact deleted by merged and find out the contact that is the current version of them. + * + * @throws \CRM_Core_Exception + */ + public function testMergedGetWithPermanentlyDeletedContact() { + $this->contactIDs[] = $this->individualCreate(); + $this->contactIDs[] = $this->individualCreate(); + $this->contactIDs[] = $this->individualCreate(); + $this->contactIDs[] = $this->individualCreate(); + + // First do an 'unnatural merge' - they 'like to merge into the lowest but this will mean that contact 0 merged to contact [3]. + // When the batch merge runs.... the new lowest contact is contact[1]. All contacts will merge into that contact, + // including contact[3], resulting in only 3 existing at the end. For each contact the correct answer to 'who did I eventually + // wind up being should be [1] + $this->callAPISuccess('Contact', 'merge', ['to_remove_id' => $this->contactIDs[0], 'to_keep_id' => $this->contactIDs[3]]); + $this->callAPISuccess('Contact', 'delete', ['id' => $this->contactIDs[3], 'skip_undelete' => TRUE]); + $this->callAPIFailure('Contact', 'getmergedto', ['sequential' => 1, 'contact_id' => $this->contactIDs[0]]); + $title = CRM_Contact_Page_View::setTitle($this->contactIDs[0], TRUE); + $this->assertContains('civicrm/profile/view&reset=1&gid=7&id=3&snippet=4', $title); + } + /** * Test merging 2 contacts with delete to trash off. * -- 2.25.1