jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/373155 )
Change subject: Add ability to find duplicates for selected contacts. ...................................................................... Add ability to find duplicates for selected contacts. Notes: - This is not in my mind a final implementation. I wish to merge to core as part of extracting the code to an extension & version iteration & hence some choices may not be permanent - In the extension context the addition of the task may be by hook rather than adding to the array. I could not see any reason for the weird CONST numbering scheme in core for the task list & ignored it. - I wanted to confirm whether it is necessary to extend the task class which seems unwieldly to me & so have done this just extending CRM_Core_Form. -It occurs to me there are 2 separate actions we are interested in 1) select a bunch of contacts & find all the matches for them (based on either default rule or selecting a rule). 2) dedupe the contacts selected against each other. The patch here adds an action to contact search results (Find duplicates for these contacts) that uses the default rule to find all matches for selected contacts. This is the simpler option of those listed. Implementing 2 will require some more work on the cacheKey mechanism since we are trying to by-pass the rules. Normally I would try to focus on what I can get into core first but in this case I'm looking for a user win & to explore the code more to plan the next step upstream, which will involve refactoring. Bug: T151270 Change-Id: I2da53510e879c6260be8cee4a455d4a0a2d54693 --- M CRM/Contact/Form/Merge.php A CRM/Contact/Form/Task/FindDuplicates.php M CRM/Contact/Page/AJAX.php M CRM/Contact/Page/DedupeFind.php M CRM/Contact/Page/DedupeMerge.php M CRM/Contact/Task.php M templates/CRM/Contact/Page/DedupeFind.tpl 7 files changed, 138 insertions(+), 17 deletions(-) Approvals: jenkins-bot: Verified Ejegg: Looks good to me, approved diff --git a/CRM/Contact/Form/Merge.php b/CRM/Contact/Form/Merge.php index 6381852..1be1904 100644 --- a/CRM/Contact/Form/Merge.php +++ b/CRM/Contact/Form/Merge.php @@ -45,6 +45,11 @@ var $_contactType = NULL; /** + * @var array + */ + public $criteria = array(); + + /** * Query limit to be retained in the urls. * * @var int @@ -74,7 +79,9 @@ $this->_gid = $gid = CRM_Utils_Request::retrieve('gid', 'Positive', $this, FALSE); $this->_mergeId = CRM_Utils_Request::retrieve('mergeId', 'Positive', $this, FALSE); $this->limit = CRM_Utils_Request::retrieve('limit', 'Positive', $this, FALSE); - $urlParams = "reset=1&rgid={$this->_rgid}&gid={$this->_gid}&limit=" . $this->limit; + $this->criteria = CRM_Utils_Request::retrieve('criteria', 'String', $this, FALSE, '{}'); + + $urlParams = "reset=1&rgid={$this->_rgid}&gid={$this->_gid}&limit=" . $this->limit . '&criteria=' . $this->criteria; $this->bounceIfInvalid($this->_cid, $this->_oid); @@ -83,7 +90,7 @@ 'return' => 'contact_type', )); - $browseUrl = CRM_Utils_System::url('civicrm/contact/dedupefind', $urlParams . '&action=browse'); + $browseUrl = CRM_Utils_System::url('civicrm/contact/dedupefind', $urlParams . '&action=browse', FALSE, NULL, FALSE); if (!$this->_rgid) { // Unset browse URL as we have come from the search screen. @@ -99,7 +106,7 @@ CRM_Core_Session::singleton()->pushUserContext($browseUrl); } - $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $gid); + $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $gid, json_decode($this->criteria, TRUE)); $join = CRM_Dedupe_Merger::getJoinOnDedupeTable(); $where = "de.id IS NULL"; @@ -126,7 +133,7 @@ } $flipUrl = CRM_Utils_System::url('civicrm/contact/merge', - "reset=1&action=update&cid={$this->_oid}&oid={$this->_cid}&rgid={$this->_rgid}&gid={$gid}" + "reset=1&action=update&cid={$this->_oid}&oid={$this->_cid}&rgid={$this->_rgid}&gid={$gid}&criteria={$this->criteria}" ); if (!$flip) { $flipUrl .= '&flip=1'; @@ -294,7 +301,7 @@ CRM_Core_Session::setStatus($message, ts('Contacts Merged'), 'success'); $url = CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$this->_cid}"); - $urlParams = "reset=1&gid={$this->_gid}&rgid={$this->_rgid}&limit={$this->limit}"; + $urlParams = "reset=1&rgid={$this->_rgid}&gid={$this->_gid}&limit=" . $this->limit . '&criteria=' . $this->criteria; if (!empty($formValues['_qf_Merge_submit'])) { $urlParams .= "&action=update"; @@ -308,7 +315,7 @@ } if ($this->next && $this->_mergeId) { - $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $this->_gid); + $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $this->_gid, json_decode($this->criteria, TRUE)); $join = CRM_Dedupe_Merger::getJoinOnDedupeTable(); $where = "de.id IS NULL"; @@ -321,7 +328,7 @@ ) { $urlParams .= "&cid={$pos['next']['id1']}&oid={$pos['next']['id2']}&mergeId={$pos['next']['mergeId']}&action=update"; - $url = CRM_Utils_System::url('civicrm/contact/merge', $urlParams); + $url = CRM_Utils_System::url('civicrm/contact/merge', $urlParams, FALSE, NULL, FALSE); } } diff --git a/CRM/Contact/Form/Task/FindDuplicates.php b/CRM/Contact/Form/Task/FindDuplicates.php new file mode 100644 index 0000000..cc7cfa6 --- /dev/null +++ b/CRM/Contact/Form/Task/FindDuplicates.php @@ -0,0 +1,89 @@ +<?php +/* + +--------------------------------------------------------------------+ + | CiviCRM version 4.7 | + +--------------------------------------------------------------------+ + | Copyright CiviCRM LLC (c) 2004-2017 | + +--------------------------------------------------------------------+ + | This file is a part of CiviCRM. | + | | + | CiviCRM is free software; you can copy, modify, and distribute it | + | under the terms of the GNU Affero General Public License | + | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | + | | + | CiviCRM is distributed in the hope that it will be useful, but | + | WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | + | See the GNU Affero General Public License for more details. | + | | + | You should have received a copy of the GNU Affero General Public | + | License and the CiviCRM Licensing Exception along | + | with this program; if not, contact CiviCRM LLC | + | at info[AT]civicrm[DOT]org. If you have questions about the | + | GNU Affero General Public License or the licensing of CiviCRM, | + | see the CiviCRM license FAQ at http://civicrm.org/licensing | + +--------------------------------------------------------------------+ + */ + +/** + * + * @package CRM + * @copyright CiviCRM LLC (c) 2004-2017 + */ + +/** + * This class provides the functionality to find potential matches. + */ +class CRM_Contact_Form_Task_FindDuplicates extends CRM_Core_Form { + + /** + * Name of temporary table holding contacts. + * + * @var string + */ + public $_componentTable; + + /** + * Selected contact ids. + * + * @var array + */ + public $_contactIds = array(); + + /** + * Build all the data structures needed to build the form. + */ + public function preProcess() { + CRM_Contact_Form_Task::preProcessCommon($this, TRUE); + // Some issues with how we are passing these need dealing with at some stage. + // ie. switch to dedupe table first & load. For now limit. + $limit = 100; + $contactIDs = CRM_Core_DAO::singleValueQuery('SELECT GROUP_CONCAT(contact_id) FROM (SELECT contact_id FROM ' . $this->_componentTable . " LIMIT {$limit}) as d"); + $contactType = CRM_Core_DAO::singleValueQuery( + "SELECT GROUP_CONCAT(DISTINCT contact_type) FROM civicrm_contact WHERE id IN ({$contactIDs}) " + ); + + if (CRM_Core_DAO::singleValueQuery("SELECT count(*) FROM {$this->_componentTable}") > $limit) { + CRM_Core_Session::setStatus(ts("Only the first $limit have been selected for deduping")); + } + try { + $rule_group_id = civicrm_api3('RuleGroup', 'getvalue', array( + 'contact_type' => $contactType, + 'used' => 'Unsupervised', + 'return' => 'id', + 'options' => array('limit' => 1), + )); + } + catch (CiviCRM_API3_Exception $e) { + CRM_Core_Error::statusBounce(ts('It was not possible to identify a default rule that was applicable to all selected contacts. You must choose only one contact type. You chose %1', array($contactType))); + } + + CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/dedupefind', array( + 'reset' => 1, + 'action' => 'update', + 'rgid' => $rule_group_id, + 'criteria' => json_encode(array('contact' => array('id' => array('IN' => explode(',', $contactIDs))))), + 'limit' => count($contactIDs), + ))); + } +} \ No newline at end of file diff --git a/CRM/Contact/Page/AJAX.php b/CRM/Contact/Page/AJAX.php index cfdff39..6d861b9 100644 --- a/CRM/Contact/Page/AJAX.php +++ b/CRM/Contact/Page/AJAX.php @@ -649,13 +649,16 @@ $gid = CRM_Utils_Request::retrieve('gid', 'Positive'); $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive'); + $null = NULL; + $criteria = CRM_Utils_Request::retrieve('criteria', 'String', $null, FALSE, '{}'); $selected = isset($_REQUEST['selected']) ? CRM_Utils_Type::escape($_REQUEST['selected'], 'Integer') : 0; if ($rowCount < 0) { $rowCount = 0; } $whereClause = $orderByClause = ''; - $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid); + $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, json_decode($criteria, TRUE)); + $searchRows = array(); $searchParams = self::getSearchOptionsFromRequest(); @@ -811,7 +814,7 @@ $searchRows[$count]['weight'] = CRM_Utils_Array::value('weight', $pair); if (!empty($pairInfo['data']['canMerge'])) { - $mergeParams = "reset=1&cid={$pairInfo['entity_id1']}&oid={$pairInfo['entity_id2']}&action=update&rgid={$rgid}&limit=" . CRM_Utils_Request::retrieve('limit', 'Integer'); + $mergeParams = "reset=1&cid={$pairInfo['entity_id1']}&oid={$pairInfo['entity_id2']}&action=update&rgid={$rgid}&criteria={$criteria}&limit=" . CRM_Utils_Request::retrieve('limit', 'Integer'); if ($gid) { $mergeParams .= "&gid={$gid}"; } @@ -1010,8 +1013,9 @@ $gid = CRM_Utils_Type::escape($_REQUEST['gid'], 'Integer'); $pnid = $_REQUEST['pnid']; $isSelected = CRM_Utils_Type::escape($_REQUEST['is_selected'], 'Boolean'); + $criteria = CRM_Utils_Request::retrieve('criteria', 'String', $null, FALSE, '{}'); - $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid); + $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, json_decode($criteria, TRUE)); $params = array( 1 => array($isSelected, 'Boolean'), diff --git a/CRM/Contact/Page/DedupeFind.php b/CRM/Contact/Page/DedupeFind.php index 5b09ef6..decfdbc 100644 --- a/CRM/Contact/Page/DedupeFind.php +++ b/CRM/Contact/Page/DedupeFind.php @@ -63,8 +63,9 @@ $limit = CRM_Utils_Request::retrieve('limit', 'Integer', $this); $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive', $this); $cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this, FALSE, 0); - // Using a placeholder for criteria as it is intended to be able to pass this later. - $criteria = array(); + $criteria = CRM_Utils_Request::retrieve('criteria', 'String', $this, FALSE, '{}'); + $this->assign('criteria', $criteria); + $isConflictMode = ($context == 'conflicts'); if ($cid) { $this->_cid = $cid; @@ -79,8 +80,10 @@ 'rgid' => $rgid, 'gid' => $gid, 'limit' => $limit, + 'criteria' => $criteria, ); $this->assign('urlQuery', CRM_Utils_System::makeQueryString($urlQry)); + $criteria = json_decode($criteria, TRUE); if ($context == 'search') { $context = 'search'; diff --git a/CRM/Contact/Page/DedupeMerge.php b/CRM/Contact/Page/DedupeMerge.php index df91a14..1c95481 100644 --- a/CRM/Contact/Page/DedupeMerge.php +++ b/CRM/Contact/Page/DedupeMerge.php @@ -55,15 +55,25 @@ * Build a queue of tasks by dividing dupe pairs in batches. */ public static function getRunner() { + $null = NULL; $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive'); $gid = CRM_Utils_Request::retrieve('gid', 'Positive'); $limit = CRM_Utils_Request::retrieve('limit', 'Positive'); $action = CRM_Utils_Request::retrieve('action', 'String'); - $mode = CRM_Utils_Request::retrieve('mode', 'String', CRM_Core_DAO::$_nullObject, FALSE, 'safe'); + $mode = CRM_Utils_Request::retrieve('mode', 'String', $null, FALSE, 'safe'); + $criteria = CRM_Utils_Request::retrieve('criteria', 'String', $null, FALSE, '{}'); - $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid); + $urlQry = array( + 'reset' => 1, + 'action' => 'update', + 'rgid' => $rgid, + 'gid' => $gid, + 'limit' => $limit, + 'criteria' => $criteria, + ); - $urlQry = "reset=1&action=update&rgid={$rgid}&gid={$gid}&limit={$limit}"; + $criteria = json_decode($criteria, TRUE); + $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, $criteria); if ($mode == 'aggressive' && !CRM_Core_Permission::check('force merge duplicate contacts')) { CRM_Core_Session::setStatus(ts('You do not have permission to force merge duplicate contact records'), ts('Permission Denied'), 'error'); diff --git a/CRM/Contact/Task.php b/CRM/Contact/Task.php index 503c511..d78200d 100644 --- a/CRM/Contact/Task.php +++ b/CRM/Contact/Task.php @@ -228,6 +228,11 @@ 'class' => 'CRM_Contact_Form_Task_Merge', 'result' => TRUE, ); + self::$_tasks['find_duplicates'] = array( + 'title' => ts('Find duplicates for these contacts'), + 'class' => 'CRM_Contact_Form_Task_FindDuplicates', + 'result' => TRUE, + ); } //CRM-4418, check for delete diff --git a/templates/CRM/Contact/Page/DedupeFind.tpl b/templates/CRM/Contact/Page/DedupeFind.tpl index c770655..ca4e491 100644 --- a/templates/CRM/Contact/Page/DedupeFind.tpl +++ b/templates/CRM/Contact/Page/DedupeFind.tpl @@ -122,7 +122,7 @@ {foreach from=$dupe_contacts[$cid] item=dupe_name key=dupe_id} {if $dupe_name} {capture assign=link}<a href="{crmURL p='civicrm/contact/view' q="reset=1&cid=$dupe_id"}">{$dupe_name}</a>{/capture} - {capture assign=merge}<a href="{crmURL p='civicrm/contact/merge' q="reset=1&cid=$cid&oid=$dupe_id"}">{ts}merge{/ts}</a>{/capture} + {capture assign=merge}<a href="{crmURL p='civicrm/contact/merge' q="`$urlQuery`&reset=1&cid=$cid&oid=$dupe_id"}">{ts}merfe{/ts}</a>{/capture} <tr class="{cycle values="odd-row,even-row"}"> <td>{$link}</td> <td style="text-align: right">{$merge}</td> @@ -339,6 +339,9 @@ var is_selected = CRM.$('.crm-dedupe-select-all').prop('checked') ? 1 : 0; } + var criteria = {/literal}'{$criteria}'{literal}; + criteria = criteria.length > 0 ? criteria : 0; + var dataUrl = {/literal}"{crmURL p='civicrm/ajax/toggleDedupeSelect' h=0 q='snippet=4'}"{literal}; var rgid = {/literal}"{$rgid}"{literal}; var gid = {/literal}"{$gid}"{literal}; @@ -346,7 +349,7 @@ rgid = rgid.length > 0 ? rgid : 0; gid = gid.length > 0 ? gid : 0; - CRM.$.post(dataUrl, {pnid: id, rgid: rgid, gid: gid, is_selected: is_selected}, function (data) { + CRM.$.post(dataUrl, {pnid: id, rgid: rgid, gid: gid, is_selected: is_selected, criteria : criteria}, function (data) { // nothing to do for now }, 'json'); } -- To view, visit https://gerrit.wikimedia.org/r/373155 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I2da53510e879c6260be8cee4a455d4a0a2d54693 Gerrit-PatchSet: 16 Gerrit-Project: wikimedia/fundraising/crm/civicrm Gerrit-Branch: master Gerrit-Owner: Eileen <emcnaugh...@wikimedia.org> Gerrit-Reviewer: Eileen <emcnaugh...@wikimedia.org> Gerrit-Reviewer: Ejegg <ej...@ejegg.com> Gerrit-Reviewer: Mepps <me...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits