CRM-21849: Add getoptions spec params for relationship_type_id
[civicrm-core.git] / CRM / Contact / BAO / Relationship.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
7e9e8871 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
8c9251b3 6 | Copyright CiviCRM LLC (c) 2004-2018 |
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
bfa4da96 29 * Class CRM_Contact_BAO_Relationship.
6a488035
TO
30 */
31class CRM_Contact_BAO_Relationship extends CRM_Contact_DAO_Relationship {
32
33 /**
fe482240 34 * Various constants to indicate different type of relationships.
6a488035
TO
35 *
36 * @var int
37 */
a4dc03f7 38 const ALL = 0, PAST = 1, DISABLED = 2, CURRENT = 4, INACTIVE = 8;
6a488035 39
7ecf6275 40 /**
d49c2966 41 * Create function - use the API instead.
bfa4da96 42 *
2da59b29 43 * Note that the previous create function has been renamed 'legacyCreateMultiple'
7ecf6275 44 * and this is new in 4.6
2da59b29 45 * All existing calls have been changed to legacyCreateMultiple except the api call - however, it is recommended
bfa4da96
EM
46 * that you call that as the end to end testing here is based on the api & refactoring may still be done.
47 *
16b10e64 48 * @param array $params
bfa4da96 49 *
7ecf6275
EM
50 * @return \CRM_Contact_BAO_Relationship
51 * @throws \CRM_Core_Exception
52 */
53 public static function create(&$params) {
609d8c32 54
4f9f6ede 55 $extendedParams = self::loadExistingRelationshipDetails($params);
609d8c32
TM
56 // When id is specified we always wan't to update, so we don't need to
57 // check for duplicate relations.
4f9f6ede 58 if (!isset($params['id']) && self::checkDuplicateRelationship($extendedParams, $extendedParams['contact_id_a'], $extendedParams['contact_id_b'], CRM_Utils_Array::value('id', $extendedParams, 0))) {
7ecf6275
EM
59 throw new CRM_Core_Exception('Duplicate Relationship');
60 }
4f9f6ede 61 $params = $extendedParams;
7ecf6275 62 if (self::checkValidRelationship($params, $params, 0)) {
936e43d6 63 throw new CRM_Core_Exception('Invalid Relationship');
7ecf6275
EM
64 }
65 $relationship = self::add($params);
936e43d6 66 if (!empty($params['contact_id_a'])) {
04ad3598
EM
67 $ids = array(
68 'contactTarget' => $relationship->contact_id_b,
69 'contact' => $params['contact_id_a'],
70 );
6c25ede2 71
690c56c3 72 //CRM-16087 removed additional call to function relatedMemberships which is already called by disableEnableRelationship
7a44a255 73 //resulting in membership being created twice
6946fcbf 74 if (array_key_exists('is_active', $params) && empty($params['is_active'])) {
75 $action = CRM_Core_Action::DISABLE;
76 $active = FALSE;
77 }
78 else {
79 $action = CRM_Core_Action::ENABLE;
80 $active = TRUE;
81 }
91244f1d 82 $id = empty($params['id']) ? $relationship->id : $params['id'];
83 self::disableEnableRelationship($id, $action, $params, $ids, $active);
6c25ede2 84 }
04ad3598 85
aeacb9a9
MM
86 if (empty($params['skipRecentView'])) {
87 self::addRecent($params, $relationship);
88 }
89
7ecf6275
EM
90 return $relationship;
91 }
7f3647bc 92
2da59b29 93 /**
d49c2966 94 * Create multiple relationships for one contact.
2da59b29 95 *
d49c2966
EM
96 * The relationship details are the same for each relationship except the secondary contact
97 * id can be an array.
98 *
99 * @param array $params
100 * Parameters for creating multiple relationships.
101 * The parameters are the same as for relationship create function except that the non-primary
102 * end of the relationship should be an array of one or more contact IDs.
103 * @param string $primaryContactLetter
104 * a or b to denote the primary contact for this action. The secondary may be multiple contacts
105 * and should be an array.
2da59b29
EM
106 *
107 * @return array
108 * @throws \CRM_Core_Exception
109 */
110 public static function createMultiple($params, $primaryContactLetter) {
111 $secondaryContactLetter = ($primaryContactLetter == 'a') ? 'b' : 'a';
112 $secondaryContactIDs = $params['contact_id_' . $secondaryContactLetter];
113 $valid = $invalid = $duplicate = $saved = 0;
d49c2966 114 $relationshipIDs = array();
2da59b29
EM
115 foreach ($secondaryContactIDs as $secondaryContactID) {
116 try {
117 $params['contact_id_' . $secondaryContactLetter] = $secondaryContactID;
118 $relationship = civicrm_api3('relationship', 'create', $params);
d49c2966 119 $relationshipIDs[] = $relationship['id'];
bfa4da96 120 $valid++;
2da59b29
EM
121 }
122 catch (CiviCRM_API3_Exception $e) {
123 switch ($e->getMessage()) {
bfa4da96
EM
124 case 'Duplicate Relationship':
125 $duplicate++;
2da59b29
EM
126 break;
127
bfa4da96
EM
128 case 'Invalid Relationship':
129 $invalid++;
2da59b29
EM
130 break;
131
132 default:
133 throw new CRM_Core_Exception('unknown relationship create error ' . $e->getMessage());
134 }
135 }
136 }
137
d49c2966
EM
138 return array(
139 'valid' => $valid,
140 'invalid' => $invalid,
141 'duplicate' => $duplicate,
142 'saved' => $saved,
143 'relationship_ids' => $relationshipIDs,
144 );
2da59b29
EM
145 }
146
6a488035 147 /**
fe482240 148 * Takes an associative array and creates a relationship object.
7ecf6275
EM
149 * @deprecated For single creates use the api instead (it's tested).
150 * For multiple a new variant of this function needs to be written and migrated to as this is a bit
151 * nasty
6a488035 152 *
77c5b619
TO
153 * @param array $params
154 * (reference ) an assoc array of name/value pairs.
155 * @param array $ids
156 * The array that holds all the db ids.
16b10e64 157 * per http://wiki.civicrm.org/confluence/display/CRM/Database+layer
26dcc9eb 158 * "we are moving away from the $ids param "
6a488035 159 *
16b10e64 160 * @return CRM_Contact_BAO_Relationship
6a488035 161 */
2da59b29 162 public static function legacyCreateMultiple(&$params, $ids = array()) {
6a488035 163 $valid = $invalid = $duplicate = $saved = 0;
9af2925b 164 $relationships = $relationshipIds = array();
26dcc9eb 165 $relationshipId = CRM_Utils_Array::value('relationship', $ids, CRM_Utils_Array::value('id', $params));
5ad88e9d 166
6a488035
TO
167 //CRM-9015 - the hooks are called here & in add (since add doesn't call create)
168 // but in future should be tidied per ticket
9b873358 169 if (empty($relationshipId)) {
26dcc9eb 170 $hook = 'create';
6a488035 171 }
92e4c2a5 172 else {
26dcc9eb 173 $hook = 'edit';
6a488035 174 }
26dcc9eb 175
176 CRM_Utils_Hook::pre($hook, 'Relationship', $relationshipId, $params);
177
6a488035
TO
178 if (!$relationshipId) {
179 // creating a new relationship
180 $dataExists = self::dataExists($params);
181 if (!$dataExists) {
43291913 182 return array(FALSE, TRUE, FALSE, FALSE, NULL);
6a488035
TO
183 }
184 $relationshipIds = array();
185 foreach ($params['contact_check'] as $key => $value) {
6a488035
TO
186 // check if the relationship is valid between contacts.
187 // step 1: check if the relationship is valid if not valid skip and keep the count
188 // step 2: check the if two contacts already have a relationship if yes skip and keep the count
189 // step 3: if valid relationship then add the relation and keep the count
190
191 // step 1
2001204e
EM
192 $contactFields = self::setContactABFromIDs($params, $ids, $key);
193 $errors = self::checkValidRelationship($contactFields, $ids, $key);
6a488035
TO
194 if ($errors) {
195 $invalid++;
196 continue;
197 }
198
ef6463ad
SB
199 //CRM-16978:check duplicate relationship as per case id.
200 if ($caseId = CRM_Utils_Array::value('case_id', $params)) {
201 $contactFields['case_id'] = $caseId;
202 }
6a488035 203 if (
7f3647bc 204 self::checkDuplicateRelationship(
2001204e 205 $contactFields,
7f3647bc
TO
206 CRM_Utils_Array::value('contact', $ids),
207 // step 2
208 $key
209 )
6a488035
TO
210 ) {
211 $duplicate++;
212 continue;
213 }
2001204e 214
bfa4da96 215 $singleInstanceParams = array_merge($params, $contactFields);
eff45dce 216 $relationship = self::add($singleInstanceParams);
6a488035 217 $relationshipIds[] = $relationship->id;
26dcc9eb 218 $relationships[$relationship->id] = $relationship;
6a488035
TO
219 $valid++;
220 }
221 // editing the relationship
222 }
223 else {
224 // check for duplicate relationship
f0fc26a5
DL
225 // @todo this code doesn't cope well with updates - causes e-Notices.
226 // API has a lot of code to work around
49f8272d 227 // this but should review this code & remove the extra handling from the api
f0fc26a5
DL
228 // it seems doubtful any of this is relevant if the contact fields & relationship
229 // type fields are not set
6a488035 230 if (
7f3647bc
TO
231 self::checkDuplicateRelationship(
232 $params,
233 CRM_Utils_Array::value('contact', $ids),
234 $ids['contactTarget'],
235 $relationshipId
236 )
6a488035
TO
237 ) {
238 $duplicate++;
43291913 239 return array($valid, $invalid, $duplicate, $saved, NULL);
6a488035
TO
240 }
241
242 $validContacts = TRUE;
243 //validate contacts in update mode also.
2f36ede8 244 $contactFields = self::setContactABFromIDs($params, $ids, $ids['contactTarget']);
8cc574cf 245 if (!empty($ids['contact']) && !empty($ids['contactTarget'])) {
2f36ede8 246 if (self::checkValidRelationship($contactFields, $ids, $ids['contactTarget'])) {
6a488035
TO
247 $validContacts = FALSE;
248 $invalid++;
249 }
250 }
251 if ($validContacts) {
252 // editing an existing relationship
2f36ede8
SB
253 $singleInstanceParams = array_merge($params, $contactFields);
254 $relationship = self::add($singleInstanceParams, $ids, $ids['contactTarget']);
6a488035 255 $relationshipIds[] = $relationship->id;
26dcc9eb 256 $relationships[$relationship->id] = $relationship;
6a488035
TO
257 $saved++;
258 }
259 }
260
261 // do not add to recent items for import, CRM-4399
8cc574cf 262 if (!(!empty($params['skipRecentView']) || $invalid || $duplicate)) {
7ecf6275 263 self::addRecent($params, $relationship);
6a488035
TO
264 }
265
26dcc9eb 266 return array($valid, $invalid, $duplicate, $saved, $relationshipIds, $relationships);
6a488035
TO
267 }
268
269 /**
bfa4da96 270 * This is the function that check/add if the relationship created is valid.
6a488035 271 *
77c5b619
TO
272 * @param array $params
273 * (reference ) an assoc array of name/value pairs.
77c5b619
TO
274 * @param array $ids
275 * The array that holds all the db ids.
c301f76e 276 * @param int $contactId
277 * This is contact id for adding relationship.
6a488035 278 *
c490a46a 279 * @return CRM_Contact_BAO_Relationship
6a488035 280 */
00be9182 281 public static function add(&$params, $ids = array(), $contactId = NULL) {
c301f76e 282 $relationshipId = CRM_Utils_Array::value('relationship', $ids, CRM_Utils_Array::value('id', $params));
f0fc26a5 283
49f8272d 284 $hook = 'create';
22e263ad 285 if ($relationshipId) {
49f8272d 286 $hook = 'edit';
6a488035 287 }
49f8272d 288 //@todo hook are called from create and add - remove one
7f3647bc 289 CRM_Utils_Hook::pre($hook, 'Relationship', $relationshipId, $params);
6a488035
TO
290
291 $relationshipTypes = CRM_Utils_Array::value('relationship_type_id', $params);
292
f0fc26a5
DL
293 // explode the string with _ to get the relationship type id
294 // and to know which contact has to be inserted in
6a488035 295 // contact_id_a and which one in contact_id_b
7ecf6275 296 list($type) = explode('_', $relationshipTypes);
6a488035 297
f0fc26a5
DL
298 // check if the relationship type is Head of Household then update the
299 // household's primary contact with this contact.
6a488035 300 if ($type == 6) {
7ecf6275 301 CRM_Contact_BAO_Household::updatePrimaryContact($params['contact_id_b'], $params['contact_id_a']);
6a488035
TO
302 }
303
304 $relationship = new CRM_Contact_BAO_Relationship();
49f8272d 305 //@todo this code needs to be updated for the possibility that not all fields are set
eff45dce 306 // by using $relationship->copyValues($params);
49f8272d 307 // (update)
7ecf6275
EM
308 $relationship->contact_id_b = $params['contact_id_b'];
309 $relationship->contact_id_a = $params['contact_id_a'];
6a488035 310 $relationship->relationship_type_id = $type;
49f8272d 311 $relationship->id = $relationshipId;
6a488035
TO
312
313 $dateFields = array('end_date', 'start_date');
314
9b873358
TO
315 foreach (self::getdefaults() as $defaultField => $defaultValue) {
316 if (isset($params[$defaultField])) {
317 if (in_array($defaultField, $dateFields)) {
6a488035 318 $relationship->$defaultField = CRM_Utils_Date::format(CRM_Utils_Array::value($defaultField, $params));
9b873358 319 if (!$relationship->$defaultField) {
6a488035
TO
320 $relationship->$defaultField = 'NULL';
321 }
322 }
92e4c2a5 323 else {
6a488035
TO
324 $relationship->$defaultField = $params[$defaultField];
325 }
326 }
7f3647bc 327 elseif (!$relationshipId) {
6a488035
TO
328 $relationship->$defaultField = $defaultValue;
329 }
330 }
331
332 $relationship->save();
333
334 // add custom field values
a7488080 335 if (!empty($params['custom'])) {
6a488035
TO
336 CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_relationship', $relationship->id);
337 }
338
339 $relationship->free();
340
5c208c3f 341 CRM_Utils_Hook::post($hook, 'Relationship', $relationship->id, $relationship);
6a488035
TO
342
343 return $relationship;
344 }
7ecf6275
EM
345
346 /**
fe482240 347 * Add relationship to recent links.
bfa4da96 348 *
7ecf6275
EM
349 * @param array $params
350 * @param CRM_Contact_DAO_Relationship $relationship
351 */
352 public static function addRecent($params, $relationship) {
353 $url = CRM_Utils_System::url('civicrm/contact/view/rel',
354 "action=view&reset=1&id={$relationship->id}&cid={$relationship->contact_id_a}&context=home"
355 );
356 $session = CRM_Core_Session::singleton();
357 $recentOther = array();
358 if (($session->get('userID') == $relationship->contact_id_a) ||
359 CRM_Contact_BAO_Contact_Permission::allow($relationship->contact_id_a, CRM_Core_Permission::EDIT)
360 ) {
361 $rType = substr(CRM_Utils_Array::value('relationship_type_id', $params), -3);
362 $recentOther = array(
363 'editUrl' => CRM_Utils_System::url('civicrm/contact/view/rel',
364 "action=update&reset=1&id={$relationship->id}&cid={$relationship->contact_id_a}&rtype={$rType}&context=home"
365 ),
366 'deleteUrl' => CRM_Utils_System::url('civicrm/contact/view/rel',
367 "action=delete&reset=1&id={$relationship->id}&cid={$relationship->contact_id_a}&rtype={$rType}&context=home"
368 ),
369 );
370 }
371 $title = CRM_Contact_BAO_Contact::displayName($relationship->contact_id_a) . ' (' . CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType',
372 $relationship->relationship_type_id, 'label_a_b'
373 ) . ' ' . CRM_Contact_BAO_Contact::displayName($relationship->contact_id_b) . ')';
374
375 CRM_Utils_Recent::add($title,
376 $url,
377 $relationship->id,
378 'Relationship',
379 $relationship->contact_id_a,
380 NULL,
381 $recentOther
382 );
383 }
384
d49c2966
EM
385 /**
386 * Load contact ids and relationship type id when doing a create call if not provided.
387 *
388 * There are are various checks done in create which require this information which is optional
389 * when using id.
390 *
391 * @param array $params
392 * Parameters passed to create call.
393 *
394 * @return array
395 * Parameters with missing fields added if required.
396 */
397 public static function loadExistingRelationshipDetails($params) {
398 if (!empty($params['contact_id_a'])
399 && !empty($params['contact_id_b'])
400 && is_numeric($params['relationship_type_id'])) {
401 return $params;
402 }
403 if (empty($params['id'])) {
404 return $params;
405 }
406
407 $fieldsToFill = array('contact_id_a', 'contact_id_b', 'relationship_type_id');
408 $result = CRM_Core_DAO::executeQuery("SELECT " . implode(',', $fieldsToFill) . " FROM civicrm_relationship WHERE id = %1", array(
409 1 => array(
410 $params['id'],
411 'Integer',
412 ),
413 ));
414 while ($result->fetch()) {
415 foreach ($fieldsToFill as $field) {
416 $params[$field] = !empty($params[$field]) ? $params[$field] : $result->$field;
417 }
418 }
419 return $params;
420 }
421
7ecf6275 422 /**
bfa4da96 423 * Resolve passed in contact IDs to contact_id_a & contact_id_b.
eff45dce 424 *
16b10e64 425 * @param array $params
7ecf6275
EM
426 * @param array $ids
427 * @param null $contactID
eff45dce
EM
428 *
429 * @return array
7ecf6275
EM
430 * @throws \CRM_Core_Exception
431 */
eff45dce
EM
432 public static function setContactABFromIDs($params, $ids = array(), $contactID = NULL) {
433 $returnFields = array();
d49c2966
EM
434
435 // $ids['contact'] is deprecated but comes from legacyCreateMultiple function.
7ecf6275
EM
436 if (empty($ids['contact'])) {
437 if (!empty($params['id'])) {
d49c2966 438 return self::loadExistingRelationshipDetails($params);
7ecf6275
EM
439 }
440 throw new CRM_Core_Exception('Cannot create relationship, insufficient contact IDs provided');
441 }
2001204e 442 if (isset($params['relationship_type_id']) && !is_numeric($params['relationship_type_id'])) {
eff45dce
EM
443 $relationshipTypes = CRM_Utils_Array::value('relationship_type_id', $params);
444 list($relationshipTypeID, $first) = explode('_', $relationshipTypes);
2001204e
EM
445 $returnFields['relationship_type_id'] = $relationshipTypeID;
446
d49c2966
EM
447 foreach (array('a', 'b') as $contactLetter) {
448 if (empty($params['contact_' . $contactLetter])) {
449 if ($first == $contactLetter) {
450 $returnFields['contact_id_' . $contactLetter] = CRM_Utils_Array::value('contact', $ids);
451 }
452 else {
453 $returnFields['contact_id_' . $contactLetter] = $contactID;
454 }
7ecf6275
EM
455 }
456 }
457 }
d49c2966 458
eff45dce 459 return $returnFields;
7ecf6275
EM
460 }
461
6a488035 462 /**
d49c2966 463 * Specify defaults for creating a relationship.
6a488035 464 *
a6c01b45
CW
465 * @return array
466 * array of defaults for creating relationship
6a488035 467 */
00be9182 468 public static function getdefaults() {
6a488035
TO
469 return array(
470 'is_active' => 0,
471 'is_permission_a_b' => 0,
472 'is_permission_b_a' => 0,
473 'description' => '',
474 'start_date' => 'NULL',
475 'case_id' => NULL,
476 'end_date' => 'NULL',
477 );
478 }
479
480
481 /**
fe482240 482 * Check if there is data to create the object.
6a488035 483 *
77c5b619
TO
484 * @param array $params
485 * (reference ) an assoc array of name/value pairs.
6a488035 486 *
c301f76e 487 * @return bool
6a488035 488 */
00be9182 489 public static function dataExists(&$params) {
6a488035
TO
490 // return if no data present
491 if (!is_array(CRM_Utils_Array::value('contact_check', $params))) {
492 return FALSE;
493 }
494 return TRUE;
495 }
496
497 /**
100fef9d 498 * Get get list of relationship type based on the contact type.
6a488035 499 *
77c5b619
TO
500 * @param int $contactId
501 * This is the contact id of the current contact.
fd31fa4c 502 * @param null $contactSuffix
77c5b619
TO
503 * @param string $relationshipId
504 * The id of the existing relationship if any.
505 * @param string $contactType
506 * Contact type.
507 * @param bool $all
508 * If true returns relationship types in both the direction.
509 * @param string $column
510 * Name/label that going to retrieve from db.
fd31fa4c 511 * @param bool $biDirectional
4091c7e7 512 * @param array $contactSubType
bfa4da96 513 * Includes relationship types between this subtype.
77c5b619 514 * @param bool $onlySubTypeRelationTypes
bfa4da96
EM
515 * If set only subtype which is passed by $contactSubType
516 * related relationship types get return
6a488035 517 *
a6c01b45
CW
518 * @return array
519 * array reference of all relationship types with context to current contact.
6a488035 520 */
c301f76e 521 public static function getContactRelationshipType(
51ccfbbe 522 $contactId = NULL,
6a488035
TO
523 $contactSuffix = NULL,
524 $relationshipId = NULL,
525 $contactType = NULL,
526 $all = FALSE,
527 $column = 'label',
528 $biDirectional = TRUE,
529 $contactSubType = NULL,
530 $onlySubTypeRelationTypes = FALSE
531 ) {
d49c2966 532
7f3647bc 533 $relationshipType = array();
6a488035
TO
534 $allRelationshipType = CRM_Core_PseudoConstant::relationshipType($column);
535
536 $otherContactType = NULL;
537 if ($relationshipId) {
538 $relationship = new CRM_Contact_DAO_Relationship();
539 $relationship->id = $relationshipId;
540 if ($relationship->find(TRUE)) {
541 $contact = new CRM_Contact_DAO_Contact();
e003e69b 542 $contact->id = ((int) $relationship->contact_id_a === $contactId) ? $relationship->contact_id_b : $relationship->contact_id_a;
6a488035
TO
543
544 if ($contact->find(TRUE)) {
545 $otherContactType = $contact->contact_type;
546 //CRM-5125 for contact subtype specific relationshiptypes
547 if ($contact->contact_sub_type) {
548 $otherContactSubType = $contact->contact_sub_type;
549 }
550 }
551 }
552 }
553
318c4e1c 554 $contactSubType = (array) $contactSubType;
6a488035
TO
555 if ($contactId) {
556 $contactType = CRM_Contact_BAO_Contact::getContactType($contactId);
557 $contactSubType = CRM_Contact_BAO_Contact::getContactSubType($contactId);
558 }
559
560 foreach ($allRelationshipType as $key => $value) {
561 // the contact type is required or matches
562 if (((!$value['contact_type_a']) ||
563 $value['contact_type_a'] == $contactType
564 ) &&
565 // the other contact type is required or present or matches
566 ((!$value['contact_type_b']) ||
567 (!$otherContactType) ||
568 $value['contact_type_b'] == $otherContactType
569 ) &&
91c0d0d8 570 (in_array($value['contact_sub_type_a'], $contactSubType) ||
91c0d0d8 571 (!$value['contact_sub_type_a'] && !$onlySubTypeRelationTypes)
6a488035
TO
572 )
573 ) {
574 $relationshipType[$key . '_a_b'] = $value["{$column}_a_b"];
575 }
6a488035
TO
576
577 if (((!$value['contact_type_b']) ||
578 $value['contact_type_b'] == $contactType
579 ) &&
580 ((!$value['contact_type_a']) ||
581 (!$otherContactType) ||
582 $value['contact_type_a'] == $otherContactType
583 ) &&
91c0d0d8 584 (in_array($value['contact_sub_type_b'], $contactSubType) ||
91c0d0d8 585 (!$value['contact_sub_type_b'] && !$onlySubTypeRelationTypes)
6a488035
TO
586 )
587 ) {
588 $relationshipType[$key . '_b_a'] = $value["{$column}_b_a"];
589 }
6a488035
TO
590
591 if ($all) {
592 $relationshipType[$key . '_a_b'] = $value["{$column}_a_b"];
593 $relationshipType[$key . '_b_a'] = $value["{$column}_b_a"];
594 }
595 }
596
597 if ($biDirectional) {
02e028a0 598 $relationshipType = self::removeRelationshipTypeDuplicates($relationshipType, $contactSuffix);
6a488035
TO
599 }
600
601 // sort the relationshipType in ascending order CRM-7736
602 asort($relationshipType);
603 return $relationshipType;
604 }
605
02e028a0
AS
606 /**
607 * Given a list of relationship types, return the list with duplicate types
608 * removed, being careful to retain only the duplicate which matches the given
609 * 'a_b' or 'b_a' suffix.
610 *
611 * @param array $relationshipTypeList A list of relationship types, in the format
612 * returned by self::getContactRelationshipType().
613 * @param string $suffix Either 'a_b' or 'b_a'; defaults to 'a_b'
614 *
615 * @return array The modified value of $relationshipType
616 */
617 public static function removeRelationshipTypeDuplicates($relationshipTypeList, $suffix = NULL) {
618 if (empty($suffix)) {
619 $suffix = 'a_b';
620 }
621
622 // Find those labels which are listed more than once.
623 $duplicateValues = array_diff_assoc($relationshipTypeList, array_unique($relationshipTypeList));
624
625 // For each duplicate label, find its keys, and remove from $relationshipType
626 // the key which does not match $suffix.
627 foreach ($duplicateValues as $value) {
628 $keys = array_keys($relationshipTypeList, $value);
629 foreach ($keys as $key) {
630 if (substr($key, -3) != $suffix) {
631 unset($relationshipTypeList[$key]);
632 }
633 }
634 }
635 return $relationshipTypeList;
636 }
637
86538308 638 /**
98a06ae0
EM
639 * Delete current employer relationship.
640 *
100fef9d 641 * @param int $id
98a06ae0 642 * @param int $action
86538308
EM
643 *
644 * @return CRM_Contact_DAO_Relationship
645 */
00be9182 646 public static function clearCurrentEmployer($id, $action) {
6a488035
TO
647 $relationship = new CRM_Contact_DAO_Relationship();
648 $relationship->id = $id;
649 $relationship->find(TRUE);
650
651 //to delete relationship between household and individual \
98a06ae0 652 //or between individual and organization
6a488035 653 if (($action & CRM_Core_Action::DISABLE) || ($action & CRM_Core_Action::DELETE)) {
05802b8e 654 $relTypes = CRM_Utils_Array::index(array('name_a_b'), CRM_Core_PseudoConstant::relationshipType('name'));
81d1f764
MM
655 if (
656 (isset($relTypes['Employee of']) && $relationship->relationship_type_id == $relTypes['Employee of']['id']) ||
657 (isset ($relTypes['Household Member of']) && $relationship->relationship_type_id == $relTypes['Household Member of']['id'])
7f3647bc 658 ) {
05802b8e
DG
659 $sharedContact = new CRM_Contact_DAO_Contact();
660 $sharedContact->id = $relationship->contact_id_a;
661 $sharedContact->find(TRUE);
662
bd655ee6
MV
663 // CRM-15881 UPDATES
664 // changed FROM "...relationship->relationship_type_id == 4..." TO "...relationship->relationship_type_id == 5..."
665 // As the system should be looking for type "employer of" (id 5) and not "sibling of" (id 4)
3421dcee
MV
666 // As suggested by @davecivicrm, the employee relationship type id is fetched using the CRM_Core_DAO::getFieldValue() class and method, since these ids differ from system to system.
667 $employerRelTypeId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType', 'Employee of', 'id', 'name_a_b');
668
669 if ($relationship->relationship_type_id == $employerRelTypeId && $relationship->contact_id_b == $sharedContact->employer_id) {
05802b8e
DG
670 CRM_Contact_BAO_Contact_Utils::clearCurrentEmployer($relationship->contact_id_a);
671 }
3421dcee 672
6a488035
TO
673 }
674 }
7f3647bc 675 return $relationship;
6a488035
TO
676 }
677
678 /**
fe482240 679 * Delete the relationship.
6a488035 680 *
77c5b619
TO
681 * @param int $id
682 * Relationship id.
6a488035
TO
683 *
684 * @return null
6a488035 685 */
00be9182 686 public static function del($id) {
6a488035
TO
687 // delete from relationship table
688 CRM_Utils_Hook::pre('delete', 'Relationship', $id, CRM_Core_DAO::$_nullArray);
689
690 $relationship = self::clearCurrentEmployer($id, CRM_Core_Action::DELETE);
691 if (CRM_Core_Permission::access('CiviMember')) {
692 // create $params array which isrequired to delete memberships
693 // of the related contacts.
694 $params = array(
695 'relationship_type_id' => "{$relationship->relationship_type_id}_a_b",
696 'contact_check' => array($relationship->contact_id_b => 1),
697 );
698
699 $ids = array();
700 // calling relatedMemberships to delete the memberships of
701 // related contacts.
702 self::relatedMemberships($relationship->contact_id_a,
703 $params,
704 $ids,
705 CRM_Core_Action::DELETE,
706 FALSE
707 );
708 }
709
710 $relationship->delete();
711 CRM_Core_Session::setStatus(ts('Selected relationship has been deleted successfully.'), ts('Record Deleted'), 'success');
712
5c208c3f 713 CRM_Utils_Hook::post('delete', 'Relationship', $id, $relationship);
6a488035
TO
714
715 // delete the recently created Relationship
716 $relationshipRecent = array(
717 'id' => $id,
718 'type' => 'Relationship',
719 );
720 CRM_Utils_Recent::del($relationshipRecent);
721
722 return $relationship;
723 }
724
725 /**
98a06ae0 726 * Disable/enable the relationship.
6a488035 727 *
77c5b619
TO
728 * @param int $id
729 * Relationship id.
6a488035 730 *
7a44a255
EM
731 * @param int $action
732 * @param array $params
733 * @param array $ids
734 * @param bool $active
6a488035 735 */
690c56c3 736 public static function disableEnableRelationship($id, $action, $params = array(), $ids = array(), $active = FALSE) {
6a488035 737 $relationship = self::clearCurrentEmployer($id, $action);
25f1372e 738
1b5fad8a 739 if ($id) {
25f1372e 740 // create $params array which is required to delete memberships
6a488035 741 // of the related contacts.
690c56c3 742 if (empty($params)) {
743 $params = array(
744 'relationship_type_id' => "{$relationship->relationship_type_id}_a_b",
745 'contact_check' => array($relationship->contact_id_b => 1),
746 );
747 }
690c56c3 748 $contact_id_a = empty($params['contact_id_a']) ? $relationship->contact_id_a : $params['contact_id_a'];
6a488035
TO
749 // calling relatedMemberships to delete/add the memberships of
750 // related contacts.
751 if ($action & CRM_Core_Action::DISABLE) {
690c56c3 752 CRM_Contact_BAO_Relationship::relatedMemberships($contact_id_a,
6a488035
TO
753 $params,
754 $ids,
755 CRM_Core_Action::DELETE,
690c56c3 756 $active
6a488035
TO
757 );
758 }
759 elseif ($action & CRM_Core_Action::ENABLE) {
91244f1d 760 $ids['contact'] = empty($ids['contact']) ? $contact_id_a : $ids['contact'];
690c56c3 761 CRM_Contact_BAO_Relationship::relatedMemberships($contact_id_a,
6a488035
TO
762 $params,
763 $ids,
690c56c3 764 empty($params['id']) ? CRM_Core_Action::ADD : CRM_Core_Action::UPDATE,
765 $active
6a488035
TO
766 );
767 }
768 }
769 }
770
771 /**
fe482240 772 * Delete the object records that are associated with this contact.
6a488035 773 *
77c5b619
TO
774 * @param int $contactId
775 * Id of the contact to delete.
6a488035 776 */
00be9182 777 public static function deleteContact($contactId) {
6a488035
TO
778 $relationship = new CRM_Contact_DAO_Relationship();
779 $relationship->contact_id_a = $contactId;
780 $relationship->delete();
781
782 $relationship = new CRM_Contact_DAO_Relationship();
783 $relationship->contact_id_b = $contactId;
784 $relationship->delete();
785
786 CRM_Contact_BAO_Household::updatePrimaryContact(NULL, $contactId);
787 }
788
789 /**
fe482240 790 * Get the other contact in a relationship.
6a488035 791 *
77c5b619
TO
792 * @param int $id
793 * Relationship id.
6a488035
TO
794 *
795 * $returns returns the contact ids in the realtionship
77b97be7
EM
796 *
797 * @return \CRM_Contact_DAO_Relationship
6a488035 798 */
eff45dce 799 public static function getRelationshipByID($id) {
6a488035
TO
800 $relationship = new CRM_Contact_DAO_Relationship();
801
802 $relationship->id = $id;
803 $relationship->selectAdd();
804 $relationship->selectAdd('contact_id_a, contact_id_b');
805 $relationship->find(TRUE);
806
807 return $relationship;
808 }
809
810 /**
fe482240 811 * Check if the relationship type selected between two contacts is correct.
6a488035 812 *
77c5b619
TO
813 * @param int $contact_a
814 * 1st contact id.
815 * @param int $contact_b
816 * 2nd contact id.
817 * @param int $relationshipTypeId
818 * Relationship type id.
6a488035 819 *
c301f76e 820 * @return bool
a6c01b45 821 * true if it is valid relationship else false
6a488035 822 */
00be9182 823 public static function checkRelationshipType($contact_a, $contact_b, $relationshipTypeId) {
6a488035
TO
824 $relationshipType = new CRM_Contact_DAO_RelationshipType();
825 $relationshipType->id = $relationshipTypeId;
826 $relationshipType->selectAdd();
827 $relationshipType->selectAdd('contact_type_a, contact_type_b, contact_sub_type_a, contact_sub_type_b');
828 if ($relationshipType->find(TRUE)) {
829 $contact_type_a = CRM_Contact_BAO_Contact::getContactType($contact_a);
830 $contact_type_b = CRM_Contact_BAO_Contact::getContactType($contact_b);
831
832 $contact_sub_type_a = CRM_Contact_BAO_Contact::getContactSubType($contact_a);
833 $contact_sub_type_b = CRM_Contact_BAO_Contact::getContactSubType($contact_b);
834
835 if (((!$relationshipType->contact_type_a) || ($relationshipType->contact_type_a == $contact_type_a)) &&
836 ((!$relationshipType->contact_type_b) || ($relationshipType->contact_type_b == $contact_type_b)) &&
837 ((!$relationshipType->contact_sub_type_a) || (in_array($relationshipType->contact_sub_type_a,
7f3647bc
TO
838 $contact_sub_type_a
839 ))) &&
6a488035 840 ((!$relationshipType->contact_sub_type_b) || (in_array($relationshipType->contact_sub_type_b,
7f3647bc
TO
841 $contact_sub_type_b
842 )))
6a488035
TO
843 ) {
844 return TRUE;
845 }
846 else {
847 return FALSE;
848 }
849 }
850 return FALSE;
851 }
852
853 /**
fe482240 854 * This function does the validtion for valid relationship.
6a488035 855 *
77c5b619
TO
856 * @param array $params
857 * This array contains the values there are subitted by the form.
858 * @param array $ids
859 * The array that holds all the db ids.
860 * @param int $contactId
861 * This is contact id for adding relationship.
6a488035 862 *
2a6da8d7 863 * @return string
6a488035 864 */
7ecf6275 865 public static function checkValidRelationship($params, $ids, $contactId) {
6a488035 866 $errors = '';
6a488035
TO
867 // function to check if the relationship selected is correct
868 // i.e. employer relationship can exit between Individual and Organization (not between Individual and Individual)
c4dcea5b
EM
869 if (!CRM_Contact_BAO_Relationship::checkRelationshipType($params['contact_id_a'], $params['contact_id_b'],
870 $params['relationship_type_id'])) {
6a488035
TO
871 $errors = 'Please select valid relationship between these two contacts.';
872 }
873 return $errors;
874 }
875
876 /**
fe482240 877 * This function checks for duplicate relationship.
6a488035 878 *
77c5b619
TO
879 * @param array $params
880 * (reference ) an assoc array of name/value pairs.
881 * @param int $id
882 * This the id of the contact whom we are adding relationship.
883 * @param int $contactId
884 * This is contact id for adding relationship.
885 * @param int $relationshipId
886 * This is relationship id for the contact.
6a488035 887 *
c301f76e 888 * @return bool
a6c01b45 889 * true if record exists else false
6a488035 890 */
00be9182 891 public static function checkDuplicateRelationship(&$params, $id, $contactId = 0, $relationshipId = 0) {
6a488035 892 $relationshipTypeId = CRM_Utils_Array::value('relationship_type_id', $params);
decc60a0 893 list($type) = explode('_', $relationshipTypeId);
6a488035 894
f0fc26a5
DL
895 $queryString = "
896SELECT id
897FROM civicrm_relationship
898WHERE relationship_type_id = " . CRM_Utils_Type::escape($type, 'Integer');
6a488035
TO
899
900 /*
e70a7fc0
TO
901 * CRM-11792 - date fields from API are in ISO format, but this function
902 * supports date arrays BAO has increasingly standardised to ISO format
903 * so I believe this function should support ISO rather than make API
904 * format it - however, need to support array format for now to avoid breakage
2da59b29 905 * @ time of writing this function is called from Relationship::legacyCreateMultiple (twice)
e70a7fc0
TO
906 * CRM_BAO_Contact_Utils::clearCurrentEmployer (seemingly without dates)
907 * CRM_Contact_Form_Task_AddToOrganization::postProcess &
908 * CRM_Contact_Form_Task_AddToHousehold::postProcess
909 * (I don't think the last 2 support dates but not sure
910 */
6a488035
TO
911
912 $dateFields = array('end_date', 'start_date');
9b873358 913 foreach ($dateFields as $dateField) {
22e263ad 914 if (array_key_exists($dateField, $params)) {
9b873358 915 if (empty($params[$dateField]) || $params[$dateField] == 'null') {
f0fc26a5
DL
916 //this is most likely coming from an api call & probably loaded
917 // from the DB to deal with some of the
918 // other myriad of excessive checks still in place both in
919 // the api & the create functions
6a488035
TO
920 $queryString .= " AND $dateField IS NULL";
921 continue;
922 }
9b873358 923 elseif (is_array($params[$dateField])) {
f0fc26a5
DL
924 $queryString .= " AND $dateField = " .
925 CRM_Utils_Type::escape(CRM_Utils_Date::format($params[$dateField]), 'Date');
6a488035 926 }
f0fc26a5
DL
927 else {
928 $queryString .= " AND $dateField = " .
929 CRM_Utils_Type::escape($params[$dateField], 'Date');
6a488035
TO
930 }
931 }
932 }
933
934 $queryString .=
935 " AND ( ( contact_id_a = " . CRM_Utils_Type::escape($id, 'Integer') .
936 " AND contact_id_b = " . CRM_Utils_Type::escape($contactId, 'Integer') .
937 " ) OR ( contact_id_a = " . CRM_Utils_Type::escape($contactId, 'Integer') .
938 " AND contact_id_b = " . CRM_Utils_Type::escape($id, 'Integer') . " ) ) ";
939
940 //if caseId is provided, include it duplicate checking.
941 if ($caseId = CRM_Utils_Array::value('case_id', $params)) {
942 $queryString .= " AND case_id = " . CRM_Utils_Type::escape($caseId, 'Integer');
943 }
944
945 if ($relationshipId) {
946 $queryString .= " AND id !=" . CRM_Utils_Type::escape($relationshipId, 'Integer');
947 }
948
949 $relationship = new CRM_Contact_BAO_Relationship();
950 $relationship->query($queryString);
6b284952
JV
951 while ($relationship->fetch()) {
952 // Check whether the custom field values are identical.
953 $result = self::checkDuplicateCustomFields($params, $relationship->id);
954 if ($result) {
955 $relationship->free();
956 return TRUE;
957 }
958 }
6a488035 959 $relationship->free();
6b284952
JV
960 return FALSE;
961 }
962
963 /**
964 * this function checks whether the values of the custom fields in $params are
965 * the same as the values of the custom fields of the relation with given
966 * $relationshipId.
967 *
968 * @param array $params (reference) an assoc array of name/value pairs
969 * @param int $relationshipId ID of an existing duplicate relation
970 *
971 * @return boolean true if custom field values are identical
972 * @access private
973 * @static
974 */
975 private static function checkDuplicateCustomFields(&$params, $relationshipId) {
e312bf62 976 // Get the custom values of the existing relationship.
6b284952 977 $existingValues = CRM_Core_BAO_CustomValueTable::getEntityValues($relationshipId, 'Relationship');
e312bf62
JV
978 // Create a similar array for the new relationship.
979 $newValues = array();
1bedc18d
JV
980 if (array_key_exists('custom', $params)) {
981 // $params['custom'] seems to be an array. Each value is again an array.
982 // This array contains one value (key -1), and this value seems to be
983 // an array with the information about the custom value.
984 foreach ($params['custom'] as $value) {
985 foreach ($value as $customValue) {
986 $newValues[$customValue['custom_field_id']] = $customValue['value'];
987 }
6b284952
JV
988 }
989 }
e312bf62
JV
990
991 // Calculate difference between arrays. If the only key-value pairs
992 // that are in one array but not in the other are empty, the
993 // custom fields are considered to be equal.
994 // See https://github.com/civicrm/civicrm-core/pull/6515#issuecomment-137985667
995 $diff1 = array_diff_assoc($existingValues, $newValues);
996 $diff2 = array_diff_assoc($newValues, $existingValues);
997
998 return !array_filter($diff1) && !array_filter($diff2);
6a488035
TO
999 }
1000
1001 /**
fe482240 1002 * Update the is_active flag in the db.
6a488035 1003 *
77c5b619
TO
1004 * @param int $id
1005 * Id of the database record.
1006 * @param bool $is_active
1007 * Value we want to set the is_active field.
6a488035 1008 *
77b97be7 1009 * @throws CiviCRM_API3_Exception
a6c01b45
CW
1010 * @return Object
1011 * DAO object on success, null otherwise
6a488035 1012 */
00be9182 1013 public static function setIsActive($id, $is_active) {
49f8272d
E
1014 // as both the create & add functions have a bunch of logic in them that
1015 // doesn't seem to cope with a normal update we will call the api which
1016 // has tested handling for this
1017 // however, a longer term solution would be to simplify the add, create & api functions
1018 // to be more standard. It is debatable @ that point whether it's better to call the BAO
1019 // direct as the api is more tested.
80109b10 1020 $result = civicrm_api('relationship', 'create', array(
1021 'id' => $id,
1022 'is_active' => $is_active,
1023 'version' => 3,
1024 ));
1025
338ca861 1026 if (is_array($result) && !empty($result['is_error']) && $result['error_message'] != 'Duplicate Relationship') {
80109b10 1027 throw new CiviCRM_API3_Exception($result['error_message'], CRM_Utils_Array::value('error_code', $result, 'undefined'), $result);
1028 }
49f8272d 1029
6a488035
TO
1030 return TRUE;
1031 }
1032
1033 /**
98a06ae0 1034 * Fetch a relationship object and store the values in the values array.
6a488035 1035 *
77c5b619
TO
1036 * @param array $params
1037 * Input parameters to find object.
1038 * @param array $values
1039 * Output values of the object.
6a488035 1040 *
a6c01b45
CW
1041 * @return array
1042 * (reference) the values that could be potentially assigned to smarty
6a488035 1043 */
00be9182 1044 public static function &getValues(&$params, &$values) {
6a488035
TO
1045 if (empty($params)) {
1046 return NULL;
1047 }
1048 $v = array();
1049
1050 // get the specific number of relationship or all relationships.
a7488080 1051 if (!empty($params['numRelationship'])) {
6a488035
TO
1052 $v['data'] = &CRM_Contact_BAO_Relationship::getRelationship($params['contact_id'], NULL, $params['numRelationship']);
1053 }
1054 else {
1055 $v['data'] = CRM_Contact_BAO_Relationship::getRelationship($params['contact_id']);
1056 }
1057
1058 // get the total count of relationships
c23fcc07 1059 $v['totalCount'] = count($v['data']);
6a488035
TO
1060
1061 $values['relationship']['data'] = &$v['data'];
1062 $values['relationship']['totalCount'] = &$v['totalCount'];
1063
1064 return $v;
1065 }
1066
1067 /**
fe482240 1068 * Helper function to form the sql for relationship retrieval.
6a488035 1069 *
77c5b619
TO
1070 * @param int $contactId
1071 * Contact id.
1072 * @param int $status
1073 * (check const at top of file).
1074 * @param int $numRelationship
1075 * No of relationships to display (limit).
1076 * @param int $count
1077 * Get the no of relationships.
6a488035 1078 * $param int $relationshipId relationship id
100fef9d 1079 * @param int $relationshipId
77c5b619
TO
1080 * @param string $direction
1081 * The direction we are interested in a_b or b_a.
1082 * @param array $params
1083 * Array of extra values including relationship_type_id per api spec.
6a488035 1084 *
77b97be7 1085 * @return array
76e7a76c 1086 * [select, from, where]
6a488035 1087 */
00be9182 1088 public static function makeURLClause($contactId, $status, $numRelationship, $count, $relationshipId, $direction, $params = array()) {
6a488035
TO
1089 $select = $from = $where = '';
1090
1091 $select = '( ';
1092 if ($count) {
1093 if ($direction == 'a_b') {
1094 $select .= ' SELECT count(DISTINCT civicrm_relationship.id) as cnt1, 0 as cnt2 ';
1095 }
1096 else {
1097 $select .= ' SELECT 0 as cnt1, count(DISTINCT civicrm_relationship.id) as cnt2 ';
1098 }
1099 }
1100 else {
1101 $select .= ' SELECT civicrm_relationship.id as civicrm_relationship_id,
1102 civicrm_contact.sort_name as sort_name,
1103 civicrm_contact.display_name as display_name,
1104 civicrm_contact.job_title as job_title,
1105 civicrm_contact.employer_id as employer_id,
1106 civicrm_contact.organization_name as organization_name,
1107 civicrm_address.street_address as street_address,
1108 civicrm_address.city as city,
1109 civicrm_address.postal_code as postal_code,
1110 civicrm_state_province.abbreviation as state,
1111 civicrm_country.name as country,
1112 civicrm_email.email as email,
c6c691a5 1113 civicrm_contact.contact_type as contact_type,
20be4ac3 1114 civicrm_contact.contact_sub_type as contact_sub_type,
6a488035
TO
1115 civicrm_phone.phone as phone,
1116 civicrm_contact.id as civicrm_contact_id,
6a488035
TO
1117 civicrm_relationship.contact_id_b as contact_id_b,
1118 civicrm_relationship.contact_id_a as contact_id_a,
1119 civicrm_relationship_type.id as civicrm_relationship_type_id,
1120 civicrm_relationship.start_date as start_date,
1121 civicrm_relationship.end_date as end_date,
1122 civicrm_relationship.description as description,
1123 civicrm_relationship.is_active as is_active,
1124 civicrm_relationship.is_permission_a_b as is_permission_a_b,
1125 civicrm_relationship.is_permission_b_a as is_permission_b_a,
1126 civicrm_relationship.case_id as case_id';
1127
1128 if ($direction == 'a_b') {
1129 $select .= ', civicrm_relationship_type.label_a_b as label_a_b,
c6c691a5 1130 civicrm_relationship_type.label_b_a as relation ';
6a488035
TO
1131 }
1132 else {
1133 $select .= ', civicrm_relationship_type.label_a_b as label_a_b,
c6c691a5 1134 civicrm_relationship_type.label_a_b as relation ';
6a488035
TO
1135 }
1136 }
1137
1138 $from = "
1139 FROM civicrm_relationship
1140INNER JOIN civicrm_relationship_type ON ( civicrm_relationship.relationship_type_id = civicrm_relationship_type.id )
1141INNER JOIN civicrm_contact ";
1142 if ($direction == 'a_b') {
1143 $from .= 'ON ( civicrm_contact.id = civicrm_relationship.contact_id_a ) ';
1144 }
1145 else {
1146 $from .= 'ON ( civicrm_contact.id = civicrm_relationship.contact_id_b ) ';
1147 }
b7d19957
CR
1148
1149 if (!$count) {
1150 $from .= "
6a488035
TO
1151LEFT JOIN civicrm_address ON (civicrm_address.contact_id = civicrm_contact.id AND civicrm_address.is_primary = 1)
1152LEFT JOIN civicrm_phone ON (civicrm_phone.contact_id = civicrm_contact.id AND civicrm_phone.is_primary = 1)
1153LEFT JOIN civicrm_email ON (civicrm_email.contact_id = civicrm_contact.id AND civicrm_email.is_primary = 1)
1154LEFT JOIN civicrm_state_province ON (civicrm_address.state_province_id = civicrm_state_province.id)
1155LEFT JOIN civicrm_country ON (civicrm_address.country_id = civicrm_country.id)
1156";
b7d19957
CR
1157 }
1158
6a488035
TO
1159 $where = 'WHERE ( 1 )';
1160 if ($contactId) {
1161 if ($direction == 'a_b') {
1162 $where .= ' AND civicrm_relationship.contact_id_b = ' . CRM_Utils_Type::escape($contactId, 'Positive');
1163 }
1164 else {
075fa74e 1165 $where .= ' AND civicrm_relationship.contact_id_a = ' . CRM_Utils_Type::escape($contactId, 'Positive') . '
1166 AND civicrm_relationship.contact_id_a != civicrm_relationship.contact_id_b ';
6a488035
TO
1167 }
1168 }
1169 if ($relationshipId) {
1170 $where .= ' AND civicrm_relationship.id = ' . CRM_Utils_Type::escape($relationshipId, 'Positive');
1171 }
1172
1173 $date = date('Y-m-d');
1174 if ($status == self::PAST) {
1175 //this case for showing past relationship
1176 $where .= ' AND civicrm_relationship.is_active = 1 ';
1177 $where .= " AND civicrm_relationship.end_date < '" . $date . "'";
1178 }
1179 elseif ($status == self::DISABLED) {
1180 // this case for showing disabled relationship
1181 $where .= ' AND civicrm_relationship.is_active = 0 ';
1182 }
1183 elseif ($status == self::CURRENT) {
1184 //this case for showing current relationship
1185 $where .= ' AND civicrm_relationship.is_active = 1 ';
1186 $where .= " AND (civicrm_relationship.end_date >= '" . $date . "' OR civicrm_relationship.end_date IS NULL) ";
1187 }
1188 elseif ($status == self::INACTIVE) {
1189 //this case for showing inactive relationships
1190 $where .= " AND (civicrm_relationship.end_date < '" . $date . "'";
1191 $where .= ' OR civicrm_relationship.is_active = 0 )';
1192 }
1193
1194 // CRM-6181
1195 $where .= ' AND civicrm_contact.is_deleted = 0';
22e263ad 1196 if (!empty($params['membership_type_id']) && empty($params['relationship_type_id'])) {
c9c41397 1197 $where .= self::membershipTypeToRelationshipTypes($params, $direction);
1198 }
22e263ad
TO
1199 if (!empty($params['relationship_type_id'])) {
1200 if (is_array($params['relationship_type_id'])) {
7f3647bc 1201 $where .= " AND " . CRM_Core_DAO::createSQLFilter('relationship_type_id', $params['relationship_type_id'], 'Integer');
75638074 1202 }
1203 else {
1204 $where .= ' AND relationship_type_id = ' . CRM_Utils_Type::escape($params['relationship_type_id'], 'Positive');
1205 }
1206 }
6a488035
TO
1207 if ($direction == 'a_b') {
1208 $where .= ' ) UNION ';
1209 }
1210 else {
1211 $where .= ' ) ';
1212 }
1213
1214 return array($select, $from, $where);
1215 }
1216
1217 /**
fe482240 1218 * Get a list of relationships.
6a488035 1219 *
77c5b619
TO
1220 * @param int $contactId
1221 * Contact id.
1222 * @param int $status
1223 * 1: Past 2: Disabled 3: Current.
1224 * @param int $numRelationship
1225 * No of relationships to display (limit).
1226 * @param int $count
1227 * Get the no of relationships.
77b97be7 1228 * @param int $relationshipId
76e7a76c
CW
1229 * @param array $links
1230 * the list of links to display
1231 * @param int $permissionMask
1232 * the permission mask to be applied for the actions
77b97be7 1233 * @param bool $permissionedContact
76e7a76c 1234 * to return only permissioned Contact
77b97be7 1235 * @param array $params
644587aa
SL
1236 * @param bool $includeTotalCount
1237 * Should we return a count of total accessable relationships
77b97be7
EM
1238 *
1239 * @return array|int
76e7a76c 1240 * relationship records
6a488035 1241 */
c301f76e 1242 public static function getRelationship(
51ccfbbe 1243 $contactId = NULL,
7f3647bc
TO
1244 $status = 0, $numRelationship = 0,
1245 $count = 0, $relationshipId = 0,
1246 $links = NULL, $permissionMask = NULL,
75638074 1247 $permissionedContact = FALSE,
644587aa 1248 $params = array(), $includeTotalCount = FALSE
6a488035
TO
1249 ) {
1250 $values = array();
1251 if (!$contactId && !$relationshipId) {
1252 return $values;
1253 }
1254
1255 list($select1, $from1, $where1) = self::makeURLClause($contactId, $status, $numRelationship,
75638074 1256 $count, $relationshipId, 'a_b', $params
6a488035
TO
1257 );
1258 list($select2, $from2, $where2) = self::makeURLClause($contactId, $status, $numRelationship,
75638074 1259 $count, $relationshipId, 'b_a', $params
6a488035
TO
1260 );
1261
1262 $order = $limit = '';
1263 if (!$count) {
40458f6c 1264 if (empty($params['sort'])) {
1265 $order = ' ORDER BY civicrm_relationship_type_id, sort_name ';
1266 }
1267 else {
1268 $order = " ORDER BY {$params['sort']} ";
1269 }
1270
1271 $offset = 0;
630d1aaa 1272 if (!empty($params['offset']) && $params['offset'] > 0) {
40458f6c 1273 $offset = $params['offset'];
1274 }
6a488035
TO
1275
1276 if ($numRelationship) {
40458f6c 1277 $limit = " LIMIT {$offset}, $numRelationship";
6a488035
TO
1278 }
1279 }
1280
1281 // building the query string
e729799a 1282 $queryString = $select1 . $from1 . $where1 . $select2 . $from2 . $where2;
6a488035
TO
1283
1284 $relationship = new CRM_Contact_DAO_Relationship();
1285
e729799a 1286 $relationship->query($queryString . $order . $limit);
6a488035
TO
1287 $row = array();
1288 if ($count) {
1289 $relationshipCount = 0;
1290 while ($relationship->fetch()) {
1291 $relationshipCount += $relationship->cnt1 + $relationship->cnt2;
1292 }
1293 return $relationshipCount;
1294 }
1295 else {
1296
644587aa 1297 if ($includeTotalCount) {
e729799a 1298 $values['total_relationships'] = CRM_Core_DAO::singleValueQuery("SELECT count(*) FROM ({$queryString}) AS r");
644587aa
SL
1299 }
1300
6a488035
TO
1301 $mask = NULL;
1302 if ($status != self::INACTIVE) {
1303 if ($links) {
1304 $mask = array_sum(array_keys($links));
1305 if ($mask & CRM_Core_Action::DISABLE) {
1306 $mask -= CRM_Core_Action::DISABLE;
1307 }
1308 if ($mask & CRM_Core_Action::ENABLE) {
1309 $mask -= CRM_Core_Action::ENABLE;
1310 }
1311
1312 if ($status == self::CURRENT) {
1313 $mask |= CRM_Core_Action::DISABLE;
1314 }
1315 elseif ($status == self::DISABLED) {
1316 $mask |= CRM_Core_Action::ENABLE;
1317 }
6a488035 1318 }
75b35151 1319 // temporary hold the value of $mask.
1320 $tempMask = $mask;
6a488035 1321 }
c23fcc07 1322
6a488035
TO
1323 while ($relationship->fetch()) {
1324 $rid = $relationship->civicrm_relationship_id;
1325 $cid = $relationship->civicrm_contact_id;
a93664c8 1326
dc15bb38 1327 if ($permissionedContact &&
a93664c8 1328 (!CRM_Contact_BAO_Contact_Permission::allow($cid))
6a488035
TO
1329 ) {
1330 continue;
1331 }
75b35151 1332 if ($status != self::INACTIVE && $links) {
1333 // assign the original value to $mask
1334 $mask = $tempMask;
1335 // display action links if $cid has edit permission for the relationship.
1336 if (!($permissionMask & CRM_Core_Permission::EDIT) && CRM_Contact_BAO_Contact_Permission::allow($cid, CRM_Core_Permission::EDIT)) {
1337 $permissions[] = CRM_Core_Permission::EDIT;
1338 $permissions[] = CRM_Core_Permission::DELETE;
1339 $permissionMask = CRM_Core_Action::mask($permissions);
1340 }
1341 $mask = $mask & $permissionMask;
1342 }
6a488035
TO
1343 $values[$rid]['id'] = $rid;
1344 $values[$rid]['cid'] = $cid;
1345 $values[$rid]['contact_id_a'] = $relationship->contact_id_a;
1346 $values[$rid]['contact_id_b'] = $relationship->contact_id_b;
c6c691a5 1347 $values[$rid]['contact_type'] = $relationship->contact_type;
20be4ac3 1348 $values[$rid]['contact_sub_type'] = $relationship->contact_sub_type;
6a488035
TO
1349 $values[$rid]['relationship_type_id'] = $relationship->civicrm_relationship_type_id;
1350 $values[$rid]['relation'] = $relationship->relation;
1351 $values[$rid]['name'] = $relationship->sort_name;
1352 $values[$rid]['display_name'] = $relationship->display_name;
1353 $values[$rid]['job_title'] = $relationship->job_title;
1354 $values[$rid]['email'] = $relationship->email;
1355 $values[$rid]['phone'] = $relationship->phone;
1356 $values[$rid]['employer_id'] = $relationship->employer_id;
1357 $values[$rid]['organization_name'] = $relationship->organization_name;
1358 $values[$rid]['country'] = $relationship->country;
1359 $values[$rid]['city'] = $relationship->city;
1360 $values[$rid]['state'] = $relationship->state;
1361 $values[$rid]['start_date'] = $relationship->start_date;
1362 $values[$rid]['end_date'] = $relationship->end_date;
1363 $values[$rid]['description'] = $relationship->description;
1364 $values[$rid]['is_active'] = $relationship->is_active;
1365 $values[$rid]['is_permission_a_b'] = $relationship->is_permission_a_b;
1366 $values[$rid]['is_permission_b_a'] = $relationship->is_permission_b_a;
1367 $values[$rid]['case_id'] = $relationship->case_id;
1368
1369 if ($status) {
1370 $values[$rid]['status'] = $status;
1371 }
1372
1373 $values[$rid]['civicrm_relationship_type_id'] = $relationship->civicrm_relationship_type_id;
1374
1375 if ($relationship->contact_id_a == $contactId) {
1376 $values[$rid]['rtype'] = 'a_b';
1377 }
1378 else {
1379 $values[$rid]['rtype'] = 'b_a';
1380 }
1381
1382 if ($links) {
1383 $replace = array(
1384 'id' => $rid,
1385 'rtype' => $values[$rid]['rtype'],
1386 'cid' => $contactId,
1387 'cbid' => $values[$rid]['cid'],
1388 'caseid' => $values[$rid]['case_id'],
1389 'clientid' => $contactId,
1390 );
1391
1392 if ($status == self::INACTIVE) {
1393 // setting links for inactive relationships
1394 $mask = array_sum(array_keys($links));
1395 if (!$values[$rid]['is_active']) {
1396 $mask -= CRM_Core_Action::DISABLE;
1397 }
1398 else {
1399 $mask -= CRM_Core_Action::ENABLE;
1400 $mask -= CRM_Core_Action::DISABLE;
1401 }
cd056f13 1402 $mask = $mask & $permissionMask;
6a488035
TO
1403 }
1404
1405 // Give access to manage case link by copying to MAX_ACTION index temporarily, depending on case permission of user.
1406 if ($values[$rid]['case_id']) {
1407 // Borrowed logic from CRM_Case_Page_Tab
1408 $hasCaseAccess = FALSE;
1409 if (CRM_Core_Permission::check('access all cases and activities')) {
1410 $hasCaseAccess = TRUE;
1411 }
1412 else {
1413 $userCases = CRM_Case_BAO_Case::getCases(FALSE);
1414 if (array_key_exists($values[$rid]['case_id'], $userCases)) {
1415 $hasCaseAccess = TRUE;
1416 }
1417 }
1418
1419 if ($hasCaseAccess) {
1420 // give access by copying to MAX_ACTION temporarily, otherwise leave at NONE which won't display
1421 $links[CRM_Core_Action::MAX_ACTION] = $links[CRM_Core_Action::NONE];
1422 $links[CRM_Core_Action::MAX_ACTION]['name'] = ts('Manage Case #%1', array(1 => $values[$rid]['case_id']));
f89f2102 1423 $links[CRM_Core_Action::MAX_ACTION]['class'] = 'no-popup';
6a488035
TO
1424
1425 // Also make sure we have the right client cid since can get here from multiple relationship tabs.
1426 if ($values[$rid]['rtype'] == 'b_a') {
1427 $replace['clientid'] = $values[$rid]['cid'];
1428 }
1429 }
1430 }
1431
87dab4a4 1432 $values[$rid]['action'] = CRM_Core_Action::formLink(
1cfa04c4
EM
1433 $links,
1434 $mask,
87dab4a4
AH
1435 $replace,
1436 ts('more'),
1437 FALSE,
1438 'relationship.selector.row',
1439 'Relationship',
1440 $rid);
6a488035
TO
1441 unset($links[CRM_Core_Action::MAX_ACTION]);
1442 }
1443 }
1444
1445 $relationship->free();
1446 return $values;
1447 }
1448 }
1449
1450 /**
100fef9d 1451 * Get get list of relationship type based on the target contact type.
6a488035 1452 *
77c5b619
TO
1453 * @param string $targetContactType
1454 * It's valid contact tpye(may be Individual , Organization , Household).
6a488035 1455 *
a6c01b45
CW
1456 * @return array
1457 * array reference of all relationship types with context to current contact type .
6a488035 1458 */
ee17a760 1459 static public function getRelationType($targetContactType) {
6a488035
TO
1460 $relationshipType = array();
1461 $allRelationshipType = CRM_Core_PseudoConstant::relationshipType();
1462
1463 foreach ($allRelationshipType as $key => $type) {
1464 if ($type['contact_type_b'] == $targetContactType) {
1465 $relationshipType[$key . '_a_b'] = $type['label_a_b'];
1466 }
1467 }
1468
1469 return $relationshipType;
1470 }
1471
1472 /**
100fef9d 1473 * Create / update / delete membership for related contacts.
6a488035
TO
1474 *
1475 * This function will create/update/delete membership for related
1476 * contact based on 1) contact have active membership 2) that
1477 * membership is is extedned by the same relationship type to that
1478 * of the existing relationship.
1479 *
5a4f6742
CW
1480 * @param int $contactId
1481 * contact id.
1482 * @param array $params
1483 * array of values submitted by POST.
1484 * @param array $ids
1485 * array of ids.
bfa4da96 1486 * @param \const|int $action which action called this function
6a488035 1487 *
dd244018 1488 * @param bool $active
6a488035 1489 *
bfa4da96 1490 * @throws \CRM_Core_Exception
6a488035 1491 */
00be9182 1492 public static function relatedMemberships($contactId, &$params, $ids, $action = CRM_Core_Action::ADD, $active = TRUE) {
6a488035 1493 // Check the end date and set the status of the relationship
decc60a0 1494 // accordingly.
6a488035 1495 $status = self::CURRENT;
04ad3598 1496 $targetContact = $targetContact = CRM_Utils_Array::value('contact_check', $params, array());
45089d88
CW
1497 $today = date('Ymd');
1498
1499 // If a relationship hasn't yet started, just return for now
1500 // TODO: handle edge-case of updating start_date of an existing relationship
1501 if (!empty($params['start_date'])) {
1502 $startDate = substr(CRM_Utils_Date::format($params['start_date']), 0, 8);
1503 if ($today < $startDate) {
1504 return;
1505 }
1506 }
6a488035
TO
1507
1508 if (!empty($params['end_date'])) {
45089d88 1509 $endDate = substr(CRM_Utils_Date::format($params['end_date']), 0, 8);
6a488035
TO
1510 if ($today > $endDate) {
1511 $status = self::PAST;
1512 }
1513 }
1514
45089d88
CW
1515 if (($action & CRM_Core_Action::ADD) && ($status & self::PAST)) {
1516 // If relationship is PAST and action is ADD, do nothing.
6a488035
TO
1517 return;
1518 }
1519
1520 $rel = explode('_', $params['relationship_type_id']);
1521
7f3647bc 1522 $relTypeId = $rel[0];
decc60a0
EM
1523 if (!empty($rel[1])) {
1524 $relDirection = "_{$rel[1]}_{$rel[2]}";
1525 }
1526 else {
1527 // this call is coming from somewhere where the direction was resolved early on (e.g an api call)
1528 // so we can assume _a_b
1529 $relDirection = "_a_b";
04ad3598 1530 $targetContact = array($params['contact_id_b'] => 1);
decc60a0 1531 }
04ad3598 1532
6a488035
TO
1533 if (($action & CRM_Core_Action::ADD) ||
1534 ($action & CRM_Core_Action::DELETE)
1535 ) {
1536 $contact = $contactId;
6a488035
TO
1537 }
1538 elseif ($action & CRM_Core_Action::UPDATE) {
1539 $contact = $ids['contact'];
1540 $targetContact = array($ids['contactTarget'] => 1);
1541 }
1542
1543 // Build the 'values' array for
1544 // 1. ContactA
1545 // 2. ContactB
1546 // This will allow us to check if either of the contacts in
1547 // relationship have active memberships.
1548
1549 $values = array();
1550
1551 // 1. ContactA
1552 $values[$contact] = array(
1553 'relatedContacts' => $targetContact,
1554 'relationshipTypeId' => $relTypeId,
1555 'relationshipTypeDirection' => $relDirection,
1556 );
1557 // 2. ContactB
1558 if (!empty($targetContact)) {
1559 foreach ($targetContact as $cid => $donCare) {
1560 $values[$cid] = array(
1561 'relatedContacts' => array($contact => 1),
1562 'relationshipTypeId' => $relTypeId,
1563 );
1564
1565 $relTypeParams = array('id' => $relTypeId);
1566 $relTypeValues = array();
1567 CRM_Contact_BAO_RelationshipType::retrieve($relTypeParams, $relTypeValues);
1568
1569 if (CRM_Utils_Array::value('name_a_b', $relTypeValues) == CRM_Utils_Array::value('name_b_a', $relTypeValues)) {
1570 $values[$cid]['relationshipTypeDirection'] = '_a_b';
1571 }
1572 else {
1573 $values[$cid]['relationshipTypeDirection'] = ($relDirection == '_a_b') ? '_b_a' : '_a_b';
1574 }
1575 }
1576 }
1577
bd655ee6
MV
1578 // CRM-15829 UPDATES
1579 // If we're looking for active memberships we must consider pending (id: 5) ones too.
1580 // Hence we can't just call CRM_Member_BAO_Membership::getValues below with the active flag, is it would completely miss pending relatioships.
3421dcee
MV
1581 // As suggested by @davecivicrm, the pending status id is fetched using the CRM_Member_PseudoConstant::membershipStatus() class and method, since these ids differ from system to system.
1582 $pendingStatusId = array_search('Pending', CRM_Member_PseudoConstant::membershipStatus());
bd655ee6
MV
1583
1584 $query = 'SELECT * FROM `civicrm_membership_status`';
1585 if ($active) {
51d0ad3d 1586 $query .= ' WHERE `is_current_member` = 1 OR `id` = %1 ';
bd655ee6
MV
1587 }
1588
51d0ad3d 1589 $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($pendingStatusId, 'Integer')));
3421dcee 1590
bd655ee6
MV
1591 while ($dao->fetch()) {
1592 $membershipStatusRecordIds[$dao->id] = $dao->id;
1593 }
1594
6a488035
TO
1595 // Now get the active memberships for all the contacts.
1596 // If contact have any valid membership(s), then add it to
1597 // 'values' array.
1598 foreach ($values as $cid => $subValues) {
1599 $memParams = array('contact_id' => $cid);
1600 $memberships = array();
1601
bd655ee6
MV
1602 // CRM-15829 UPDATES
1603 // Since we want PENDING memberships as well, the $active flag needs to be set to false so that this will return all memberships and we can then filter the memberships based on the status IDs recieved above.
1604 CRM_Member_BAO_Membership::getValues($memParams, $memberships, FALSE, TRUE);
1605
1606 // CRM-15829 UPDATES
1607 // filter out the memberships returned by CRM_Member_BAO_Membership::getValues based on the status IDs fetched on line ~1462
1608 foreach ($memberships as $key => $membership) {
1609
1610 if (!isset($memberships[$key]['status_id'])) {
1611 continue;
1612 }
1613
1614 $membershipStatusId = $memberships[$key]['status_id'];
1615 if (!isset($membershipStatusRecordIds[$membershipStatusId])) {
1616 unset($memberships[$key]);
1617 }
1618 }
6a488035
TO
1619
1620 if (empty($memberships)) {
1621 continue;
1622 }
1623
f1e48e7f 1624 //get ownerMembershipIds for related Membership
1625 //this is to handle memberships being deleted and recreated
1626 if (!empty($memberships['owner_membership_ids'])) {
91b00626 1627 $ownerMemIds[$cid] = $memberships['owner_membership_ids'];
f1e48e7f 1628 unset($memberships['owner_membership_ids']);
1629 }
1630
6a488035
TO
1631 $values[$cid]['memberships'] = $memberships;
1632 }
1633 $deceasedStatusId = array_search('Deceased', CRM_Member_PseudoConstant::membershipStatus());
1634
1635 // done with 'values' array.
1636 // Finally add / edit / delete memberships for the related contacts
ee17a760 1637
6a488035
TO
1638 foreach ($values as $cid => $details) {
1639 if (!array_key_exists('memberships', $details)) {
1640 continue;
1641 }
1642
25f1372e 1643 $relatedContacts = array_keys(CRM_Utils_Array::value('relatedContacts', $details, array()));
ee17a760 1644 $mainRelatedContactId = reset($relatedContacts);
6a488035
TO
1645
1646 foreach ($details['memberships'] as $membershipId => $membershipValues) {
1647 $relTypeIds = array();
1648 if ($action & CRM_Core_Action::DELETE) {
1649 // Delete memberships of the related contacts only if relationship type exists for membership type
1650 $query = "
1651SELECT relationship_type_id, relationship_direction
1652 FROM civicrm_membership_type
1653 WHERE id = {$membershipValues['membership_type_id']}";
1654 $dao = CRM_Core_DAO::executeQuery($query);
1655 $relTypeDirs = array();
1656 while ($dao->fetch()) {
1657 $relTypeId = $dao->relationship_type_id;
1658 $relDirection = $dao->relationship_direction;
1659 }
1660 $relTypeIds = explode(CRM_Core_DAO::VALUE_SEPARATOR, $relTypeId);
4d88abcc 1661 if (in_array($values[$cid]['relationshipTypeId'], $relTypeIds
1662 //CRM-16300 check if owner membership exist for related membership
1663 ) && !empty($membershipValues['owner_membership_id']) && !empty($values[$mainRelatedContactId]['memberships'][$membershipValues['owner_membership_id']])) {
690c56c3 1664 CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipValues['owner_membership_id'], $membershipValues['membership_contact_id']);
6a488035
TO
1665 }
1666 continue;
1667 }
1668 if (($action & CRM_Core_Action::UPDATE) &&
1669 ($status & self::PAST) &&
1670 ($membershipValues['owner_membership_id'])
1671 ) {
1672 // If relationship is PAST and action is UPDATE
1673 // then delete the RELATED membership
1674 CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipValues['owner_membership_id'],
1675 $membershipValues['membership_contact_id']
1676 );
1677 continue;
1678 }
1679
1680 // add / edit the memberships for related
1681 // contacts.
1682
1683 // Get the Membership Type Details.
1684 $membershipType = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($membershipValues['membership_type_id']);
1685 // Check if contact's relationship type exists in membership type
1686 $relTypeDirs = array();
a7488080 1687 if (!empty($membershipType['relationship_type_id'])) {
6a488035
TO
1688 $relTypeIds = explode(CRM_Core_DAO::VALUE_SEPARATOR, $membershipType['relationship_type_id']);
1689 }
a7488080 1690 if (!empty($membershipType['relationship_direction'])) {
6a488035
TO
1691 $relDirections = explode(CRM_Core_DAO::VALUE_SEPARATOR, $membershipType['relationship_direction']);
1692 }
1693 foreach ($relTypeIds as $key => $value) {
1694 $relTypeDirs[] = $value . '_' . $relDirections[$key];
1695 }
1696 $relTypeDir = $details['relationshipTypeId'] . $details['relationshipTypeDirection'];
1697 if (in_array($relTypeDir, $relTypeDirs)) {
1698 // Check if relationship being created/updated is
1699 // similar to that of membership type's
1700 // relationship.
1701
1702 $membershipValues['owner_membership_id'] = $membershipId;
1703 unset($membershipValues['id']);
1704 unset($membershipValues['membership_contact_id']);
1705 unset($membershipValues['contact_id']);
1706 unset($membershipValues['membership_id']);
1707 foreach ($details['relatedContacts'] as $relatedContactId => $donCare) {
1708 $membershipValues['contact_id'] = $relatedContactId;
1709 if ($deceasedStatusId &&
1710 CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $relatedContactId, 'is_deceased')
1711 ) {
1712 $membershipValues['status_id'] = $deceasedStatusId;
1713 $membershipValues['skipStatusCal'] = TRUE;
1714 }
1715 foreach (array(
7f3647bc
TO
1716 'join_date',
1717 'start_date',
21dfd5f5 1718 'end_date',
7f3647bc 1719 ) as $dateField) {
a7488080 1720 if (!empty($membershipValues[$dateField])) {
6a488035
TO
1721 $membershipValues[$dateField] = CRM_Utils_Date::processDate($membershipValues[$dateField]);
1722 }
1723 }
1724
e72dea83 1725 if ($action & CRM_Core_Action::UPDATE) {
1726 //if updated relationship is already related to contact don't delete existing inherited membership
1727 if (in_array($relTypeId, $relTypeIds
1728 ) && !empty($values[$relatedContactId]['memberships']) && !empty($ownerMemIds
1729 ) && in_array($membershipValues['owner_membership_id'], $ownerMemIds[$relatedContactId])) {
1730 continue;
1731 }
1732
1733 //delete the membership record for related
1734 //contact before creating new membership record.
1735 CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipId, $relatedContactId);
1736 }
1737
6a488035
TO
1738 // check whether we have some related memberships still available
1739 $query = "
1740SELECT count(*)
1741 FROM civicrm_membership
1742 LEFT JOIN civicrm_membership_status ON (civicrm_membership_status.id = civicrm_membership.status_id)
1743 WHERE membership_type_id = {$membershipValues['membership_type_id']} AND owner_membership_id = {$membershipValues['owner_membership_id']}
1744 AND is_current_member = 1";
1745 $result = CRM_Core_DAO::singleValueQuery($query);
1746 if ($result < CRM_Utils_Array::value('max_related', $membershipValues, PHP_INT_MAX)) {
43291913 1747 CRM_Member_BAO_Membership::create($membershipValues, CRM_Core_DAO::$_nullArray);
6a488035
TO
1748 }
1749 }
1750 }
1751 elseif ($action & CRM_Core_Action::UPDATE) {
1752 // if action is update and updated relationship do
1753 // not match with the existing
1754 // membership=>relationship then we need to
e62adec9 1755 // change the status of the membership record to expired for
1756 // previous relationship -- CRM-12078.
1757 // CRM-16087 we need to pass ownerMembershipId to isRelatedMembershipExpired function
690c56c3 1758 if (empty($params['relationship_ids']) && !empty($params['id'])) {
1759 $relIds = array($params['id']);
1760 }
1761 else {
1762 $relIds = CRM_Utils_Array::value('relationship_ids', $params);
1763 }
e62adec9 1764 if (self::isRelatedMembershipExpired($relTypeIds, $contactId, $mainRelatedContactId, $relTypeId,
4d88abcc 1765 $relIds) && !empty($membershipValues['owner_membership_id']
1766 ) && !empty($values[$mainRelatedContactId]['memberships'][$membershipValues['owner_membership_id']])) {
e62adec9 1767 $membershipValues['status_id'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipStatus', 'Expired', 'id', 'label');
1768 $type = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $membershipValues['membership_type_id'], 'name', 'id');
1769 CRM_Member_BAO_Membership::add($membershipValues);
1770 CRM_Core_Session::setStatus(ts("Inherited membership {$type} status was changed to Expired due to the change in relationship type."), ts('Record Updated'), 'alert');
6a488035
TO
1771 }
1772 }
1773 }
1774 }
1775 }
1776
1777 /**
e62adec9 1778 * Helper function to check whether the membership is expired or not.
6616f7c1
EM
1779 *
1780 * Function takes a list of related membership types and if it is not also passed a
e62adec9 1781 * relationship ID of that types evaluates whether the membership status should be changed to expired.
6616f7c1
EM
1782 *
1783 * @param array $membershipTypeRelationshipTypeIDs
1784 * Relation type IDs related to the given membership type.
1785 * @param int $contactId
1786 * @param int $mainRelatedContactId
1787 * @param int $relTypeId
1788 * @param array $relIds
1789 *
1790 * @return bool
6a488035 1791 */
e62adec9 1792 public static function isRelatedMembershipExpired($membershipTypeRelationshipTypeIDs, $contactId, $mainRelatedContactId, $relTypeId, $relIds) {
6616f7c1 1793 if (empty($membershipTypeRelationshipTypeIDs) || in_array($relTypeId, $membershipTypeRelationshipTypeIDs)) {
eec8d770 1794 return FALSE;
6a488035
TO
1795 }
1796
1797 if (empty($relIds)) {
1798 return FALSE;
1799 }
1800
7f3647bc
TO
1801 $relParamas = array(
1802 1 => array($contactId, 'Integer'),
6a488035
TO
1803 2 => array($mainRelatedContactId, 'Integer'),
1804 );
1805
1806 if ($contactId == $mainRelatedContactId) {
6616f7c1
EM
1807 $recordsFound = (int) CRM_Core_DAO::singleValueQuery("SELECT COUNT(*) FROM civicrm_relationship WHERE relationship_type_id IN ( " . implode(',', $membershipTypeRelationshipTypeIDs) . " ) AND
1808contact_id_a IN ( %1 ) OR contact_id_b IN ( %1 ) AND id IN (" . implode(',', $relIds) . ")", $relParamas);
6a488035
TO
1809 if ($recordsFound) {
1810 return FALSE;
1811 }
1812 return TRUE;
1813 }
1814
6616f7c1 1815 $recordsFound = (int) CRM_Core_DAO::singleValueQuery("SELECT COUNT(*) FROM civicrm_relationship WHERE relationship_type_id IN ( " . implode(',', $membershipTypeRelationshipTypeIDs) . " ) AND contact_id_a IN ( %1, %2 ) AND contact_id_b IN ( %1, %2 ) AND id NOT IN (" . implode(',', $relIds) . ")", $relParamas);
6a488035
TO
1816
1817 if ($recordsFound) {
1818 return FALSE;
1819 }
1820
1821 return TRUE;
1822 }
1823
1824 /**
fe482240 1825 * Get Current Employer for Contact.
6a488035 1826 *
77c5b619
TO
1827 * @param $contactIds
1828 * Contact Ids.
6a488035 1829 *
a6c01b45
CW
1830 * @return array
1831 * array of the current employer
6a488035 1832 */
00be9182 1833 public static function getCurrentEmployer($contactIds) {
6a488035
TO
1834 $contacts = implode(',', $contactIds);
1835
1836 $query = "
1837SELECT organization_name, id, employer_id
1838FROM civicrm_contact
1839WHERE id IN ( {$contacts} )
1840";
1841
33621c4f 1842 $dao = CRM_Core_DAO::executeQuery($query);
6a488035
TO
1843 $currentEmployer = array();
1844 while ($dao->fetch()) {
1845 $currentEmployer[$dao->id]['org_id'] = $dao->employer_id;
1846 $currentEmployer[$dao->id]['org_name'] = $dao->organization_name;
1847 }
1848
1849 return $currentEmployer;
1850 }
1851
7f3647bc 1852 /**
fe482240 1853 * Function to return list of permissioned contacts for a given contact and relationship type.
7f3647bc 1854 *
5a4f6742
CW
1855 * @param int $contactID
1856 * contact id whose permissioned contacts are to be found.
b0076fe6 1857 * @param int $relTypeId
5a4f6742
CW
1858 * one or more relationship type id's.
1859 * @param string $name
33260076 1860 * @param string $contactType
7f3647bc 1861 *
a6c01b45 1862 * @return array
16b10e64 1863 * Array of contacts
7f3647bc 1864 */
33260076 1865 public static function getPermissionedContacts($contactID, $relTypeId = NULL, $name = NULL, $contactType = NULL) {
51e89def 1866 $contacts = array();
b0076fe6 1867 $args = array(1 => array($contactID, 'Integer'));
33260076 1868 $relationshipTypeClause = $contactTypeClause = '';
51e89def 1869
6a488035 1870 if ($relTypeId) {
b0076fe6
EM
1871 // @todo relTypeId is only ever passed in as an int. Change this to reflect that -
1872 // probably being overly conservative by not doing so but working on stable release.
1873 $relationshipTypeClause = 'AND cr.relationship_type_id IN (%2) ';
1874 $args[2] = array($relTypeId, 'String');
1875 }
33260076 1876
1877 if ($contactType) {
1878 $contactTypeClause = ' AND cr.relationship_type_id = crt.id AND crt.contact_type_b = %3 ';
1879 $args[3] = array($contactType, 'String');
1880 }
1881
4779abb3 1882 $query = "
6a488035 1883SELECT cc.id as id, cc.sort_name as name
33260076 1884FROM civicrm_relationship cr, civicrm_contact cc, civicrm_relationship_type crt
49f8272d 1885WHERE
51e89def 1886cr.contact_id_a = %1 AND
51e89def 1887cr.is_permission_a_b = 1 AND
6a488035
TO
1888IF(cr.end_date IS NULL, 1, (DATEDIFF( CURDATE( ), cr.end_date ) <= 0)) AND
1889cr.is_active = 1 AND
7ecf6275 1890cc.id = cr.contact_id_b AND
b0076fe6
EM
1891cc.is_deleted = 0
1892$relationshipTypeClause
33260076 1893$contactTypeClause
b0076fe6 1894";
51e89def 1895
4779abb3 1896 if (!empty($name)) {
1897 $name = CRM_Utils_Type::escape($name, 'String');
1898 $query .= "
49f8272d 1899AND cc.sort_name LIKE '%$name%'";
4779abb3 1900 }
6a488035 1901
4779abb3 1902 $dao = CRM_Core_DAO::executeQuery($query, $args);
1903 while ($dao->fetch()) {
1904 $contacts[$dao->id] = array(
1905 'name' => $dao->name,
1906 'value' => $dao->id,
1907 );
1908 }
b0076fe6 1909
51e89def 1910 return $contacts;
6a488035
TO
1911 }
1912
6a488035 1913 /**
fe482240 1914 * Merge relationships from otherContact to mainContact.
bfa4da96 1915 *
6a488035
TO
1916 * Called during contact merge operation
1917 *
77c5b619
TO
1918 * @param int $mainId
1919 * Contact id of main contact record.
1920 * @param int $otherId
1921 * Contact id of record which is going to merge.
1922 * @param array $sqls
1923 * (reference) array of sql statements to append to.
6a488035
TO
1924 *
1925 * @see CRM_Dedupe_Merger::cpTables()
6a488035 1926 */
00be9182 1927 public static function mergeRelationships($mainId, $otherId, &$sqls) {
6a488035
TO
1928 // Delete circular relationships
1929 $sqls[] = "DELETE FROM civicrm_relationship
1930 WHERE (contact_id_a = $mainId AND contact_id_b = $otherId)
1931 OR (contact_id_b = $mainId AND contact_id_a = $otherId)";
1932
1933 // Delete relationship from other contact if main contact already has that relationship
1934 $sqls[] = "DELETE r2
1935 FROM civicrm_relationship r1, civicrm_relationship r2
1936 WHERE r1.relationship_type_id = r2.relationship_type_id
1937 AND r1.id <> r2.id
1938 AND (
1939 r1.contact_id_a = $mainId AND r2.contact_id_a = $otherId AND r1.contact_id_b = r2.contact_id_b
1940 OR r1.contact_id_b = $mainId AND r2.contact_id_b = $otherId AND r1.contact_id_a = r2.contact_id_a
1941 OR (
1942 (r1.contact_id_a = $mainId AND r2.contact_id_b = $otherId AND r1.contact_id_b = r2.contact_id_a
1943 OR r1.contact_id_b = $mainId AND r2.contact_id_a = $otherId AND r1.contact_id_a = r2.contact_id_b)
1944 AND r1.relationship_type_id IN (SELECT id FROM civicrm_relationship_type WHERE name_b_a = name_a_b)
1945 )
1946 )";
1947
1948 // Move relationships
1949 $sqls[] = "UPDATE IGNORE civicrm_relationship SET contact_id_a = $mainId WHERE contact_id_a = $otherId";
1950 $sqls[] = "UPDATE IGNORE civicrm_relationship SET contact_id_b = $mainId WHERE contact_id_b = $otherId";
1951
1952 // Move current employer id (name will get updated later)
1953 $sqls[] = "UPDATE civicrm_contact SET employer_id = $mainId WHERE employer_id = $otherId";
1954 }
1955
1956 /**
1957 * Set 'is_valid' field to false for all relationships whose end date is in the past, ie. are expired.
1958 *
72b3a70c
CW
1959 * @return bool
1960 * True on success, false if error is encountered.
6a488035 1961 */
00be9182 1962 public static function disableExpiredRelationships() {
6a488035
TO
1963 $query = "SELECT id FROM civicrm_relationship WHERE is_active = 1 AND end_date < CURDATE()";
1964
1965 $dao = CRM_Core_DAO::executeQuery($query);
1966 while ($dao->fetch()) {
1967 $result = CRM_Contact_BAO_Relationship::setIsActive($dao->id, FALSE);
1968 // Result will be NULL if error occurred. We abort early if error detected.
1969 if ($result == NULL) {
1970 return FALSE;
1971 }
1972 }
1973 return TRUE;
1974 }
c9c41397 1975
1976 /**
fe482240 1977 * Function filters the query by possible relationships for the membership type.
98a06ae0 1978 *
c9c41397 1979 * It is intended to be called when constructing queries for the api (reciprocal & non-reciprocal)
1980 * and to add clauses to limit the return to those relationships which COULD inherit a membership type
1981 * (as opposed to those who inherit a particular membership
1982 *
77c5b619
TO
1983 * @param array $params
1984 * Api input array.
77b97be7
EM
1985 * @param null $direction
1986 *
c301f76e 1987 * @return array|void
c9c41397 1988 */
00be9182 1989 public static function membershipTypeToRelationshipTypes(&$params, $direction = NULL) {
7f3647bc 1990 $membershipType = civicrm_api3('membership_type', 'getsingle', array(
353ffa53
TO
1991 'id' => $params['membership_type_id'],
1992 'return' => 'relationship_type_id, relationship_direction',
1993 ));
c9c41397 1994 $relationshipTypes = $membershipType['relationship_type_id'];
22e263ad 1995 if (empty($relationshipTypes)) {
c301f76e 1996 return NULL;
f201289d 1997 }
c9c41397 1998 // if we don't have any contact data we can only filter on type
22e263ad 1999 if (empty($params['contact_id']) && empty($params['contact_id_a']) && empty($params['contact_id_a'])) {
c9c41397 2000 $params['relationship_type_id'] = array('IN' => $relationshipTypes);
c301f76e 2001 return NULL;
c9c41397 2002 }
2003 else {
1a9b2ee8 2004 $relationshipDirections = (array) $membershipType['relationship_direction'];
c9c41397 2005 // if we have contact_id_a OR contact_id_b we can make a call here
2006 // if we have contact??
2007 foreach ($relationshipDirections as $index => $mtdirection) {
7f3647bc 2008 if (isset($params['contact_id_a']) && $mtdirection == 'a_b' || $direction == 'a_b') {
c9c41397 2009 $types[] = $relationshipTypes[$index];
2010 }
7f3647bc 2011 if (isset($params['contact_id_b']) && $mtdirection == 'b_a' || $direction == 'b_a') {
c9c41397 2012 $types[] = $relationshipTypes[$index];
2013 }
2014 }
22e263ad 2015 if (!empty($types)) {
c9c41397 2016 $params['relationship_type_id'] = array('IN' => $types);
2017 }
7f3647bc 2018 elseif (!empty($clauses)) {
c9c41397 2019 return explode(' OR ', $clauses);
2020 }
92e4c2a5 2021 else {
c9c41397 2022 // effectively setting it to return no results
2023 $params['relationship_type_id'] = 0;
2024 }
2025 }
2026 }
40458f6c 2027
2028
2029 /**
98a06ae0 2030 * Wrapper for contact relationship selector.
40458f6c 2031 *
77c5b619
TO
2032 * @param array $params
2033 * Associated array for params record id.
40458f6c 2034 *
a6c01b45
CW
2035 * @return array
2036 * associated array of contact relationships
40458f6c 2037 */
2038 public static function getContactRelationshipSelector(&$params) {
2039 // format the params
7f3647bc
TO
2040 $params['offset'] = ($params['page'] - 1) * $params['rp'];
2041 $params['sort'] = CRM_Utils_Array::value('sortBy', $params);
40458f6c 2042
2043 if ($params['context'] == 'past') {
2044 $relationshipStatus = CRM_Contact_BAO_Relationship::INACTIVE;
2045 }
62e6afce 2046 elseif ($params['context'] == 'all') {
6c292184
TM
2047 $relationshipStatus = CRM_Contact_BAO_Relationship::ALL;
2048 }
40458f6c 2049 else {
2050 $relationshipStatus = CRM_Contact_BAO_Relationship::CURRENT;
2051 }
2052
2053 // check logged in user for permission
2054 $page = new CRM_Core_Page();
2055 CRM_Contact_Page_View::checkUserPermission($page, $params['contact_id']);
2056 $permissions = array($page->_permission);
2057 if ($page->_permission == CRM_Core_Permission::EDIT) {
2058 $permissions[] = CRM_Core_Permission::DELETE;
2059 }
2060 $mask = CRM_Core_Action::mask($permissions);
2061
a93664c8 2062 $permissionedContacts = TRUE;
d0592c3d 2063 if ($params['context'] != 'user') {
2064 $links = CRM_Contact_Page_View_Relationship::links();
d0592c3d 2065 }
2066 else {
2067 $links = CRM_Contact_Page_View_UserDashBoard::links();
d0592c3d 2068 $mask = NULL;
2069 }
40458f6c 2070 // get contact relationships
2071 $relationships = CRM_Contact_BAO_Relationship::getRelationship($params['contact_id'],
2072 $relationshipStatus,
2073 $params['rp'], 0, 0,
d0592c3d 2074 $links, $mask,
2075 $permissionedContacts,
644587aa 2076 $params, TRUE
40458f6c 2077 );
2078
2079 $contactRelationships = array();
644587aa
SL
2080 $params['total'] = $relationships['total_relationships'];
2081 unset($relationships['total_relationships']);
40458f6c 2082 if (!empty($relationships)) {
40458f6c 2083
2084 // format params
2085 foreach ($relationships as $relationshipId => $values) {
7d12de7f
JL
2086 $relationship = array();
2087
febb6506 2088 $relationship['DT_RowId'] = $values['id'];
7d12de7f
JL
2089 $relationship['DT_RowClass'] = 'crm-entity';
2090 if ($values['is_active'] == 0) {
2091 $relationship['DT_RowClass'] .= ' disabled';
2092 }
2093
febb6506
JL
2094 $relationship['DT_RowAttr'] = array();
2095 $relationship['DT_RowAttr']['data-entity'] = 'relationship';
2096 $relationship['DT_RowAttr']['data-id'] = $values['id'];
7d12de7f 2097
20be4ac3
BS
2098 //Add image icon for related contacts: CRM-14919; CRM-19668
2099 $contactType = (!empty($values['contact_sub_type'])) ? $values['contact_sub_type'] : $values['contact_type'];
2100 $icon = CRM_Contact_BAO_Contact_Utils::getImage($contactType,
67e4fb51
N
2101 FALSE,
2102 $values['cid']
2103 );
7d12de7f 2104 $relationship['sort_name'] = $icon . ' ' . CRM_Utils_System::href(
7f3647bc
TO
2105 $values['name'],
2106 'civicrm/contact/view',
2107 "reset=1&cid={$values['cid']}");
40458f6c 2108
7d12de7f 2109 $relationship['relation'] = CRM_Utils_System::href(
40458f6c 2110 $values['relation'],
2111 'civicrm/contact/view/rel',
f1cb718d 2112 "action=view&reset=1&cid={$values['cid']}&id={$values['id']}&rtype={$values['rtype']}");
40458f6c 2113
d0592c3d 2114 if ($params['context'] == 'current') {
40458f6c 2115 if (($params['contact_id'] == $values['contact_id_a'] AND $values['is_permission_a_b'] == 1) OR
2116 ($params['contact_id'] == $values['contact_id_b'] AND $values['is_permission_b_a'] == 1)
2117 ) {
7d12de7f 2118 $relationship['sort_name'] .= '<span id="permission-a-b" class="crm-marker permission-relationship"> *</span>';
40458f6c 2119 }
2120
2121 if (($values['cid'] == $values['contact_id_a'] AND $values['is_permission_a_b'] == 1) OR
2122 ($values['cid'] == $values['contact_id_b'] AND $values['is_permission_b_a'] == 1)
2123 ) {
7d12de7f 2124 $relationship['relation'] .= '<span id="permission-b-a" class="crm-marker permission-relationship"> *</span>';
40458f6c 2125 }
2126 }
2127
2128 if (!empty($values['description'])) {
7d12de7f 2129 $relationship['relation'] .= "<p class='description'>{$values['description']}</p>";
40458f6c 2130 }
2131
7d12de7f
JL
2132 $relationship['start_date'] = CRM_Utils_Date::customFormat($values['start_date']);
2133 $relationship['end_date'] = CRM_Utils_Date::customFormat($values['end_date']);
2134 $relationship['city'] = $values['city'];
2135 $relationship['state'] = $values['state'];
2136 $relationship['email'] = $values['email'];
2137 $relationship['phone'] = $values['phone'];
2138 $relationship['links'] = $values['action'];
2139
2140 array_push($contactRelationships, $relationship);
40458f6c 2141 }
2142 }
7d12de7f
JL
2143
2144 $relationshipsDT = array();
2145 $relationshipsDT['data'] = $contactRelationships;
2146 $relationshipsDT['recordsTotal'] = $params['total'];
2147 $relationshipsDT['recordsFiltered'] = $params['total'];
2148
2149 return $relationshipsDT;
40458f6c 2150 }
2151
89e45979
MD
2152 /**
2153 * @inheritdoc
2154 */
2155 public static function buildOptions($fieldName, $context = NULL, $props = array()) {
2156 if ($fieldName === 'relationship_type_id') {
2157 return self::buildRelationshipTypeOptions($props);
2158 }
2159
2160 return parent::buildOptions($fieldName, $context, $props);
2161 }
2162
2163 /**
2164 * Builds a list of options available for relationship types
2165 *
2166 * @param array $params
2167 * - contact_type: Limits by contact type on the "A" side
2168 * - relationship_id: Used to find the value for contact type for "B" side.
2169 * If contact_a matches provided contact_id then type of contact_b will
2170 * be used. Otherwise uses type of contact_a. Must be used with contact_id
2171 * - contact_id: Limits by contact types of this contact on the "A" side
2172 * - is_form: Returns array with keys indexed for use in a quickform
2173 * - relationship_direction: For relationship types with duplicate names
2174 * on both sides, defines which option should be returned, a_b or b_a
2175 *
2176 * @return array
2177 */
2178 public static function buildRelationshipTypeOptions($params = array()) {
2179 $contactId = CRM_Utils_Array::value('contact_id', $params);
2180 $direction = CRM_Utils_Array::value('relationship_direction', $params, 'a_b');
2181 $relationshipId = CRM_Utils_Array::value('relationship_id', $params);
2182 $contactType = CRM_Utils_Array::value('contact_type', $params);
2183 $isForm = CRM_Utils_Array::value('is_form', $params);
2184 $showAll = FALSE;
2185
2186 // getContactRelationshipType will return an empty set if these are not set
2187 if (!$contactId && !$relationshipId && !$contactType) {
2188 $showAll = TRUE;
2189 }
2190
2191 $labels = self::getContactRelationshipType(
2192 $contactId,
2193 $direction,
2194 $relationshipId,
2195 $contactType,
2196 $showAll,
2197 'label'
2198 );
2199
2200 if ($isForm) {
2201 return $labels;
2202 }
2203
2204 $names = self::getContactRelationshipType(
2205 $contactId,
2206 $direction,
2207 $relationshipId,
2208 $contactType,
2209 $showAll,
2210 'name'
2211 );
2212
2213 // ensure $names contains only entries in $labels
2214 $names = array_intersect_key($names, $labels);
2215
2216 $nameToLabels = array_combine($names, $labels);
2217
2218 return $nameToLabels;
2219 }
2220
6a488035 2221}