INFRA-132 - CRM/Contact - phpcbf
[civicrm-core.git] / CRM / Contact / Page / DedupeFind.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
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. |
13 | |
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. |
18 | |
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 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35class CRM_Contact_Page_DedupeFind extends CRM_Core_Page_Basic {
36 protected $_cid = NULL;
37 protected $_rgid;
38 protected $_mainContacts;
39 protected $_gid;
40
41 /**
42 * Get BAO Name
43 *
44 * @return string Classname of BAO.
8ef12e64 45 */
00be9182 46 public function getBAOName() {
6a488035
TO
47 return 'CRM_Dedupe_BAO_RuleGroup';
48 }
49
50 /**
51 * Get action Links
52 *
53 * @return array (reference) of action links
54 */
ce80b209
TO
55 public function &links() {
56 }
6a488035
TO
57
58 /**
59 * Browse all rule groups
60 *
61 * @return void
6a488035 62 */
00be9182 63 public function run() {
6a488035
TO
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);
67
68 $session = CRM_Core_Session::singleton();
69 $contactIds = $session->get('selectedSearchContactIds');
70 if ($context == 'search' || !empty($contactIds)) {
71 $context = 'search';
72 $this->assign('backURL', $session->readUserContext());
73 }
74
75 if ($action & CRM_Core_Action::RENEW) {
76 // empty cache
77 $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive', $this, FALSE, 0);
78
79 if ($rgid) {
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);
85 }
86 $urlQry = "reset=1&action=update&rgid={$rgid}";
87 if ($gid) {
88 $urlQry .= "&gid={$gid}";
89 }
90 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry));
91 }
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);
96
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']);
101
102 if (empty($result['merged']) && empty($result['skipped'])) {
103 $message = '';
104 if ($mergedCount >= 1) {
105 $message = ts("%1 pairs of duplicates were merged", array(1 => $mergedCount));
106 }
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)
111 );
112 }
113 $message .= ts(" during the batch merge process with safe mode.");
114 CRM_Core_Session::setStatus($message, ts('Merge Complete'), 'success');
115
116 $urlQry = "reset=1&action=update&rgid={$rgid}";
117 if ($gid) {
118 $urlQry .= "&gid={$gid}";
119 }
120 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry));
121 }
122 else {
123 $urlQry = "reset=1&action=map&rgid={$rgid}";
124 if ($gid) {
125 $urlQry .= "&gid={$gid}";
126 }
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.')
132 );
133 }
134 }
135
136 if ($action & CRM_Core_Action::UPDATE ||
137 $action & CRM_Core_Action::BROWSE
138 ) {
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;
142
143 //calculate the $contactType
144 if ($rgid) {
145 $contactType = CRM_Core_DAO::getFieldValue('CRM_Dedupe_DAO_RuleGroup',
146 $rgid,
147 'contact_type'
148 );
149 }
150
151 $sourceParams = 'snippet=4';
152 if ($gid) {
153 $sourceParams .= "&gid={$gid}";
154 }
155 if ($rgid) {
156 $sourceParams .= "&rgid={$rgid}";
157 }
158
159 $this->assign('sourceUrl', CRM_Utils_System::url('civicrm/ajax/dedupefind', $sourceParams, FALSE, NULL, FALSE));
160
161 //reload from cache table
162 $cacheKeyString = "merge $contactType";
163 $cacheKeyString .= $rgid ? "_{$rgid}" : '_0';
164 $cacheKeyString .= $gid ? "_{$gid}" : '_0';
165
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)) {
171 if ($gid) {
172 $foundDupes = $this->get("dedupe_dupes_$gid");
173 if (!$foundDupes) {
174 $foundDupes = CRM_Dedupe_Finder::dupesInGroup($rgid, $gid);
175 }
176 $this->set("dedupe_dupes_$gid", $foundDupes);
177 }
178 elseif (!empty($contactIds)) {
179 $foundDupes = $this->get("search_dedupe_dupes_$gid");
180 if (!$foundDupes) {
181 $foundDupes = CRM_Dedupe_Finder::dupes($rgid, $contactIds);
182 }
183 $this->get("search_dedupe_dupes_$gid", $foundDupes);
184 }
185 else {
186 $foundDupes = $this->get('dedupe_dupes');
187 if (!$foundDupes) {
188 $foundDupes = CRM_Dedupe_Finder::dupes($rgid);
189 }
190 $this->set('dedupe_dupes', $foundDupes);
191 }
192 if (!$foundDupes) {
193 $ruleGroup = new CRM_Dedupe_BAO_RuleGroup();
194 $ruleGroup->id = $rgid;
195 $ruleGroup->find(TRUE);
196
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();
202 }
203 CRM_Utils_System::redirect($url);
204 }
205 else {
206 $cids = array();
207 foreach ($foundDupes as $dupe) {
208 $cids[$dupe[0]] = 1;
209 $cids[$dupe[1]] = 1;
210 }
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();
214 $dao->query($sql);
215 $displayNames = array();
216 while ($dao->fetch()) {
217 $displayNames[$dao->id] = $dao->display_name;
218 }
219
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();
228
229 foreach ($foundDupes as $dupes) {
230 $srcID = $dupes[0];
231 $dstID = $dupes[1];
232 if ($dstID == $userId) {
233 $srcID = $dupes[1];
234 $dstID = $dupes[0];
235 }
236
237 /***
238 * Eliminate this since it introduces 3 queries PER merge row
239 * and hence is very expensive
240 * CRM-8822
241 if ( !array_key_exists( $srcID, $permission ) ) {
242 $permission[$srcID] = CRM_Contact_BAO_Contact_Permission::allow( $srcID, CRM_Core_Permission::EDIT );
243 }
244 if ( !array_key_exists( $dstID, $permission ) ) {
245 $permission[$dstID] = CRM_Contact_BAO_Contact_Permission::allow( $dstID, CRM_Core_Permission::EDIT );
246 }
247
248 $canMerge = ( $permission[$dstID] && $permission[$srcID] );
249 *
250 */
251
252 // we'll do permission checking during the merge process
253 $canMerge = TRUE;
254
255 $mainContacts[] = $row = array(
256 'srcID' => $srcID,
257 'srcName' => $displayNames[$srcID],
258 'dstID' => $dstID,
259 'dstName' => $displayNames[$dstID],
260 'weight' => $dupes[2],
261 'canMerge' => $canMerge,
262 );
263
264 $data = CRM_Core_DAO::escapeString(serialize($row));
265 $values[] = " ( 'civicrm_contact', $srcID, $dstID, '$cacheKeyString', '$data' ) ";
266 }
267 if ($cid) {
268 $this->_cid = $cid;
269 }
270 if ($gid) {
271 $this->_gid = $gid;
272 }
273 $this->_rgid = $rgid;
274 $this->_mainContacts = $mainContacts;
275
276 CRM_Core_BAO_PrevNextCache::setItem($values);
277 $session = CRM_Core_Session::singleton();
278 if ($this->_cid) {
279 $session->pushUserContext(CRM_Utils_System::url('civicrm/contact/deduperules',
280 "action=update&rgid={$this->_rgid}&gid={$this->_gid}&cid={$this->_cid}"
281 ));
282 }
283 else {
284 $session->pushUserContext(CRM_Utils_System::url('civicrm/contact/dedupefind',
285 "reset=1&action=update&rgid={$this->_rgid}"
286 ));
287 }
288 }
289 }
290 else {
291 if ($cid) {
292 $this->_cid = $cid;
293 }
294 if ($gid) {
295 $this->_gid = $gid;
296 }
297 $this->_rgid = $rgid;
298 }
299
300 $this->assign('action', $this->action);
301 $this->browse();
302 }
303 else {
304 $this->action = CRM_Core_Action::UPDATE;
305 $this->edit($this->action);
306 $this->assign('action', $this->action);
307 }
308 $this->assign('context', $context);
309
310 // parent run
311 return parent::run();
312 }
313
314 /**
315 * Browse all rule groups
316 *
317 * @return void
6a488035 318 */
00be9182 319 public function browse() {
6a488035
TO
320 $this->assign('main_contacts', $this->_mainContacts);
321
322 if ($this->_cid) {
323 $this->assign('cid', $this->_cid);
324 }
325 if (isset($this->_gid) || $this->_gid) {
326 $this->assign('gid', $this->_gid);
327 }
328 $this->assign('rgid', $this->_rgid);
329 }
330
331 /**
332 * Get name of edit form
333 *
334 * @return string classname of edit form
335 */
00be9182 336 public function editForm() {
6a488035
TO
337 return 'CRM_Contact_Form_DedupeFind';
338 }
339
340 /**
341 * Get edit form name
342 *
343 * @return string name of this page
344 */
00be9182 345 public function editName() {
6a488035
TO
346 return 'DedupeFind';
347 }
348
349 /**
350 * Get user context
351 *
77b97be7
EM
352 * @param null $mode
353 *
6a488035
TO
354 * @return string user context
355 */
00be9182 356 public function userContext($mode = NULL) {
6a488035
TO
357 return 'civicrm/contact/dedupefind';
358 }
359}