X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FDedupe%2FMerger.php;h=b943027d8f0966d98c3c0d6fcd216030f418a604;hb=ed3f7d0115f78029e42aedf10d5c77653223d0e6;hp=9e501f35f60c2a07f11f11f03d049543429ea0f0;hpb=4c7e5001c8e518131fe7b45f0e05259079eb16a4;p=civicrm-core.git diff --git a/CRM/Dedupe/Merger.php b/CRM/Dedupe/Merger.php index 9e501f35f6..b943027d8f 100644 --- a/CRM/Dedupe/Merger.php +++ b/CRM/Dedupe/Merger.php @@ -691,11 +691,21 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m * If not set explicitly this is calculated but it is preferred that it be set * per comments on isSelected above. * + * @param int $searchLimit + * Limit on number of contacts to search for duplicates for. + * This means that if the limit is 1000 then only duplicates for the first 1000 contacts + * matching criteria will be found and batchMerged (the number of merges could be less than or greater than 100) + * * @return array|bool + * + * @throws \CRM_Core_Exception + * @throws \CiviCRM_API3_Exception */ - public static function batchMerge($rgid, $gid = NULL, $mode = 'safe', $batchLimit = 1, $isSelected = 2, $criteria = [], $checkPermissions = TRUE, $reloadCacheIfEmpty = NULL) { + public static function batchMerge($rgid, $gid = NULL, $mode = 'safe', $batchLimit = 1, $isSelected = 2, $criteria = [], $checkPermissions = TRUE, $reloadCacheIfEmpty = NULL, $searchLimit = 0) { $redirectForPerformance = ($batchLimit > 1) ? TRUE : FALSE; - + if ($mode === 'aggressive' && $checkPermissions && !CRM_Core_Permission::check('force merge duplicate contacts')) { + throw new CRM_Core_Exception(ts('Insufficient permissions for aggressive mode batch merge')); + } if (!isset($reloadCacheIfEmpty)) { $reloadCacheIfEmpty = (!$redirectForPerformance && $isSelected == 2); } @@ -703,10 +713,10 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m // explicitly set to NULL if not 1 or 0 as part of grandfathering out the mystical '2' value. $isSelected = NULL; } - $dupePairs = self::getDuplicatePairs($rgid, $gid, $reloadCacheIfEmpty, $batchLimit, $isSelected, ($mode == 'aggressive'), $criteria, $checkPermissions); + $dupePairs = self::getDuplicatePairs($rgid, $gid, $reloadCacheIfEmpty, $batchLimit, $isSelected, ($mode == 'aggressive'), $criteria, $checkPermissions, $searchLimit); $cacheParams = [ - 'cache_key_string' => self::getMergeCacheKeyString($rgid, $gid, $criteria, $checkPermissions), + 'cache_key_string' => self::getMergeCacheKeyString($rgid, $gid, $criteria, $checkPermissions, $searchLimit), // @todo stop passing these parameters in & instead calculate them in the merge function based // on the 'real' params like $isRespectExclusions $batchLimit and $isSelected. 'join' => self::getJoinOnDedupeTable(), @@ -1181,7 +1191,11 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m $locations[$moniker][$blockName][$cnt] = $value; // Fix address display if ($blockName == 'address') { + // For performance avoid geocoding while merging https://issues.civicrm.org/jira/browse/CRM-21786 + // we can expect existing geocode values to be retained. + $value['skip_geocode'] = TRUE; CRM_Core_BAO_Address::fixAddress($value); + unset($value['skip_geocode']); $locations[$moniker][$blockName][$cnt]['display'] = CRM_Utils_Address::format($value); } // Fix email display @@ -1833,20 +1847,23 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m * @param int $searchLimit * Limit to searching for matches against this many contacts. * + * @param int $isForceNewSearch + * Should a new search be forced, bypassing any cache retrieval. + * * @return array * Array of matches meeting the criteria. * * @throws \CRM_Core_Exception * @throws \CiviCRM_API3_Exception */ - public static function getDuplicatePairs($rule_group_id, $group_id, $reloadCacheIfEmpty, $batchLimit, $isSelected, $includeConflicts = TRUE, $criteria = [], $checkPermissions = TRUE, $searchLimit = 0) { - $dupePairs = self::getCachedDuplicateMatches($rule_group_id, $group_id, $batchLimit, $isSelected, $includeConflicts, $criteria, $checkPermissions); + public static function getDuplicatePairs($rule_group_id, $group_id, $reloadCacheIfEmpty, $batchLimit, $isSelected, $includeConflicts = TRUE, $criteria = [], $checkPermissions = TRUE, $searchLimit = 0, $isForceNewSearch = 0) { + $dupePairs = $isForceNewSearch ? [] : self::getCachedDuplicateMatches($rule_group_id, $group_id, $batchLimit, $isSelected, $includeConflicts, $criteria, $checkPermissions, $searchLimit); if (empty($dupePairs) && $reloadCacheIfEmpty) { // If we haven't found any dupes, probably cache is empty. // Try filling cache and give another try. We don't need to specify include conflicts here are there will not be any // until we have done some processing. CRM_Core_BAO_PrevNextCache::refillCache($rule_group_id, $group_id, $criteria, $checkPermissions, $searchLimit); - return self::getCachedDuplicateMatches($rule_group_id, $group_id, $batchLimit, $isSelected, FALSE, $criteria, $checkPermissions); + return self::getCachedDuplicateMatches($rule_group_id, $group_id, $batchLimit, $isSelected, FALSE, $criteria, $checkPermissions, $searchLimit); } return $dupePairs; } @@ -1859,17 +1876,21 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m * @param array $criteria * Additional criteria to narrow down the merge group. * Currently we are only supporting the key 'contact' within it. - * * @param bool $checkPermissions * Respect the users permissions. + * @param int $searchLimit + * Number of contacts to seek dupes for (we need this because if + * we change it the results won't be refreshed otherwise. Changing the limit + * from 100 to 1000 SHOULD result in a new dedupe search). * * @return string */ - public static function getMergeCacheKeyString($rule_group_id, $group_id, $criteria = [], $checkPermissions = TRUE) { + public static function getMergeCacheKeyString($rule_group_id, $group_id, $criteria, $checkPermissions, $searchLimit) { $contactType = CRM_Dedupe_BAO_RuleGroup::getContactTypeForRuleGroup($rule_group_id); $cacheKeyString = "merge_{$contactType}"; $cacheKeyString .= $rule_group_id ? "_{$rule_group_id}" : '_0'; $cacheKeyString .= $group_id ? "_{$group_id}" : '_0'; + $cacheKeyString .= '_' . (int) $searchLimit; $cacheKeyString .= !empty($criteria) ? md5(serialize($criteria)) : '_0'; if ($checkPermissions) { $contactID = CRM_Core_Session::getLoggedInContactID(); @@ -2487,12 +2508,13 @@ INNER JOIN civicrm_membership membership2 ON membership1.membership_type_id = m * @param bool $includeConflicts * @param array $criteria * @param int $checkPermissions + * @param int $searchLimit * * @return array */ - protected static function getCachedDuplicateMatches($rule_group_id, $group_id, $batchLimit, $isSelected, $includeConflicts, $criteria, $checkPermissions) { + protected static function getCachedDuplicateMatches($rule_group_id, $group_id, $batchLimit, $isSelected, $includeConflicts, $criteria, $checkPermissions, $searchLimit = 0) { return CRM_Core_BAO_PrevNextCache::retrieve( - self::getMergeCacheKeyString($rule_group_id, $group_id, $criteria, $checkPermissions), + self::getMergeCacheKeyString($rule_group_id, $group_id, $criteria, $checkPermissions, $searchLimit), self::getJoinOnDedupeTable(), self::getWhereString($isSelected), 0, $batchLimit,