Move function to delete merged contacts to the Merger class and include all instances...
authoreileen <emcnaughton@wikimedia.org>
Tue, 28 Jul 2020 00:21:05 +0000 (12:21 +1200)
committereileen <emcnaughton@wikimedia.org>
Tue, 28 Jul 2020 00:30:52 +0000 (12:30 +1200)
The PrevNextCache class is a bit of a mess. It has 2 roles
1) be a cache
2) provide functionality specific to the Merger class

I am working to move this second functionality to the merger class and also to remove the cacheKey
filter on it. The cacheKey pertains to a particular search set. However if 2 people are deduping different search
sets and one person merges a contact pair they should not remain available in the other person's result set.

(Likewise, and to follow, if 2 contacts have a conflict we should update all search sets with that information,
not just the one that was actively being deduped)

CRM/Core/BAO/PrevNextCache.php
CRM/Dedupe/Merger.php

index 4eae51e91a1333a47ab2ddc1d3374b192161763f..f84454ae72ed7e43fc66aa30bb71076bebebd709 100644 (file)
@@ -121,32 +121,6 @@ WHERE  cachekey     = %3 AND
     CRM_Core_DAO::executeQuery($sql, $params);
   }
 
-  /**
-   * Delete pair from the previous next cache table to remove it from further merge consideration.
-   *
-   * The pair may have been flipped, so make sure we delete using both orders
-   *
-   * @param int $id1
-   * @param int $id2
-   * @param string $cacheKey
-   */
-  public static function deletePair($id1, $id2, $cacheKey = NULL) {
-    $sql = "DELETE FROM civicrm_prevnext_cache WHERE  entity_table = 'civicrm_contact'";
-
-    $pair = "(entity_id1 = %2 AND entity_id2 = %3) OR (entity_id1 = %3 AND entity_id2 = %2)";
-    $sql .= " AND ( {$pair} )";
-    $params[2] = [$id1, 'Integer'];
-    $params[3] = [$id2, 'Integer'];
-
-    if (isset($cacheKey)) {
-      $sql .= " AND cachekey LIKE %4";
-      // used % to address any row with conflict-cacheKey e.g "merge Individual_8_0_conflicts"
-      $params[4] = ["{$cacheKey}%", 'String'];
-    }
-
-    CRM_Core_DAO::executeQuery($sql, $params);
-  }
-
   /**
    * Mark contacts as being in conflict.
    *
index 1a918695103c68e36e98001a8d0d4a0094335417..bcf68cca719e8bcc6268780011beb8f976e2b467 100644 (file)
@@ -1911,12 +1911,31 @@ INNER JOIN  civicrm_membership membership2 ON membership1.membership_type_id = m
       CRM_Core_BAO_PrevNextCache::markConflict($mainId, $otherId, $cacheKeyString, $conflicts, $mode);
     }
     else {
-      CRM_Core_BAO_PrevNextCache::deletePair($mainId, $otherId, $cacheKeyString);
+      self::deletePairFromPrevNextCache((int) $mainId, (int) $otherId);
     }
     self::releaseLocks($locks);
     return $resultStats;
   }
 
+  /**
+   * Delete merged pair from the previous next cache table as the are no longer a merge candidate.
+   *
+   * It's possible there may be more than one set of merge results cached, with different cache keys.
+   * Once we have merged a pair these should all go (even from a different merge search) as they
+   * can only be merged once.
+   *
+   * @param int $contactID1
+   * @param int $contactID2
+   */
+  protected static function deletePairFromPrevNextCache(int $contactID1, int $contactID2) {
+    CRM_Core_DAO::executeQuery("
+      DELETE FROM civicrm_prevnext_cache
+      WHERE  entity_table = 'civicrm_contact'
+        AND (entity_id1 = %1 AND entity_id2 = %2) OR (entity_id1 = %2 AND entity_id2 = %1)",
+      [1 => [$contactID1, 'Integer'], 2 => [$contactID2, 'Integer']]
+    );
+  }
+
   /**
    * Replace the pseudo QFKey with zero if it is present.
    *