-
-
Notifications
You must be signed in to change notification settings - Fork 824
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
===== Overview ==== This adds a new extension for existing dedupe finder behaviour, allowing us to support the hook that is jammed in the middle of the dedupe finder code going forwards without being blocked by it (I have an existing PR that cuts many hours off the dedupe query but it is bending over backwards to work alongside the legacy attempts to allow integration). The new extension is enabled on install and on upgrade and there is no behaviour change unless a site admin disables it. If they choose to do so then 1) the legacy hook & legacy reserved query wrangling will no longer be called 2) dedupe queries will speed up once the blocked code is also merged #30591
- Loading branch information
1 parent
726d32a
commit b987e2a
Showing
17 changed files
with
1,096 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,13 @@ | |
* The CiviCRM duplicate discovery engine is based on an | ||
* algorithm designed by David Strauss <[email protected]>. | ||
*/ | ||
class CRM_Dedupe_BAO_DedupeRuleGroup extends CRM_Dedupe_DAO_DedupeRuleGroup { | ||
class CRM_Dedupe_BAO_DedupeRuleGroup extends CRM_Dedupe_DAO_DedupeRuleGroup implements \Symfony\Component\EventDispatcher\EventSubscriberInterface { | ||
|
||
public static function getSubscribedEvents(): array { | ||
return [ | ||
'hook_civicrm_findExistingDuplicates' => ['hook_civicrm_findExistingDuplicates', -20], | ||
]; | ||
} | ||
|
||
/** | ||
* @var array | ||
|
@@ -131,6 +137,36 @@ public function tableDropQuery() { | |
return 'DROP TEMPORARY TABLE IF EXISTS dedupe'; | ||
} | ||
|
||
/** | ||
* Find existing duplicates in the database for the given rule and limitations. | ||
* | ||
* @return void | ||
*/ | ||
public static function hook_civicrm_findExistingDuplicates(\Civi\Core\Event\GenericHookEvent $event) { | ||
$ruleGroupIDs = $event->ruleGroupIDs; | ||
$ruleGroup = new \CRM_Dedupe_BAO_DedupeRuleGroup(); | ||
$ruleGroup->id = reset($ruleGroupIDs); | ||
$contactIDs = []; | ||
$whereClauses = $event->whereClauses; | ||
if (!empty($whereClauses)) { | ||
foreach ($whereClauses as $whereClause) { | ||
if ($whereClause[0] === 'id' && $whereClause[1] === 'IN') { | ||
$contactIDs = $whereClause[2]; | ||
} | ||
} | ||
} | ||
if (!$ruleGroup->fillTable($ruleGroup->id, $contactIDs, [], FALSE)) { | ||
return; | ||
} | ||
$dao = \CRM_Core_DAO::executeQuery($ruleGroup->thresholdQuery($event->checkPermissions)); | ||
$duplicates = []; | ||
while ($dao->fetch()) { | ||
$duplicates[] = ['entity_id_1' => $dao->id1, 'entity_id_2' => $dao->id2, 'weight' => $dao->weight]; | ||
} | ||
$event->duplicates = $duplicates; | ||
\CRM_Core_DAO::executeQuery($ruleGroup->tableDropQuery()); | ||
} | ||
|
||
/** | ||
* Fill the dedupe finder table. | ||
* | ||
|
@@ -139,32 +175,41 @@ public function tableDropQuery() { | |
* @param int $id | ||
* @param array $contactIDs | ||
* @param array $params | ||
* @param bool $legacyMode | ||
* Legacy mode is called to give backward hook compatibility, in the legacydedupefinder | ||
* extension. It is intended to be transitional, with the non-legacy mode being | ||
* separated out and optimized once it no longer has to comply with the legacy | ||
* hook and reserved query methodology. | ||
* | ||
* @return bool | ||
* @throws \Civi\Core\Exception\DBQueryException | ||
*/ | ||
public function fillTable(int $id, array $contactIDs, array $params): bool { | ||
$this->contactIds = $contactIDs; | ||
$this->params = $params; | ||
public function fillTable(int $id, array $contactIDs, array $params, $legacyMode = TRUE): bool { | ||
if ($legacyMode) { | ||
$this->contactIds = $contactIDs; | ||
$this->params = $params; | ||
} | ||
$this->id = $id; | ||
// make sure we've got a fetched dbrecord, not sure if this is enforced | ||
$this->find(TRUE); | ||
$optimizer = new CRM_Dedupe_FinderQueryOptimizer($this->id, $contactIDs, $params); | ||
// Reserved Rule Groups can optionally get special treatment by | ||
// implementing an optimization class and returning a query array. | ||
if ($optimizer->isUseReservedQuery()) { | ||
if ($legacyMode && $optimizer->isUseReservedQuery()) { | ||
$tableQueries = $optimizer->getReservedQuery(); | ||
} | ||
else { | ||
$tableQueries = $optimizer->getRuleQueries(); | ||
} | ||
// if there are no rules in this rule group | ||
// add an empty query fulfilling the pattern | ||
if (!$tableQueries) { | ||
// Just for the hook.... (which is deprecated). | ||
$this->noRules = TRUE; | ||
if ($legacyMode) { | ||
if (!$tableQueries) { | ||
// Just for the hook.... (which is deprecated). | ||
$this->noRules = TRUE; | ||
} | ||
CRM_Utils_Hook::dupeQuery($this, 'table', $tableQueries); | ||
} | ||
CRM_Utils_Hook::dupeQuery($this, 'table', $tableQueries); | ||
if (empty($tableQueries)) { | ||
return FALSE; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<?php | ||
|
||
namespace Civi\LegacyFinder; | ||
|
||
use Civi\Core\Event\GenericHookEvent; | ||
|
||
class Finder { | ||
|
||
/** | ||
* This function exists to provide legacy hook support for finding duplicates. | ||
* | ||
* @return void | ||
*/ | ||
public static function findExistingDuplicates(GenericHookEvent $event) { | ||
$event->stopPropagation(); | ||
$ruleGroupIDs = $event->ruleGroupIDs; | ||
$ruleGroup = new \CRM_Dedupe_BAO_DedupeRuleGroup(); | ||
$ruleGroup->id = reset($ruleGroupIDs); | ||
$contactIDs = []; | ||
$whereClauses = $event->whereClauses; | ||
if (!empty($whereClauses)) { | ||
foreach ($whereClauses as $whereClause) { | ||
if ($whereClause[0] === 'id' && $whereClause[1] === 'IN') { | ||
$contactIDs = $whereClause[2]; | ||
} | ||
} | ||
} | ||
if (!$ruleGroup->fillTable($ruleGroup->id, $contactIDs, [])) { | ||
return; | ||
} | ||
$dao = \CRM_Core_DAO::executeQuery($ruleGroup->thresholdQuery($event->checkPermissions)); | ||
$duplicates = []; | ||
while ($dao->fetch()) { | ||
$duplicates[] = ['entity_id_1' => $dao->id1, 'entity_id_2' => $dao->id2, 'weight' => $dao->weight]; | ||
} | ||
$event->duplicates = $duplicates; | ||
\CRM_Core_DAO::executeQuery($ruleGroup->tableDropQuery()); | ||
} | ||
|
||
} |
Oops, something went wrong.