Merge pull request #16432 from colemanw/comments
[civicrm-core.git] / CRM / Contact / Page / AJAX.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
bc77d7c0
TO
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035
TO
11
12/**
13 *
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035
TO
16 *
17 */
18
19/**
20 * This class contains all contact related functions that are called using AJAX (jQuery)
21 */
22class CRM_Contact_Page_AJAX {
272081ca
TO
23 /**
24 * When a user chooses a username, CHECK_USERNAME_TTL
25 * is the time window in which they can check usernames
26 * (without reloading the overall form).
27 */
69078420
SL
28 // 3hr; 3*60*60
29 const CHECK_USERNAME_TTL = 10800;
272081ca 30
69078420
SL
31 // 6hr; 6*60*60
32 const AUTOCOMPLETE_TTL = 21600;
b1dba111 33
06508628 34 /**
06508628
CW
35 * Ajax callback for custom fields of type ContactReference
36 *
37 * Todo: Migrate contact reference fields to use EntityRef
38 */
00be9182 39 public static function contactReference() {
06508628 40 $name = CRM_Utils_Array::value('term', $_GET);
6a488035
TO
41 $name = CRM_Utils_Type::escape($name, 'String');
42 $cfID = CRM_Utils_Type::escape($_GET['id'], 'Positive');
43
44 // check that this is a valid, active custom field of Contact Reference type
be2fb01f
CW
45 $params = ['id' => $cfID];
46 $returnProperties = ['filter', 'data_type', 'is_active'];
47 $cf = [];
6a488035 48 CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_CustomField', $params, $cf, $returnProperties);
a4cce21a 49 if (!$cf['id'] || !$cf['is_active'] || $cf['data_type'] != 'ContactReference') {
d8cdb7e5 50 CRM_Utils_System::civiExit(1);
6a488035
TO
51 }
52
9624538c 53 if (!empty($cf['filter'])) {
be2fb01f 54 $filterParams = [];
6a488035
TO
55 parse_str($cf['filter'], $filterParams);
56
57 $action = CRM_Utils_Array::value('action', $filterParams);
be2fb01f 58 if (!empty($action) && !in_array($action, ['get', 'lookup'])) {
d8cdb7e5 59 CRM_Utils_System::civiExit(1);
6a488035 60 }
da0136df 61
62 if (!empty($filterParams['group'])) {
63 $filterParams['group'] = explode(',', $filterParams['group']);
64 }
6a488035
TO
65 }
66
67 $list = array_keys(CRM_Core_BAO_Setting::valueOptions(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
353ffa53
TO
68 'contact_reference_options'
69 ), '1');
6a488035 70
be2fb01f 71 $return = array_unique(array_merge(['sort_name'], $list));
6a488035 72
89595c92 73 $limit = Civi::settings()->get('search_autocomplete_count');
6a488035 74
be2fb01f 75 $params = ['offset' => 0, 'rowCount' => $limit, 'version' => 3];
6a488035
TO
76 foreach ($return as $fld) {
77 $params["return.{$fld}"] = 1;
78 }
79
80 if (!empty($action)) {
be2fb01f 81 $excludeGet = [
353ffa53
TO
82 'reset',
83 'key',
84 'className',
85 'fnName',
86 'json',
87 'reset',
88 'context',
89 'timestamp',
90 'limit',
91 'id',
92 's',
93 'q',
408b79bf 94 'action',
be2fb01f 95 ];
6a488035
TO
96 foreach ($_GET as $param => $val) {
97 if (empty($val) ||
98 in_array($param, $excludeGet) ||
99 strpos($param, 'return.') !== FALSE ||
100 strpos($param, 'api.') !== FALSE
101 ) {
102 continue;
103 }
104 $params[$param] = $val;
105 }
106 }
107
108 if ($name) {
109 $params['sort_name'] = $name;
110 }
111
112 $params['sort'] = 'sort_name';
113
114 // tell api to skip permission chk. dgg
115 $params['check_permissions'] = 0;
116
117 // add filter variable to params
118 if (!empty($filterParams)) {
119 $params = array_merge($params, $filterParams);
120 }
121
122 $contact = civicrm_api('Contact', 'Get', $params);
123
a7488080 124 if (!empty($contact['is_error'])) {
d8cdb7e5 125 CRM_Utils_System::civiExit(1);
6a488035
TO
126 }
127
be2fb01f 128 $contactList = [];
6a488035 129 foreach ($contact['values'] as $value) {
be2fb01f 130 $view = [];
6a488035 131 foreach ($return as $fld) {
a7488080 132 if (!empty($value[$fld])) {
6a488035
TO
133 $view[] = $value[$fld];
134 }
135 }
be2fb01f 136 $contactList[] = ['id' => $value['id'], 'text' => implode(' :: ', $view)];
6a488035
TO
137 }
138
da0136df 139 if (!empty($_GET['is_unit_test'])) {
140 return $contactList;
141 }
8be1a839 142 CRM_Utils_JSON::output($contactList);
6a488035
TO
143 }
144
145 /**
100fef9d 146 * Fetch PCP ID by PCP Supporter sort_name, also displays PCP title and associated Contribution Page title
6a488035 147 */
00be9182 148 public static function getPCPList() {
7d86179d 149 $name = CRM_Utils_Array::value('term', $_GET);
353ffa53 150 $name = CRM_Utils_Type::escape($name, 'String');
89595c92 151 $limit = $max = Civi::settings()->get('search_autocomplete_count');
6a488035
TO
152
153 $where = ' AND pcp.page_id = cp.id AND pcp.contact_id = cc.id';
154
155 $config = CRM_Core_Config::singleton();
156 if ($config->includeWildCardInName) {
157 $strSearch = "%$name%";
158 }
159 else {
160 $strSearch = "$name%";
161 }
162 $includeEmailFrom = $includeNickName = '';
163 if ($config->includeNickNameInName) {
164 $includeNickName = " OR nick_name LIKE '$strSearch'";
165 }
166 if ($config->includeEmailInName) {
167 $includeEmailFrom = "LEFT JOIN civicrm_email eml ON ( cc.id = eml.contact_id AND eml.is_primary = 1 )";
168 $whereClause = " WHERE ( email LIKE '$strSearch' OR sort_name LIKE '$strSearch' $includeNickName ) {$where} ";
169 }
170 else {
171 $whereClause = " WHERE ( sort_name LIKE '$strSearch' $includeNickName ) {$where} ";
172 }
173
8da35492 174 $offset = $count = 0;
4feb1cad
CW
175 if (!empty($_GET['page_num'])) {
176 $page = (int) $_GET['page_num'];
8da35492
CW
177 $offset = $limit * ($page - 1);
178 $limit++;
6a488035
TO
179 }
180
181 $select = 'cc.sort_name, pcp.title, cp.title';
182 $query = "
183 SELECT id, data
184 FROM (
185 SELECT pcp.id as id, CONCAT_WS( ' :: ', {$select} ) as data, sort_name
186 FROM civicrm_pcp pcp, civicrm_contribution_page cp, civicrm_contact cc
187 {$includeEmailFrom}
900e6829 188 {$whereClause} AND pcp.page_type = 'contribute'
189 UNION ALL
190 SELECT pcp.id as id, CONCAT_WS( ' :: ', {$select} ) as data, sort_name
191 FROM civicrm_pcp pcp, civicrm_event cp, civicrm_contact cc
192 {$includeEmailFrom}
193 {$whereClause} AND pcp.page_type = 'event'
6a488035
TO
194 ) t
195 ORDER BY sort_name
8da35492 196 LIMIT $offset, $limit
6a488035
TO
197 ";
198
199 $dao = CRM_Core_DAO::executeQuery($query);
be2fb01f 200 $output = ['results' => [], 'more' => FALSE];
6a488035 201 while ($dao->fetch()) {
8da35492
CW
202 if (++$count > $max) {
203 $output['more'] = TRUE;
204 }
205 else {
be2fb01f 206 $output['results'][] = ['id' => $dao->id, 'text' => $dao->data];
8da35492 207 }
6a488035 208 }
8da35492 209 CRM_Utils_JSON::output($output);
6a488035
TO
210 }
211
00be9182 212 public static function relationship() {
3b1c37fe 213 $relType = CRM_Utils_Request::retrieve('rel_type', 'String', CRM_Core_DAO::$_nullObject, TRUE);
c91df8b4 214 $relContactID = CRM_Utils_Request::retrieve('rel_contact', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
a3d827a7
CW
215 $originalCid = CRM_Utils_Request::retrieve('cid', 'Positive');
216 $relationshipID = CRM_Utils_Request::retrieve('rel_id', 'Positive');
c91df8b4 217 $caseID = CRM_Utils_Request::retrieve('case_id', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
6a488035 218
3b1c37fe
CW
219 if (!CRM_Case_BAO_Case::accessCase($caseID)) {
220 CRM_Utils_System::permissionDenied();
221 }
6a488035 222
be2fb01f 223 $ret = ['is_error' => 0];
c91df8b4 224
3b1c37fe 225 list($relTypeId, $b, $a) = explode('_', $relType);
14a679f1 226
3b1c37fe
CW
227 if ($relationshipID && $originalCid) {
228 CRM_Case_BAO_Case::endCaseRole($caseID, $a, $originalCid, $relTypeId);
229 }
14a679f1 230
3b1c37fe 231 $clientList = CRM_Case_BAO_Case::getCaseClients($caseID);
14a679f1 232
3b1c37fe
CW
233 // Loop through multiple case clients
234 foreach ($clientList as $i => $sourceContactID) {
bb76ee5a 235 try {
a0fdfb65 236 $params = [
bb76ee5a
FG
237 'case_id' => $caseID,
238 'relationship_type_id' => $relTypeId,
239 "contact_id_$a" => $relContactID,
240 "contact_id_$b" => $sourceContactID,
a0fdfb65
MD
241 'sequential' => TRUE,
242 ];
243 // first check if there is any existing relationship present with same parameters.
244 // If yes then update the relationship by setting active and start date to current time
245 $relationship = civicrm_api3('Relationship', 'get', $params)['values'];
246 $params = array_merge(CRM_Utils_Array::value(0, $relationship, $params), [
bb76ee5a 247 'start_date' => 'now',
a0fdfb65
MD
248 'is_active' => TRUE,
249 'end_date' => '',
250 ]);
251 $result = civicrm_api3('relationship', 'create', $params);
bb76ee5a
FG
252 }
253 catch (CiviCRM_API3_Exception $e) {
254 $ret['is_error'] = 1;
255 $ret['error_message'] = $e->getMessage();
256 }
3b1c37fe
CW
257 // Save activity only for the primary (first) client
258 if ($i == 0 && empty($result['is_error'])) {
3e4eb9aa 259 CRM_Case_BAO_Case::createCaseRoleActivity($caseID, $result['id'], $relContactID, $sourceContactID);
c91df8b4 260 }
6a488035 261 }
3e4eb9aa
JP
262 if (!empty($_REQUEST['is_unit_test'])) {
263 return $ret;
264 }
6a488035 265
ecdef330 266 CRM_Utils_JSON::output($ret);
6a488035
TO
267 }
268
269 /**
fe482240 270 * Fetch the custom field help.
6a488035 271 */
00be9182 272 public static function customField() {
353ffa53 273 $fieldId = CRM_Utils_Type::escape($_REQUEST['id'], 'Integer');
be2fb01f
CW
274 $params = ['id' => $fieldId];
275 $returnProperties = ['help_pre', 'help_post'];
276 $values = [];
6a488035
TO
277
278 CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_CustomField', $params, $values, $returnProperties);
ecdef330 279 CRM_Utils_JSON::output($values);
6a488035
TO
280 }
281
00be9182 282 public static function groupTree() {
d42a224c 283 CRM_Utils_System::setHttpHeader('Content-Type', 'application/json');
6a488035
TO
284 $gids = CRM_Utils_Type::escape($_GET['gids'], 'String');
285 echo CRM_Contact_BAO_GroupNestingCache::json($gids);
286 CRM_Utils_System::civiExit();
287 }
288
6a488035 289 /**
fe482240 290 * Delete custom value.
6a488035 291 */
00be9182 292 public static function deleteCustomValue() {
d42a224c 293 CRM_Utils_System::setHttpHeader('Content-Type', 'text/plain');
6a488035
TO
294 $customValueID = CRM_Utils_Type::escape($_REQUEST['valueID'], 'Positive');
295 $customGroupID = CRM_Utils_Type::escape($_REQUEST['groupID'], 'Positive');
a3d827a7 296 $contactId = CRM_Utils_Request::retrieve('contactId', 'Positive');
6a488035 297 CRM_Core_BAO_CustomValue::deleteCustomValue($customValueID, $customGroupID);
a4cce21a 298 if ($contactId) {
7fa9167d 299 echo CRM_Contact_BAO_Contact::getCountComponent('custom_' . $customGroupID, $contactId);
6a488035
TO
300 }
301
2b68a50c 302 CRM_Contact_BAO_GroupContactCache::opportunisticCacheFlush();
6a488035
TO
303 CRM_Utils_System::civiExit();
304 }
305
6a488035 306 /**
fe482240 307 * check the CMS username.
ce80b209 308 */
69078420 309 public static function checkUserName() {
be2fb01f 310 $signer = new CRM_Utils_Signer(CRM_Core_Key::privateKey(), ['for', 'ts']);
a3d827a7
CW
311 $sig = CRM_Utils_Request::retrieve('sig', 'String');
312 $for = CRM_Utils_Request::retrieve('for', 'String');
272081ca
TO
313 if (
314 CRM_Utils_Time::getTimeRaw() > $_REQUEST['ts'] + self::CHECK_USERNAME_TTL
7fa9167d 315 || $for != 'civicrm/ajax/cmsuser'
316 || !$signer->validate($sig, $_REQUEST)
272081ca 317 ) {
be2fb01f 318 $user = ['name' => 'error'];
8be1a839 319 CRM_Utils_JSON::output($user);
272081ca
TO
320 }
321
6a488035 322 $config = CRM_Core_Config::singleton();
4c68cf7b 323 $username = trim(CRM_Utils_Array::value('cms_name', $_REQUEST));
6a488035 324
be2fb01f 325 $params = ['name' => $username];
6a488035 326
be2fb01f 327 $errors = [];
6a488035
TO
328 $config->userSystem->checkUserNameEmailExists($params, $errors);
329
330 if (isset($errors['cms_name']) || isset($errors['name'])) {
b44e3f84 331 //user name is not available
be2fb01f 332 $user = ['name' => 'no'];
8be1a839 333 CRM_Utils_JSON::output($user);
6a488035
TO
334 }
335 else {
336 //user name is available
be2fb01f 337 $user = ['name' => 'yes'];
8be1a839 338 CRM_Utils_JSON::output($user);
6a488035 339 }
8be1a839
TO
340
341 // Not reachable: JSON::output() above exits.
6a488035
TO
342 CRM_Utils_System::civiExit();
343 }
344
345 /**
fe482240 346 * Function to get email address of a contact.
6a488035 347 */
00be9182 348 public static function getContactEmail() {
a7488080 349 if (!empty($_REQUEST['contact_id'])) {
6a488035 350 $contactID = CRM_Utils_Type::escape($_REQUEST['contact_id'], 'Positive');
8c0ea1d7
TO
351 if (!CRM_Contact_BAO_Contact_Permission::allow($contactID, CRM_Core_Permission::EDIT)) {
352 return;
353 }
6a488035
TO
354 list($displayName,
355 $userEmail
353ffa53 356 ) = CRM_Contact_BAO_Contact_Location::getEmailDetails($contactID);
effdc2d9 357
d42a224c 358 CRM_Utils_System::setHttpHeader('Content-Type', 'text/plain');
6a488035
TO
359 if ($userEmail) {
360 echo $userEmail;
361 }
362 }
363 else {
364 $noemail = CRM_Utils_Array::value('noemail', $_GET);
365 $queryString = NULL;
a4cce21a
JM
366 $name = CRM_Utils_Array::value('name', $_GET);
367 if ($name) {
6a488035
TO
368 $name = CRM_Utils_Type::escape($name, 'String');
369 if ($noemail) {
370 $queryString = " cc.sort_name LIKE '%$name%'";
371 }
372 else {
373 $queryString = " ( cc.sort_name LIKE '%$name%' OR ce.email LIKE '%$name%' ) ";
374 }
375 }
a4cce21a 376 else {
d75f2f47
EM
377 $cid = CRM_Utils_Array::value('cid', $_GET);
378 if ($cid) {
b44e3f84 379 //check cid for integer
a4cce21a
JM
380 $contIDS = explode(',', $cid);
381 foreach ($contIDS as $contID) {
382 CRM_Utils_Type::escape($contID, 'Integer');
383 }
384 $queryString = " cc.id IN ( $cid )";
d75f2f47 385 }
6a488035
TO
386 }
387
388 if ($queryString) {
be2fb01f 389 $result = [];
6a488035 390 $offset = CRM_Utils_Array::value('offset', $_GET, 0);
89595c92 391 $rowCount = Civi::settings()->get('search_autocomplete_count');
6a488035 392
bf00d1b6 393 $offset = CRM_Utils_Type::escape($offset, 'Int');
bf00d1b6 394
6a488035
TO
395 // add acl clause here
396 list($aclFrom, $aclWhere) = CRM_Contact_BAO_Contact_Permission::cacheClause('cc');
397 if ($aclWhere) {
398 $aclWhere = " AND $aclWhere";
399 }
400 if ($noemail) {
401 $query = "
402SELECT sort_name name, cc.id
403FROM civicrm_contact cc
404 {$aclFrom}
405WHERE cc.is_deceased = 0 AND {$queryString}
406 {$aclWhere}
407LIMIT {$offset}, {$rowCount}
408";
409
410 // send query to hook to be modified if needed
411 CRM_Utils_Hook::contactListQuery($query,
412 $name,
edc80cda 413 CRM_Utils_Request::retrieve('context', 'Alphanumeric'),
a3d827a7 414 CRM_Utils_Request::retrieve('cid', 'Positive')
6a488035
TO
415 );
416
417 $dao = CRM_Core_DAO::executeQuery($query);
418 while ($dao->fetch()) {
be2fb01f 419 $result[] = [
6a488035 420 'id' => $dao->id,
cac1236c 421 'text' => $dao->name,
be2fb01f 422 ];
6a488035
TO
423 }
424 }
425 else {
426 $query = "
427SELECT sort_name name, ce.email, cc.id
428FROM civicrm_email ce INNER JOIN civicrm_contact cc ON cc.id = ce.contact_id
429 {$aclFrom}
430WHERE ce.on_hold = 0 AND cc.is_deceased = 0 AND cc.do_not_email = 0 AND {$queryString}
431 {$aclWhere}
432LIMIT {$offset}, {$rowCount}
433";
434
435 // send query to hook to be modified if needed
436 CRM_Utils_Hook::contactListQuery($query,
437 $name,
edc80cda 438 CRM_Utils_Request::retrieve('context', 'Alphanumeric'),
a3d827a7 439 CRM_Utils_Request::retrieve('cid', 'Positive')
6a488035
TO
440 );
441
6a488035
TO
442 $dao = CRM_Core_DAO::executeQuery($query);
443
444 while ($dao->fetch()) {
ce80b209 445 //working here
be2fb01f 446 $result[] = [
cac1236c 447 'text' => '"' . $dao->name . '" <' . $dao->email . '>',
6a488035 448 'id' => (CRM_Utils_Array::value('id', $_GET)) ? "{$dao->id}::{$dao->email}" : '"' . $dao->name . '" <' . $dao->email . '>',
be2fb01f 449 ];
6a488035
TO
450 }
451 }
aa8ff347 452 CRM_Utils_JSON::output($result);
6a488035
TO
453 }
454 }
455 CRM_Utils_System::civiExit();
456 }
457
00be9182 458 public static function getContactPhone() {
6a488035
TO
459
460 $queryString = NULL;
3ae9c7d6 461 $sqlParmas = [];
6a488035
TO
462 //check for mobile type
463 $phoneTypes = CRM_Core_OptionGroup::values('phone_type', TRUE, FALSE, FALSE, NULL, 'name');
464 $mobileType = CRM_Utils_Array::value('Mobile', $phoneTypes);
465
3ae9c7d6 466 $name = CRM_Utils_Request::retrieveValue('name', 'String', NULL, FALSE, 'GET');
a4cce21a 467 if ($name) {
3ae9c7d6
SL
468 $key = (int) count(array_keys($sqlParmas)) + 1;
469 $queryString = " ( cc.sort_name LIKE %{$key} OR cp.phone LIKE %{$key} ) ";
470 $sqlParams[$key] = ['%' . $name . '%', 'String'];
6a488035 471 }
a4cce21a 472 else {
3ae9c7d6 473 $cid = CRM_Utils_Request::retrieveValue('cid', 'CommaSeparatedIntegers', NULL, FALSE, 'GET');
d75f2f47 474 if ($cid) {
a4cce21a 475 $queryString = " cc.id IN ( $cid )";
6a488035 476 }
6a488035
TO
477 }
478
479 if ($queryString) {
be2fb01f 480 $result = [];
3ae9c7d6
SL
481 $offset = (int) CRM_Utils_Request::retrieveValue('offset', 'Integer', 0, FALSE, 'GET');
482 $rowCount = (int) CRM_Utils_Request::retrieveValue('rowcount', 'Integer', 20, FALSE, 'GET');
bf00d1b6 483
6a488035
TO
484 // add acl clause here
485 list($aclFrom, $aclWhere) = CRM_Contact_BAO_Contact_Permission::cacheClause('cc');
486 if ($aclWhere) {
487 $aclWhere = " AND $aclWhere";
488 }
489
490 $query = "
491SELECT sort_name name, cp.phone, cc.id
492FROM civicrm_phone cp INNER JOIN civicrm_contact cc ON cc.id = cp.contact_id
493 {$aclFrom}
494WHERE cc.is_deceased = 0 AND cc.do_not_sms = 0 AND cp.phone_type_id = {$mobileType} AND {$queryString}
495 {$aclWhere}
496LIMIT {$offset}, {$rowCount}
497";
498
499 // send query to hook to be modified if needed
500 CRM_Utils_Hook::contactListQuery($query,
501 $name,
edc80cda 502 CRM_Utils_Request::retrieve('context', 'Alphanumeric'),
a3d827a7 503 CRM_Utils_Request::retrieve('cid', 'Positive')
6a488035
TO
504 );
505
3ae9c7d6 506 $dao = CRM_Core_DAO::executeQuery($query, $sqlParams);
6a488035
TO
507
508 while ($dao->fetch()) {
be2fb01f 509 $result[] = [
b792e485 510 'text' => '"' . $dao->name . '" (' . $dao->phone . ')',
6a488035 511 'id' => (CRM_Utils_Array::value('id', $_GET)) ? "{$dao->id}::{$dao->phone}" : '"' . $dao->name . '" <' . $dao->phone . '>',
be2fb01f 512 ];
6a488035 513 }
8be1a839 514 CRM_Utils_JSON::output($result);
6a488035
TO
515 }
516 CRM_Utils_System::civiExit();
517 }
518
00be9182 519 public static function buildSubTypes() {
a3d827a7 520 $parent = CRM_Utils_Request::retrieve('parentId', 'Positive');
6a488035
TO
521
522 switch ($parent) {
523 case 1:
524 $contactType = 'Individual';
525 break;
526
527 case 2:
528 $contactType = 'Household';
529 break;
530
531 case 4:
532 $contactType = 'Organization';
533 break;
534 }
535
536 $subTypes = CRM_Contact_BAO_ContactType::subTypePairs($contactType, FALSE, NULL);
537 asort($subTypes);
ecdef330 538 CRM_Utils_JSON::output($subTypes);
6a488035
TO
539 }
540
00be9182 541 public static function buildDedupeRules() {
a3d827a7 542 $parent = CRM_Utils_Request::retrieve('parentId', 'Positive');
6a488035
TO
543
544 switch ($parent) {
545 case 1:
546 $contactType = 'Individual';
547 break;
548
549 case 2:
550 $contactType = 'Household';
551 break;
552
553 case 4:
554 $contactType = 'Organization';
555 break;
556 }
557
558 $dedupeRules = CRM_Dedupe_BAO_RuleGroup::getByType($contactType);
559
ecdef330 560 CRM_Utils_JSON::output($dedupeRules);
6a488035
TO
561 }
562
563 /**
fe482240 564 * Function used for CiviCRM dashboard operations.
6a488035 565 */
00be9182 566 public static function dashboard() {
ce2cc43e 567 switch ($_REQUEST['op']) {
6a488035
TO
568 case 'save_columns':
569 CRM_Core_BAO_Dashboard::saveDashletChanges($_REQUEST['columns']);
ce2cc43e
CW
570 break;
571
6a488035
TO
572 case 'delete_dashlet':
573 $dashletID = CRM_Utils_Type::escape($_REQUEST['dashlet_id'], 'Positive');
574 CRM_Core_BAO_Dashboard::deleteDashlet($dashletID);
6a488035
TO
575 }
576
ce2cc43e 577 CRM_Utils_System::civiExit();
6a488035
TO
578 }
579
580 /**
fe482240 581 * Retrieve signature based on email id.
6a488035 582 */
00be9182 583 public static function getSignature() {
6a488035 584 $emailID = CRM_Utils_Type::escape($_REQUEST['emailID'], 'Positive');
353ffa53
TO
585 $query = "SELECT signature_text, signature_html FROM civicrm_email WHERE id = {$emailID}";
586 $dao = CRM_Core_DAO::executeQuery($query);
6a488035 587
be2fb01f 588 $signatures = [];
6a488035 589 while ($dao->fetch()) {
be2fb01f 590 $signatures = [
6a488035
TO
591 'signature_text' => $dao->signature_text,
592 'signature_html' => $dao->signature_html,
be2fb01f 593 ];
6a488035
TO
594 }
595
ecdef330 596 CRM_Utils_JSON::output($signatures);
6a488035
TO
597 }
598
599 /**
100fef9d 600 * Process dupes.
6a488035 601 */
00be9182 602 public static function processDupes() {
6a488035 603 $oper = CRM_Utils_Type::escape($_REQUEST['op'], 'String');
353ffa53
TO
604 $cid = CRM_Utils_Type::escape($_REQUEST['cid'], 'Positive');
605 $oid = CRM_Utils_Type::escape($_REQUEST['oid'], 'Positive');
6a488035
TO
606
607 if (!$oper || !$cid || !$oid) {
608 return;
609 }
610
2d1fefa0 611 $status = self::markNonDuplicates($cid, $oid, $oper);
6a488035 612
be2fb01f 613 CRM_Utils_JSON::output(['status' => ($status) ? $oper : $status]);
6a488035
TO
614 }
615
183ec330 616 /**
617 * Retrieve list of duplicate pairs from cache table.
618 */
00be9182 619 public static function getDedupes() {
63ef778e 620 $offset = isset($_REQUEST['start']) ? CRM_Utils_Type::escape($_REQUEST['start'], 'Integer') : 0;
621 $rowCount = isset($_REQUEST['length']) ? CRM_Utils_Type::escape($_REQUEST['length'], 'Integer') : 25;
6a488035 622
dc6285d5 623 $gid = CRM_Utils_Request::retrieve('gid', 'Positive');
624 $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive');
997a03fe 625 $limit = CRM_Utils_Request::retrieveValue('limit', 'Positive', 0);
9f54f049 626 $null = NULL;
627 $criteria = CRM_Utils_Request::retrieve('criteria', 'Json', $null, FALSE, '{}');
bb22928b 628 $selected = CRM_Utils_Request::retrieveValue('selected', 'Boolean');
63ef778e 629 if ($rowCount < 0) {
630 $rowCount = 0;
631 }
6a488035 632
1f51ef4e 633 $whereClause = $orderByClause = '';
997a03fe 634 $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid, json_decode($criteria, TRUE), TRUE, $limit);
9f54f049 635
69078420 636 $searchRows = [];
6a488035 637
ed92673b 638 $searchParams = self::getSearchOptionsFromRequest();
be2fb01f 639 $queryParams = [];
ed92673b 640
63ef778e 641 $join = '';
be2fb01f 642 $where = [];
579ea9bc 643
ed92673b 644 $isOrQuery = self::isOrQuery();
645
646 $nextParamKey = 3;
be2fb01f 647 $mappings = [
e67dcaf8 648 'dst' => 'cc1.display_name',
649 'src' => 'cc2.display_name',
650 'dst_email' => 'ce1.email',
651 'src_email' => 'ce2.email',
652 'dst_postcode' => 'ca1.postal_code',
653 'src_postcode' => 'ca2.postal_code',
654 'dst_street' => 'ca1.street',
655 'src_street' => 'ca2.street',
be2fb01f 656 ];
ed92673b 657
658 foreach ($mappings as $key => $dbName) {
659 if (!empty($searchParams[$key])) {
12af7add 660 // CRM-18694.
661 $wildcard = strstr($key, 'postcode') ? '' : '%';
be2fb01f 662 $queryParams[$nextParamKey] = [$wildcard . $searchParams[$key] . '%', 'String'];
ed92673b 663 $where[] = $dbName . " LIKE %{$nextParamKey} ";
664 $nextParamKey++;
665 }
63ef778e 666 }
ed92673b 667
668 if ($isOrQuery) {
69078420 669 $whereClause = ' ( ' . implode(' OR ', $where) . ' ) ';
63ef778e 670 }
671 else {
672 if (!empty($where)) {
69078420 673 $whereClause = implode(' AND ', $where);
63ef778e 674 }
f931b74c 675 }
63ef778e 676 $whereClause .= $whereClause ? ' AND de.id IS NULL' : ' de.id IS NULL';
6a488035 677
63ef778e 678 if ($selected) {
679 $whereClause .= ' AND pn.is_selected = 1';
680 }
2988f5c7 681 $join .= CRM_Dedupe_Merger::getJoinOnDedupeTable();
63ef778e 682
be2fb01f 683 $select = [
e67dcaf8 684 'cc1.contact_type' => 'dst_contact_type',
685 'cc1.display_name' => 'dst_display_name',
686 'cc1.contact_sub_type' => 'dst_contact_sub_type',
687 'cc2.contact_type' => 'src_contact_type',
688 'cc2.display_name' => 'src_display_name',
689 'cc2.contact_sub_type' => 'src_contact_sub_type',
690 'ce1.email' => 'dst_email',
691 'ce2.email' => 'src_email',
692 'ca1.postal_code' => 'dst_postcode',
693 'ca2.postal_code' => 'src_postcode',
694 'ca1.street_address' => 'dst_street',
695 'ca2.street_address' => 'src_street',
be2fb01f 696 ];
63ef778e 697
f931b74c 698 if ($select) {
63ef778e 699 $join .= " INNER JOIN civicrm_contact cc1 ON cc1.id = pn.entity_id1";
700 $join .= " INNER JOIN civicrm_contact cc2 ON cc2.id = pn.entity_id2";
701 $join .= " LEFT JOIN civicrm_email ce1 ON (ce1.contact_id = pn.entity_id1 AND ce1.is_primary = 1 )";
702 $join .= " LEFT JOIN civicrm_email ce2 ON (ce2.contact_id = pn.entity_id2 AND ce2.is_primary = 1 )";
703 $join .= " LEFT JOIN civicrm_address ca1 ON (ca1.contact_id = pn.entity_id1 AND ca1.is_primary = 1 )";
704 $join .= " LEFT JOIN civicrm_address ca2 ON (ca2.contact_id = pn.entity_id2 AND ca2.is_primary = 1 )";
705 }
ed92673b 706 $iTotal = CRM_Core_BAO_PrevNextCache::getCount($cacheKeyString, $join, $whereClause, '=', $queryParams);
1f51ef4e 707 if (!empty($_REQUEST['order'])) {
708 foreach ($_REQUEST['order'] as $orderInfo) {
709 if (!empty($orderInfo['column'])) {
710 $orderColumnNumber = $orderInfo['column'];
2c032aca 711 $dir = CRM_Utils_Type::escape($orderInfo['dir'], 'MysqlOrderByDirection', FALSE);
1f51ef4e 712 }
63ef778e 713 }
1f51ef4e 714 $columnDetails = CRM_Utils_Array::value($orderColumnNumber, $_REQUEST['columns']);
63ef778e 715 }
f931b74c 716 if (!empty($columnDetails)) {
63ef778e 717 switch ($columnDetails['data']) {
f931b74c 718 case 'src':
e67dcaf8 719 $orderByClause = " ORDER BY cc2.display_name {$dir}";
f931b74c 720 break;
721
722 case 'src_email':
e67dcaf8 723 $orderByClause = " ORDER BY ce2.email {$dir}";
f931b74c 724 break;
725
726 case 'src_street':
e67dcaf8 727 $orderByClause = " ORDER BY ca2.street_address {$dir}";
f931b74c 728 break;
729
730 case 'src_postcode':
e67dcaf8 731 $orderByClause = " ORDER BY ca2.postal_code {$dir}";
f931b74c 732 break;
733
734 case 'dst':
e67dcaf8 735 $orderByClause = " ORDER BY cc1.display_name {$dir}";
f931b74c 736 break;
737
738 case 'dst_email':
e67dcaf8 739 $orderByClause = " ORDER BY ce1.email {$dir}";
f931b74c 740 break;
741
742 case 'dst_street':
e67dcaf8 743 $orderByClause = " ORDER BY ca1.street_address {$dir}";
f931b74c 744 break;
745
746 case 'dst_postcode':
e67dcaf8 747 $orderByClause = " ORDER BY ca1.postal_code {$dir}";
f931b74c 748 break;
749
750 default:
063ffcb7 751 $orderByClause = " ORDER BY cc1.display_name ASC";
f931b74c 752 break;
63ef778e 753 }
754 }
6a488035 755
ed92673b 756 $dupePairs = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, $join, $whereClause, $offset, $rowCount, $select, $orderByClause, TRUE, $queryParams);
63ef778e 757 $iFilteredTotal = CRM_Core_DAO::singleValueQuery("SELECT FOUND_ROWS()");
6a488035 758
63ef778e 759 $count = 0;
760 foreach ($dupePairs as $key => $pairInfo) {
e67dcaf8 761 $pair = $pairInfo['data'];
63ef778e 762 $srcContactSubType = CRM_Utils_Array::value('src_contact_sub_type', $pairInfo);
763 $dstContactSubType = CRM_Utils_Array::value('dst_contact_sub_type', $pairInfo);
764 $srcTypeImage = CRM_Contact_BAO_Contact_Utils::getImage($srcContactSubType ?
765 $srcContactSubType : $pairInfo['src_contact_type'],
766 FALSE,
e67dcaf8 767 $pairInfo['entity_id2']
63ef778e 768 );
769 $dstTypeImage = CRM_Contact_BAO_Contact_Utils::getImage($dstContactSubType ?
770 $dstContactSubType : $pairInfo['dst_contact_type'],
771 FALSE,
e67dcaf8 772 $pairInfo['entity_id1']
63ef778e 773 );
6a488035 774
63ef778e 775 $searchRows[$count]['is_selected'] = $pairInfo['is_selected'];
776 $searchRows[$count]['is_selected_input'] = "<input type='checkbox' class='crm-dedupe-select' name='pnid_{$pairInfo['prevnext_id']}' value='{$pairInfo['is_selected']}' onclick='toggleDedupeSelect(this)'>";
777 $searchRows[$count]['src_image'] = $srcTypeImage;
e67dcaf8 778 $searchRows[$count]['src'] = CRM_Utils_System::href($pair['srcName'], 'civicrm/contact/view', "reset=1&cid={$pairInfo['entity_id2']}");
63ef778e 779 $searchRows[$count]['src_email'] = CRM_Utils_Array::value('src_email', $pairInfo);
780 $searchRows[$count]['src_street'] = CRM_Utils_Array::value('src_street', $pairInfo);
781 $searchRows[$count]['src_postcode'] = CRM_Utils_Array::value('src_postcode', $pairInfo);
782 $searchRows[$count]['dst_image'] = $dstTypeImage;
e67dcaf8 783 $searchRows[$count]['dst'] = CRM_Utils_System::href($pair['dstName'], 'civicrm/contact/view', "reset=1&cid={$pairInfo['entity_id1']}");
63ef778e 784 $searchRows[$count]['dst_email'] = CRM_Utils_Array::value('dst_email', $pairInfo);
785 $searchRows[$count]['dst_street'] = CRM_Utils_Array::value('dst_street', $pairInfo);
786 $searchRows[$count]['dst_postcode'] = CRM_Utils_Array::value('dst_postcode', $pairInfo);
da3afd4a 787 $searchRows[$count]['conflicts'] = str_replace("',", "',<br/>", CRM_Utils_Array::value('conflicts', $pair));
63ef778e 788 $searchRows[$count]['weight'] = CRM_Utils_Array::value('weight', $pair);
789
fd630ef9 790 if (!empty($pairInfo['data']['canMerge'])) {
c0cc2ad4 791 $mergeParams = [
792 'reset' => 1,
69078420
SL
793 'cid' => $pairInfo['entity_id1'],
794 'oid' => $pairInfo['entity_id2'],
795 'action' => 'update',
796 'rgid' => $rgid,
797 'criteria' => $criteria,
798 'limit' => CRM_Utils_Request::retrieve('limit', 'Integer'),
799 ];
6a488035 800 if ($gid) {
c0cc2ad4 801 $mergeParams['gid'] = $gid;
6a488035
TO
802 }
803
fd630ef9 804 $searchRows[$count]['actions'] = "<a class='crm-dedupe-flip' href='#' data-pnid={$pairInfo['prevnext_id']}>" . ts('flip') . "</a>&nbsp;|&nbsp;";
da3afd4a 805 $searchRows[$count]['actions'] .= CRM_Utils_System::href(ts('merge'), 'civicrm/contact/merge', $mergeParams);
fd630ef9 806 $searchRows[$count]['actions'] .= "&nbsp;|&nbsp;<a id='notDuplicate' href='#' onClick=\"processDupes( {$pairInfo['entity_id1']}, {$pairInfo['entity_id2']}, 'dupe-nondupe', 'dupe-listing'); return false;\">" . ts('not a duplicate') . "</a>";
6a488035
TO
807 }
808 else {
63ef778e 809 $searchRows[$count]['actions'] = '<em>' . ts('Insufficient access rights - cannot merge') . '</em>';
6a488035 810 }
63ef778e 811 $count++;
6a488035
TO
812 }
813
be2fb01f 814 $dupePairs = [
22b232f3 815 'data' => $searchRows,
816 'recordsTotal' => $iTotal,
817 'recordsFiltered' => $iFilteredTotal,
be2fb01f 818 ];
1f51ef4e 819 if (!empty($_REQUEST['is_unit_test'])) {
820 return $dupePairs;
821 }
22b232f3 822 CRM_Utils_JSON::output($dupePairs);
6a488035
TO
823 }
824
ed92673b 825 /**
826 * Get the searchable options from the request.
827 *
828 * @return array
829 */
830 public static function getSearchOptionsFromRequest() {
be2fb01f 831 $searchParams = [];
ed92673b 832 $searchData = CRM_Utils_Array::value('search', $_REQUEST);
833 $searchData['value'] = CRM_Utils_Type::escape($searchData['value'], 'String');
be2fb01f 834 $selectorElements = [
ed92673b 835 'is_selected',
836 'is_selected_input',
837 'src_image',
838 'src',
839 'src_email',
840 'src_street',
841 'src_postcode',
842 'dst_image',
843 'dst',
844 'dst_email',
845 'dst_street',
846 'dst_postcode',
847 'conflicts',
848 'weight',
849 'actions',
be2fb01f 850 ];
ed92673b 851 $columns = $_REQUEST['columns'];
852
853 foreach ($columns as $column) {
854 if (!empty($column['search']['value']) && in_array($column['data'], $selectorElements)) {
855 $searchParams[$column['data']] = CRM_Utils_Type::escape($column['search']['value'], 'String');
856 }
857 elseif (!empty($searchData['value'])) {
858 $searchParams[$column['data']] = $searchData['value'];
859 }
860 }
861 return $searchParams;
862 }
863
864 /**
865 * Is the query an OR query.
866 *
867 * If a generic search value is passed in - ie. $_REQUEST['search']['value'] = 'abc'
868 * then all fields are searched for this.
869 *
870 * It is unclear if there is any code that still passes this in or whether is is just legacy. It
871 * could cause a server-killing query on a large site so it probably is NOT in use if we haven't
872 * had complaints.
873 *
874 * @return bool
875 */
876 public static function isOrQuery() {
877 $searchData = CRM_Utils_Array::value('search', $_REQUEST);
878 return !empty($searchData['value']);
879 }
880
2d1fefa0 881 /**
882 * Mark not duplicates.
883 *
884 * Note this function would sensibly be replaced by an api-call but extracting here to add a test first.
885 *
886 * I would have like to make it private but test class accesses it & it doesn't warrant being a BAO class
887 * as it should feel very endangered.
888 *
889 * @param int $cid
890 * @param int $oid
041ecc95 891 * @param "dupe-nondupe|nondupe-dupe" $oper
2d1fefa0 892 *
893 * @return \CRM_Core_DAO|mixed|null
894 */
895 public static function markNonDuplicates($cid, $oid, $oper) {
ac2751b3 896 if ($oper == 'dupe-nondupe') {
897 try {
898 civicrm_api3('Exception', 'create', ['contact_id1' => $cid, 'contact_id2' => $oid]);
899 return TRUE;
900 }
901 catch (CiviCRM_API3_Exception $e) {
902 return FALSE;
903 }
904 }
905
2d1fefa0 906 $exception = new CRM_Dedupe_DAO_Exception();
907 $exception->contact_id1 = $cid;
908 $exception->contact_id2 = $oid;
909 //make sure contact2 > contact1.
910 if ($cid > $oid) {
911 $exception->contact_id1 = $oid;
912 $exception->contact_id2 = $cid;
913 }
914 $exception->find(TRUE);
915 $status = NULL;
ac2751b3 916
2d1fefa0 917 if ($oper == 'nondupe-dupe') {
918 $status = $exception->delete();
919 }
920 return $status;
921 }
922
6a488035 923 /**
fe482240 924 * Retrieve a PDF Page Format for the PDF Letter form.
6a488035 925 */
00be9182 926 public function pdfFormat() {
6a488035
TO
927 $formatId = CRM_Utils_Type::escape($_REQUEST['formatId'], 'Integer');
928
929 $pdfFormat = CRM_Core_BAO_PdfFormat::getById($formatId);
930
ecdef330 931 CRM_Utils_JSON::output($pdfFormat);
6a488035
TO
932 }
933
934 /**
fe482240 935 * Retrieve Paper Size dimensions.
6a488035 936 */
00be9182 937 public static function paperSize() {
6a488035
TO
938 $paperSizeName = CRM_Utils_Type::escape($_REQUEST['paperSizeName'], 'String');
939
940 $paperSize = CRM_Core_BAO_PaperSize::getByName($paperSizeName);
941
ecdef330 942 CRM_Utils_JSON::output($paperSize);
6a488035
TO
943 }
944
183ec330 945 /**
946 * Swap contacts in a dupe pair i.e main with duplicate contact.
ea3ddccf 947 *
948 * @param int $prevNextId
183ec330 949 */
f931b74c 950 public static function flipDupePairs($prevNextId = NULL) {
fd630ef9 951 if (!$prevNextId) {
808c05a9 952 // @todo figure out if this is always POST & specify that rather than inexact GET
6d13d1c4
ML
953
954 // We cannot use CRM_Utils_Request::retrieve() because it might be an array.
955 // It later gets validated in escapeAll below.
956 $prevNextId = $_REQUEST['pnid'];
fd630ef9 957 }
808c05a9 958
959 $onlySelected = FALSE;
fd630ef9 960 if (is_array($prevNextId) && !CRM_Utils_Array::crmIsEmptyArray($prevNextId)) {
808c05a9 961 $onlySelected = TRUE;
fd630ef9 962 }
808c05a9 963 $prevNextId = CRM_Utils_Type::escapeAll((array) $prevNextId, 'Positive');
964 CRM_Core_BAO_PrevNextCache::flipPair($prevNextId, $onlySelected);
558cd7c7 965 CRM_Utils_System::civiExit();
fd630ef9 966 }
967
aeb97cc1
CW
968 /**
969 * Used to store selected contacts across multiple pages in advanced search.
970 */
00be9182 971 public static function selectUnselectContacts() {
353ffa53
TO
972 $name = CRM_Utils_Array::value('name', $_REQUEST);
973 $cacheKey = CRM_Utils_Array::value('qfKey', $_REQUEST);
974 $state = CRM_Utils_Array::value('state', $_REQUEST, 'checked');
6a488035
TO
975 $variableType = CRM_Utils_Array::value('variableType', $_REQUEST, 'single');
976
977 $actionToPerform = CRM_Utils_Array::value('action', $_REQUEST, 'select');
978
979 if ($variableType == 'multiple') {
980 // action post value only works with multiple type variable
981 if ($name) {
982 //multiple names like mark_x_1-mark_x_2 where 1,2 are cids
983 $elements = explode('-', $name);
984 foreach ($elements as $key => $element) {
985 $elements[$key] = self::_convertToId($element);
986 }
91209206 987 CRM_Utils_Type::escapeAll($elements, 'Integer');
0b8038a6 988 Civi::service('prevnext')->markSelection($cacheKey, $actionToPerform, $elements);
6a488035
TO
989 }
990 else {
0b8038a6 991 Civi::service('prevnext')->markSelection($cacheKey, $actionToPerform);
6a488035
TO
992 }
993 }
994 elseif ($variableType == 'single') {
995 $cId = self::_convertToId($name);
91209206 996 CRM_Utils_Type::escape($cId, 'Integer');
6a488035 997 $action = ($state == 'checked') ? 'select' : 'unselect';
0b8038a6 998 Civi::service('prevnext')->markSelection($cacheKey, $action, $cId);
6a488035 999 }
b7994703 1000 $contactIds = Civi::service('prevnext')->getSelection($cacheKey);
6a488035
TO
1001 $countSelectionCids = count($contactIds[$cacheKey]);
1002
be2fb01f 1003 $arrRet = ['getCount' => $countSelectionCids];
ecdef330 1004 CRM_Utils_JSON::output($arrRet);
6a488035
TO
1005 }
1006
4319322b 1007 /**
100fef9d 1008 * @param string $name
4319322b
EM
1009 *
1010 * @return string
1011 */
00be9182 1012 public static function _convertToId($name) {
6a488035
TO
1013 if (substr($name, 0, CRM_Core_Form::CB_PREFIX_LEN) == CRM_Core_Form::CB_PREFIX) {
1014 $cId = substr($name, CRM_Core_Form::CB_PREFIX_LEN);
1015 }
1016 return $cId;
1017 }
1018
00be9182 1019 public static function getAddressDisplay() {
a3d827a7 1020 $contactId = CRM_Utils_Request::retrieve('contact_id', 'Positive');
6a488035
TO
1021 if (!$contactId) {
1022 $addressVal["error_message"] = "no contact id found";
1023 }
1024 else {
be2fb01f 1025 $entityBlock = [
408b79bf 1026 'contact_id' => $contactId,
1027 'entity_id' => $contactId,
be2fb01f 1028 ];
6a488035
TO
1029 $addressVal = CRM_Core_BAO_Address::getValues($entityBlock);
1030 }
1031
ecdef330 1032 CRM_Utils_JSON::output($addressVal);
6a488035 1033 }
40458f6c 1034
183ec330 1035 /**
1036 * Mark dupe pairs as selected from un-selected state or vice-versa, in dupe cache table.
1037 */
f931b74c 1038 public static function toggleDedupeSelect() {
63ef778e 1039 $pnid = $_REQUEST['pnid'];
1040 $isSelected = CRM_Utils_Type::escape($_REQUEST['is_selected'], 'Boolean');
9d2f6d53 1041 $cacheKeyString = CRM_Utils_Request::retrieve('cacheKey', 'Alphanumeric', $null, FALSE);
63ef778e 1042
be2fb01f
CW
1043 $params = [
1044 1 => [$isSelected, 'Boolean'],
69078420
SL
1045 // using % to address rows with conflicts as well
1046 3 => ["$cacheKeyString%", 'String'],
be2fb01f 1047 ];
63ef778e 1048
1049 //check pnid is_array or integer
1050 $whereClause = NULL;
1051 if (is_array($pnid) && !CRM_Utils_Array::crmIsEmptyArray($pnid)) {
13c42e60 1052 CRM_Utils_Type::escapeAll($pnid, 'Positive');
63ef778e 1053 $pnid = implode(', ', $pnid);
63ef778e 1054 $whereClause = " id IN ( {$pnid} ) ";
1055 }
1056 else {
1057 $pnid = CRM_Utils_Type::escape($pnid, 'Integer');
1058 $whereClause = " id = %2";
be2fb01f 1059 $params[2] = [$pnid, 'Integer'];
63ef778e 1060 }
1061
783b4b21 1062 $sql = "UPDATE civicrm_prevnext_cache SET is_selected = %1 WHERE {$whereClause} AND cachekey LIKE %3";
63ef778e 1063 CRM_Core_DAO::executeQuery($sql, $params);
1064
1065 CRM_Utils_System::civiExit();
1066 }
1067
40458f6c 1068 /**
fe482240 1069 * Retrieve contact relationships.
40458f6c 1070 */
1071 public static function getContactRelationships() {
1072 $contactID = CRM_Utils_Type::escape($_GET['cid'], 'Integer');
edc80cda 1073 $context = CRM_Utils_Request::retrieve('context', 'Alphanumeric');
7d12de7f 1074 $relationship_type_id = CRM_Utils_Type::escape(CRM_Utils_Array::value('relationship_type_id', $_GET), 'Integer', FALSE);
40458f6c 1075
b0266403
CW
1076 if (!CRM_Contact_BAO_Contact_Permission::allow($contactID)) {
1077 return CRM_Utils_System::permissionDenied();
1078 }
1079
00f11506 1080 $params = CRM_Core_Page_AJAX::defaultSortAndPagerParams();
40458f6c 1081
1082 $params['contact_id'] = $contactID;
1083 $params['context'] = $context;
4c5f31d0 1084 if ($relationship_type_id) {
cdee9432
TM
1085 $params['relationship_type_id'] = $relationship_type_id;
1086 }
40458f6c 1087
1088 // get the contact relationships
1089 $relationships = CRM_Contact_BAO_Relationship::getContactRelationshipSelector($params);
1090
7d12de7f 1091 CRM_Utils_JSON::output($relationships);
40458f6c 1092 }
96025800 1093
6a488035 1094}