diff --git a/CRM/Dedupe/Merger.php b/CRM/Dedupe/Merger.php index 9f161af164195a45cd59c646e6a252c18115d756..39f649765f55564baac92d19df3c41ae712f77f3 100644 --- a/CRM/Dedupe/Merger.php +++ b/CRM/Dedupe/Merger.php @@ -222,6 +222,11 @@ class CRM_Dedupe_Merger { } $contactReferences = $coreReferences = CRM_Core_DAO::getReferencesToContactTable(); + foreach (['civicrm_group_contact_cache', 'civicrm_acl_cache', 'civicrm_acl_contact_cache'] as $tableName) { + // Don't merge cache tables. These should be otherwise cleared at some point in the dedupe + // but they are prone to locking to let's not touch during the dedupe. + unset($contactReferences[$tableName], $coreReferences[$tableName]); + } CRM_Utils_Hook::merge('cidRefs', $contactReferences); if ($contactReferences !== $coreReferences) { @@ -527,6 +532,12 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m continue; } + if ($table === 'civicrm_activity_contact') { + $sqls[] = "UPDATE IGNORE civicrm_activity_contact SET contact_id = $mainId WHERE contact_id = $otherId"; + $sqls[] = "DELETE FROM civicrm_activity_contact WHERE contact_id = $otherId"; + continue; + } + // use UPDATE IGNORE + DELETE query pair to skip on situations when // there's a UNIQUE restriction on ($field, some_other_field) pair if (isset($cidRefs[$table])) { diff --git a/CRM/Report/Form.php b/CRM/Report/Form.php index f09de2def6efe856dd694eee5e371e78d75d5690..c4eca231b16939235f4323ac08bec6c92371ea6d 100644 --- a/CRM/Report/Form.php +++ b/CRM/Report/Form.php @@ -2185,6 +2185,10 @@ class CRM_Report_Form extends CRM_Core_Form { $sqlOP = $this->getSQLOperator($relative); return "( {$fieldName} {$sqlOP} )"; } + if (strlen($to) === 10) { + // If we just have the date we assume the end of that day. + $to .= ' 23:59:59'; + } if ($relative) { list($from, $to) = $this->getFromTo($relative, $from, $to, $fromTime, $toTime); diff --git a/tests/phpunit/CRM/Dedupe/MergerTest.php b/tests/phpunit/CRM/Dedupe/MergerTest.php index e796173fa4b7641c8366630b2e4cd06349e889e2..8f4bf06043473a7d0e2dd1f3cda7089ec9ef60d0 100644 --- a/tests/phpunit/CRM/Dedupe/MergerTest.php +++ b/tests/phpunit/CRM/Dedupe/MergerTest.php @@ -285,8 +285,10 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase { */ public function testGetCidRefs() { $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, 'Contacts'); - $this->assertEquals($this->getStaticCIDRefs(), CRM_Dedupe_Merger::cidRefs()); - $this->assertEquals($this->getCalculatedCIDRefs(), CRM_Dedupe_Merger::cidRefs()); + // These are deliberately unset. + $unsetRefs = array_fill_keys(['civicrm_group_contact_cache', 'civicrm_acl_cache', 'civicrm_acl_contact_cache'], 1); + $this->assertEquals(array_diff_key($this->getStaticCIDRefs(), $unsetRefs), CRM_Dedupe_Merger::cidRefs()); + $this->assertEquals(array_diff_key($this->getCalculatedCIDRefs(), $unsetRefs), CRM_Dedupe_Merger::cidRefs()); } /** diff --git a/tests/phpunit/api/v3/JobTest.php b/tests/phpunit/api/v3/JobTest.php index 444714204ab93936985eec1c5b06a698b38cefa6..9eb857ff85d9706c41e547577c39ed00b288d110 100644 --- a/tests/phpunit/api/v3/JobTest.php +++ b/tests/phpunit/api/v3/JobTest.php @@ -573,11 +573,37 @@ class api_v3_JobTest extends CiviUnitTestCase { foreach ($groupResult['values'] as $groupValues) { $this->assertEquals($contactID, $groupValues['contact_id']); $this->assertEquals('Added', $groupValues['status']); - $this->assertTrue(in_array($groupValues['group_id'], $expectedGroups)); + $this->assertContains($groupValues['group_id'], $expectedGroups); } } + /** + * Test that we handle cache entries without clashes. + */ + public function testMergeCaches() { + $contactID = $this->individualCreate(); + $contact2ID = $this->individualCreate(); + $groupID = $this->groupCreate(); + $this->callAPISuccess('GroupContact', 'create', ['group_id' => $groupID, 'contact_id' => $contactID]); + $this->callAPISuccess('GroupContact', 'create', ['group_id' => $groupID, 'contact_id' => $contact2ID]); + CRM_Core_DAO::executeQuery("INSERT INTO civicrm_group_contact_cache(group_id, contact_id) VALUES + ($groupID, $contactID), + ($groupID, $contact2ID) + "); + $this->callAPISuccess('Job', 'process_batch_merge', ['mode' => 'safe']); + } + + /** + * Test that we handle cache entries without clashes. + */ + public function testMergeSharedActivity() { + $contactID = $this->individualCreate(); + $contact2ID = $this->individualCreate(); + $activityID = $this->activityCreate(['target_contact_id' => [$contactID, $contact2ID]]); + $this->callAPISuccess('Job', 'process_batch_merge', ['mode' => 'safe']); + } + /** * Test the decisions made for addresses when merging. *