Merge pull request #1943 from dlobo/CRM-13714
[civicrm-core.git] / CRM / Contact / Form / Merge.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
232624b1 4 | CiviCRM version 4.4 |
6a488035
TO
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
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
31 * @copyright CiviCRM LLC (c) 2004-2013
32 * $Id$
33 *
34 */
35
36require_once 'api/api.php';
37class CRM_Contact_Form_Merge extends CRM_Core_Form {
38 // the id of the contact that tere's a duplicate for; this one will
39 // possibly inherit some of $_oid's properties and remain in the system
40 var $_cid = NULL;
41
42 // the id of the other contact - the duplicate one that will get deleted
43 var $_oid = NULL;
44
45 var $_contactType = NULL;
46
47 // variable to keep all location block ids.
48 protected $_locBlockIds = array();
49
50 // FIXME: QuickForm can't create advcheckboxes with value set to 0 or '0' :(
51 // see HTML_QuickForm_advcheckbox::setValues() - but patching that doesn't
52 // help, as QF doesn't put the 0-value elements in exportValues() anyway...
53 // to side-step this, we use the below UUID as a (re)placeholder
8ef12e64 54 var $_qfZeroBug = 'e8cddb72-a257-11dc-b9cc-0016d3330ee9';
55
6a488035
TO
56 function preProcess() {
57 if (!CRM_Core_Permission::check('merge duplicate contacts')) {
58 CRM_Core_Error::fatal(ts('You do not have access to this page'));
59 }
60
61 $rows = array();
62 $cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this, TRUE);
63 $oid = CRM_Utils_Request::retrieve('oid', 'Positive', $this, TRUE);
64 $flip = CRM_Utils_Request::retrieve('flip', 'Positive', $this, FALSE);
65
66 $this->_rgid = $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive', $this, FALSE);
67 $this->_gid = $gid = CRM_Utils_Request::retrieve('gid', 'Positive', $this, FALSE);
68 $this->_mergeId = CRM_Utils_Request::retrieve('mergeId', 'Positive', $this, FALSE);
69
70 if (!CRM_Dedupe_BAO_Rule::validateContacts($cid, $oid)) {
71 CRM_Core_Error::statusBounce(ts('The selected pair of contacts are marked as non duplicates. If these records should be merged, you can remove this exception on the <a href=\'%1\'>Dedupe Exceptions</a> page.', array(1 => CRM_Utils_System::url('civicrm/dedupe/exception', 'reset=1'))));
72 }
73
74 //load cache mechanism
75 $contactType = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $cid, 'contact_type');
76 $cacheKey = "merge $contactType";
77 $cacheKey .= $rgid ? "_{$rgid}" : '_0';
78 $cacheKey .= $gid ? "_{$gid}" : '_0';
79
8ef12e64 80 $join = "LEFT JOIN civicrm_dedupe_exception de ON ( pn.entity_id1 = de.contact_id1 AND
6a488035
TO
81 pn.entity_id2 = de.contact_id2 )";
82 $where = "de.id IS NULL";
83
84 $pos = CRM_Core_BAO_PrevNextCache::getPositions($cacheKey, $cid, $oid, $this->_mergeId, $join, $where, $flip);
85
86 // Block access if user does not have EDIT permissions for both contacts.
87 if (!(CRM_Contact_BAO_Contact_Permission::allow($cid, CRM_Core_Permission::EDIT) &&
88 CRM_Contact_BAO_Contact_Permission::allow($oid, CRM_Core_Permission::EDIT)
89 )) {
90 CRM_Utils_System::permissionDenied();
91 }
92
93 // get user info of main contact.
94 $config = CRM_Core_Config::singleton();
95 $config->doNotResetCache = 1;
96
97 $viewUser = CRM_Core_Permission::check('access user profiles');
98 $mainUfId = CRM_Core_BAO_UFMatch::getUFId($cid);
99 $mainUser = NULL;
100 if ($mainUfId) {
101 // d6 compatible
102 if ($config->userSystem->is_drupal == '1') {
103 $mainUser = user_load($mainUfId);
104 }
105 elseif ($config->userFramework == 'Joomla') {
106 $mainUser = JFactory::getUser($mainUfId);
107 }
108
109 $this->assign('mainUfId', $mainUfId);
110 $this->assign('mainUfName', $mainUser ? $mainUser->name : NULL);
111 }
112
113 $flipUrl = CRM_Utils_system::url('civicrm/contact/merge',
114 "reset=1&action=update&cid={$oid}&oid={$cid}&rgid={$rgid}&gid={$gid}"
115 );
116 if (!$flip) {
117 $flipUrl .= '&flip=1';
118 }
119 $this->assign('flip', $flipUrl);
120
121 $this->prev = $this->next = NULL;
122 foreach (array(
123 'prev', 'next') as $position) {
124 if (!empty($pos[$position])) {
125 if ($pos[$position]['id1'] && $pos[$position]['id2']) {
126 $urlParam = "reset=1&cid={$pos[$position]['id1']}&oid={$pos[$position]['id2']}&mergeId={$pos[$position]['mergeId']}&action=update";
127
128 if ($rgid) {
129 $urlParam .= "&rgid={$rgid}";
130 }
131 if ($gid) {
132 $urlParam .= "&gid={$gid}";
133 }
134
135 $this->$position = CRM_Utils_system::url('civicrm/contact/merge', $urlParam);
136 $this->assign($position, $this->$position);
137 }
138 }
139 }
140
141 // get user info of other contact.
142 $otherUfId = CRM_Core_BAO_UFMatch::getUFId($oid);
143 $otherUser = NULL;
144
145 if ($otherUfId) {
146 // d6 compatible
147 if ($config->userSystem->is_drupal == '1') {
148 $otherUser = user_load($otherUfId);
149 }
150 elseif ($config->userFramework == 'Joomla') {
151 $otherUser = JFactory::getUser($otherUfId);
152 }
153
154 $this->assign('otherUfId', $otherUfId);
155 $this->assign('otherUfName', $otherUser ? $otherUser->name : NULL);
156 }
157
158 $cmsUser = ($mainUfId && $otherUfId) ? TRUE : FALSE;
159 $this->assign('user', $cmsUser);
160
161 $session = CRM_Core_Session::singleton();
162
163 // context fixed.
164 if ($rgid) {
165 $urlParam = "reset=1&action=browse&rgid={$rgid}";
166 if ($gid) {
167 $urlParam .= "&gid={$gid}";
168 }
169 $session->pushUserContext(CRM_Utils_system::url('civicrm/contact/dedupefind', $urlParam));
170 }
171
172 // ensure that oid is not the current user, if so refuse to do the merge
173 if ($session->get('userID') == $oid) {
174 $display_name = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $oid, 'display_name');
175 $message = ts('The contact record which is linked to the currently logged in user account - \'%1\' - cannot be deleted.',
176 array(1 => $display_name)
177 );
178 CRM_Core_Error::statusBounce($message);
179 }
180
181 $rowsElementsAndInfo = CRM_Dedupe_Merger::getRowsElementsAndInfo($cid, $oid);
182 $main = &$rowsElementsAndInfo['main_details'];
183 $other = &$rowsElementsAndInfo['other_details'];
184
185 if ($main['contact_id'] != $cid) {
186 CRM_Core_Error::fatal(ts('The main contact record does not exist'));
187 }
188
189 if ($other['contact_id'] != $oid) {
190 CRM_Core_Error::fatal(ts('The other contact record does not exist'));
191 }
192
193 $subtypes = CRM_Contact_BAO_ContactType::subTypePairs(NULL, TRUE, '');
194
195 $this->assign('contact_type', $main['contact_type']);
0f6fa7a8 196 if (!empty($main['contact_sub_type'])) {
6a488035
TO
197 $this->assign('main_contact_subtype',
198 CRM_Utils_Array::value('contact_sub_type', $subtypes[$main['contact_sub_type'][0]])
199 );
200 }
0f6fa7a8 201 if (!empty($other['contact_sub_type'])) {
6a488035
TO
202 $this->assign('other_contact_subtype',
203 CRM_Utils_Array::value('contact_sub_type', $subtypes[$other['contact_sub_type'][0]])
204 );
205 }
206 $this->assign('main_name', $main['display_name']);
207 $this->assign('other_name', $other['display_name']);
208 $this->assign('main_cid', $main['contact_id']);
209 $this->assign('other_cid', $other['contact_id']);
210
211 $this->_cid = $cid;
212 $this->_oid = $oid;
213 $this->_rgid = $rgid;
214 $this->_contactType = $main['contact_type'];
215 $this->addElement('checkbox', 'toggleSelect', NULL, NULL, array('onclick' => "return toggleCheckboxVals('move_',this);"));
216
217 $this->assign('mainLocBlock', json_encode($rowsElementsAndInfo['main_loc_block']));
218 $this->assign('rows', $rowsElementsAndInfo['rows']);
219
220 $this->_locBlockIds = array(
221 'main' => $rowsElementsAndInfo['main_details']['loc_block_ids'],
222 'other' => $rowsElementsAndInfo['other_details']['loc_block_ids']
223 );
224
225 // add elements
226 foreach ($rowsElementsAndInfo['elements'] as $element) {
227 $this->addElement($element[0],
228 $element[1],
229 array_key_exists('2', $element) ? $element[2] : NULL,
230 array_key_exists('3', $element) ? $element[3] : NULL,
231 array_key_exists('4', $element) ? $element[4] : NULL,
232 array_key_exists('5', $element) ? $element[5] : NULL
233 );
234 }
235
236 // add related table elements
237 foreach ($rowsElementsAndInfo['rel_table_elements'] as $relTableElement) {
238 $element = $this->addElement($relTableElement[0], $relTableElement[1]);
239 $element->setChecked(TRUE);
240 }
241
242 $this->assign('rel_tables', $rowsElementsAndInfo['rel_tables']);
243 $this->assign('userContextURL', $session->readUserContext());
244 }
245
246 function setDefaultValues() {
247 return array('deleteOther' => 1);
248 }
249
250 function addRules() {}
251
252 public function buildQuickForm() {
253 CRM_Utils_System::setTitle(ts('Merge %1s', array(1 => $this->_contactType)));
254 $name = ts('Merge');
255 if ($this->next) {
256 $name = ts('Merge and Goto Next Pair');
257 }
258
259 if ($this->next || $this->prev) {
260 $button = array(
261 array(
262 'type' => 'next',
263 'name' => $name,
264 'isDefault' => TRUE,
265 ),
266 array(
267 'type' => 'submit',
268 'name' => ts('Merge and Goto Listing'),
269 ),
270 array(
271 'type' => 'done',
272 'name' => ts('Merge and View Result'),
273 ),
274 array(
275 'type' => 'cancel',
276 'name' => ts('Cancel'),
277 ),
278 );
279 }
280 else {
281 $button = array(
282 array(
283 'type' => 'next',
284 'name' => $name,
285 'isDefault' => TRUE,
286 ),
287 array(
288 'type' => 'cancel',
289 'name' => ts('Cancel'),
290 ),
291 );
292 }
293
294 $this->addButtons($button);
295 }
296
297 public function postProcess() {
298 $formValues = $this->exportValues();
8ef12e64 299
6a488035
TO
300 // reset all selected contact ids from session
301 // when we came from search context, CRM-3526
302 $session = CRM_Core_Session::singleton();
303 if ($session->get('selectedSearchContactIds')) {
304 $session->resetScope('selectedSearchContactIds');
305 }
306
307 $formValues['main_details'] = $formValues['other_details'] = array();
308 $formValues['main_details']['contact_type'] = $this->_contactType;
309 $formValues['main_details']['loc_block_ids'] = $this->_locBlockIds['main'];
310 $formValues['other_details']['loc_block_ids'] = $this->_locBlockIds['other'];
311
312 CRM_Dedupe_Merger::moveAllBelongings($this->_cid, $this->_oid, $formValues);
313
314 CRM_Core_Session::setStatus(ts('Contact id %1 has been updated and contact id %2 has been deleted.', array(1 => $this->_cid, 2 => $this->_oid)), ts('Contacts Merged'), 'success');
315 $url = CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$this->_cid}");
316 if (CRM_Utils_Array::value('_qf_Merge_submit', $formValues)) {
317 $listParamsURL = "reset=1&action=update&rgid={$this->_rgid}";
318 if ($this->_gid) {
319 $listParamsURL .= "&gid={$this->_gid}";
320 }
321 $lisitingURL = CRM_Utils_System::url('civicrm/contact/dedupefind',
322 $listParamsURL
323 );
324 CRM_Utils_System::redirect($lisitingURL);
325 }
326 if (CRM_Utils_Array::value('_qf_Merge_done', $formValues)) {
327 CRM_Utils_System::redirect($url);
328 }
329
330 if ($this->next && $this->_mergeId) {
331 $cacheKey = "merge {$this->_contactType}";
332 $cacheKey .= $this->_rgid ? "_{$this->_rgid}" : '_0';
333 $cacheKey .= $this->_gid ? "_{$this->_gid}" : '_0';
334
8ef12e64 335 $join = "LEFT JOIN civicrm_dedupe_exception de ON ( pn.entity_id1 = de.contact_id1 AND
6a488035
TO
336 pn.entity_id2 = de.contact_id2 )";
337 $where = "de.id IS NULL";
338
339 $pos = CRM_Core_BAO_PrevNextCache::getPositions($cacheKey, NULL, NULL, $this->_mergeId, $join, $where);
340
341 if (!empty($pos) &&
342 $pos['next']['id1'] &&
343 $pos['next']['id2']
344 ) {
345
346 $urlParam = "reset=1&cid={$pos['next']['id1']}&oid={$pos['next']['id2']}&mergeId={$pos['next']['mergeId']}&action=update";
347 if ($this->_rgid) {
348 $urlParam .= "&rgid={$this->_rgid}";
349 }
350 if ($this->_gid) {
351 $urlParam .= "&gid={$this->_gid}";
352 }
353
354 $url = CRM_Utils_system::url('civicrm/contact/merge', $urlParam);
355 }
356 }
357
358 CRM_Utils_System::redirect($url);
359 }
360}
361