3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2014
35 class CRM_Contact_Page_DedupeFind
extends CRM_Core_Page_Basic
{
36 protected $_cid = NULL;
38 protected $_mainContacts;
44 * @return string Classname of BAO.
46 function getBAOName() {
47 return 'CRM_Dedupe_BAO_RuleGroup';
53 * @return array (reference) of action links
58 * Browse all rule groups
64 $gid = CRM_Utils_Request
::retrieve('gid', 'Positive', $this, FALSE, 0);
65 $action = CRM_Utils_Request
::retrieve('action', 'String', $this, FALSE, 0);
66 $context = CRM_Utils_Request
::retrieve('context', 'String', $this);
68 $session = CRM_Core_Session
::singleton();
69 $contactIds = $session->get('selectedSearchContactIds');
70 if ($context == 'search' ||
!empty($contactIds)) {
72 $this->assign('backURL', $session->readUserContext());
75 if ($action & CRM_Core_Action
::RENEW
) {
77 $rgid = CRM_Utils_Request
::retrieve('rgid', 'Positive', $this, FALSE, 0);
80 $contactType = CRM_Core_DAO
::getFieldValue('CRM_Dedupe_DAO_RuleGroup', $rgid, 'contact_type');
81 $cacheKeyString = "merge $contactType";
82 $cacheKeyString .= $rgid ?
"_{$rgid}" : '_0';
83 $cacheKeyString .= $gid ?
"_{$gid}" : '_0';
84 CRM_Core_BAO_PrevNextCache
::deleteItem(NULL, $cacheKeyString);
86 $urlQry = "reset=1&action=update&rgid={$rgid}";
88 $urlQry .= "&gid={$gid}";
90 CRM_Utils_System
::redirect(CRM_Utils_System
::url('civicrm/contact/dedupefind', $urlQry));
92 elseif ($action & CRM_Core_Action
::MAP
) {
93 // do a batch merge if requested
94 $rgid = CRM_Utils_Request
::retrieve('rgid', 'Positive', $this, FALSE, 0);
95 $result = CRM_Dedupe_Merger
::batchMerge($rgid, $gid, 'safe', TRUE, TRUE);
97 $skippedCount = CRM_Utils_Request
::retrieve('skipped', 'Positive', $this, FALSE, 0);
98 $skippedCount = $skippedCount +
count($result['skipped']);
99 $mergedCount = CRM_Utils_Request
::retrieve('merged', 'Positive', $this, FALSE, 0);
100 $mergedCount = $mergedCount +
count($result['merged']);
102 if (empty($result['merged']) && empty($result['skipped'])) {
104 if ($mergedCount >= 1) {
105 $message = ts("%1 pairs of duplicates were merged", array(1 => $mergedCount));
107 if ($skippedCount >= 1) {
108 $message = $message ?
"{$message} and " : '';
109 $message .= ts("%1 pairs of duplicates were skipped due to conflict",
110 array(1 => $skippedCount)
113 $message .= ts(" during the batch merge process with safe mode.");
114 CRM_Core_Session
::setStatus($message, ts('Merge Complete'), 'success');
116 $urlQry = "reset=1&action=update&rgid={$rgid}";
118 $urlQry .= "&gid={$gid}";
120 CRM_Utils_System
::redirect(CRM_Utils_System
::url('civicrm/contact/dedupefind', $urlQry));
123 $urlQry = "reset=1&action=map&rgid={$rgid}";
125 $urlQry .= "&gid={$gid}";
127 $urlQry .= "&skipped={$skippedCount}&merged={$mergedCount}";
128 CRM_Utils_System
::jsRedirect(
129 CRM_Utils_System
::url('civicrm/contact/dedupefind', $urlQry),
130 ts('Batch Merge Task in progress'),
131 ts('The batch merge task is still in progress. This page will be refreshed automatically.')
136 if ($action & CRM_Core_Action
::UPDATE ||
137 $action & CRM_Core_Action
::BROWSE
139 $cid = CRM_Utils_Request
::retrieve('cid', 'Positive', $this, FALSE, 0);
140 $rgid = CRM_Utils_Request
::retrieve('rgid', 'Positive', $this, FALSE, 0);
141 $this->action
= CRM_Core_Action
::UPDATE
;
143 //calculate the $contactType
145 $contactType = CRM_Core_DAO
::getFieldValue('CRM_Dedupe_DAO_RuleGroup',
151 $sourceParams = 'snippet=4';
153 $sourceParams .= "&gid={$gid}";
156 $sourceParams .= "&rgid={$rgid}";
159 $this->assign('sourceUrl', CRM_Utils_System
::url('civicrm/ajax/dedupefind', $sourceParams, FALSE, NULL, FALSE));
161 //reload from cache table
162 $cacheKeyString = "merge $contactType";
163 $cacheKeyString .= $rgid ?
"_{$rgid}" : '_0';
164 $cacheKeyString .= $gid ?
"_{$gid}" : '_0';
166 $join = "LEFT JOIN civicrm_dedupe_exception de ON ( pn.entity_id1 = de.contact_id1 AND
167 pn.entity_id2 = de.contact_id2 )";
168 $where = "de.id IS NULL";
169 $this->_mainContacts
= CRM_Core_BAO_PrevNextCache
::retrieve($cacheKeyString, $join, $where);
170 if (empty($this->_mainContacts
)) {
172 $foundDupes = $this->get("dedupe_dupes_$gid");
174 $foundDupes = CRM_Dedupe_Finder
::dupesInGroup($rgid, $gid);
176 $this->set("dedupe_dupes_$gid", $foundDupes);
178 elseif (!empty($contactIds)) {
179 $foundDupes = $this->get("search_dedupe_dupes_$gid");
181 $foundDupes = CRM_Dedupe_Finder
::dupes($rgid, $contactIds);
183 $this->get("search_dedupe_dupes_$gid", $foundDupes);
186 $foundDupes = $this->get('dedupe_dupes');
188 $foundDupes = CRM_Dedupe_Finder
::dupes($rgid);
190 $this->set('dedupe_dupes', $foundDupes);
193 $ruleGroup = new CRM_Dedupe_BAO_RuleGroup();
194 $ruleGroup->id
= $rgid;
195 $ruleGroup->find(TRUE);
197 $session = CRM_Core_Session
::singleton();
198 $session->setStatus(ts('No possible duplicates were found using %1 rule.', array(1 => $ruleGroup->name
)), ts('None Found'), 'info');
199 $url = CRM_Utils_System
::url('civicrm/contact/deduperules', 'reset=1');
200 if ($context == 'search') {
201 $url = $session->readUserContext();
203 CRM_Utils_System
::redirect($url);
207 foreach ($foundDupes as $dupe) {
211 $cidString = implode(', ', array_keys($cids));
212 $sql = "SELECT id, display_name FROM civicrm_contact WHERE id IN ($cidString) ORDER BY sort_name";
213 $dao = new CRM_Core_DAO();
215 $displayNames = array();
216 while ($dao->fetch()) {
217 $displayNames[$dao->id
] = $dao->display_name
;
220 // FIXME: sort the contacts; $displayName
221 // is already sort_name-sorted, so use that
222 // (also, consider sorting by dupe count first)
223 // lobo - change the sort to by threshold value
224 // so the more likely dupes are sorted first
225 $session = CRM_Core_Session
::singleton();
226 $userId = $session->get('userID');
227 $mainContacts = $permission = array();
229 foreach ($foundDupes as $dupes) {
232 if ($dstID == $userId) {
238 * Eliminate this since it introduces 3 queries PER merge row
239 * and hence is very expensive
241 if ( !array_key_exists( $srcID, $permission ) ) {
242 $permission[$srcID] = CRM_Contact_BAO_Contact_Permission::allow( $srcID, CRM_Core_Permission::EDIT );
244 if ( !array_key_exists( $dstID, $permission ) ) {
245 $permission[$dstID] = CRM_Contact_BAO_Contact_Permission::allow( $dstID, CRM_Core_Permission::EDIT );
248 $canMerge = ( $permission[$dstID] && $permission[$srcID] );
252 // we'll do permission checking during the merge process
255 $mainContacts[] = $row = array(
257 'srcName' => $displayNames[$srcID],
259 'dstName' => $displayNames[$dstID],
260 'weight' => $dupes[2],
261 'canMerge' => $canMerge,
264 $data = CRM_Core_DAO
::escapeString(serialize($row));
265 $values[] = " ( 'civicrm_contact', $srcID, $dstID, '$cacheKeyString', '$data' ) ";
273 $this->_rgid
= $rgid;
274 $this->_mainContacts
= $mainContacts;
276 CRM_Core_BAO_PrevNextCache
::setItem($values);
277 $session = CRM_Core_Session
::singleton();
279 $session->pushUserContext(CRM_Utils_System
::url('civicrm/contact/deduperules',
280 "action=update&rgid={$this->_rgid}&gid={$this->_gid}&cid={$this->_cid}"
284 $session->pushUserContext(CRM_Utils_System
::url('civicrm/contact/dedupefind',
285 "reset=1&action=update&rgid={$this->_rgid}"
297 $this->_rgid
= $rgid;
300 $this->assign('action', $this->action
);
304 $this->action
= CRM_Core_Action
::UPDATE
;
305 $this->edit($this->action
);
306 $this->assign('action', $this->action
);
308 $this->assign('context', $context);
311 return parent
::run();
315 * Browse all rule groups
321 $this->assign('main_contacts', $this->_mainContacts
);
324 $this->assign('cid', $this->_cid
);
326 if (isset($this->_gid
) ||
$this->_gid
) {
327 $this->assign('gid', $this->_gid
);
329 $this->assign('rgid', $this->_rgid
);
333 * Get name of edit form
335 * @return string classname of edit form
337 function editForm() {
338 return 'CRM_Contact_Form_DedupeFind';
344 * @return string name of this page
346 function editName() {
355 * @return string user context
357 function userContext($mode = NULL) {
358 return 'civicrm/contact/dedupefind';