INFRA-132 - Civi - PHPStorm cleanup
[civicrm-core.git] / CRM / Contact / BAO / ContactType.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35class CRM_Contact_BAO_ContactType extends CRM_Contact_DAO_ContactType {
36
37 /**
c490a46a 38 * Fetch object based on array of properties
6a488035 39 *
77c5b619
TO
40 * @param array $params
41 * (reference ) an assoc array of name/value pairs.
42 * @param array $defaults
43 * (reference ) an assoc array to hold the flattened values.
6a488035 44 *
c490a46a 45 * @return CRM_Contact_BAO_ContactType object on success, null otherwise
6a488035
TO
46 * @static
47 */
00be9182 48 public static function retrieve(&$params, &$defaults) {
6a488035
TO
49 $contactType = new CRM_Contact_DAO_ContactType();
50 $contactType->copyValues($params);
51 if ($contactType->find(TRUE)) {
52 CRM_Core_DAO::storeValues($contactType, $defaults);
53 return $contactType;
54 }
55 return NULL;
56 }
57
86538308
EM
58 /**
59 * @param $contactType
60 *
61 * @return bool
62 */
00be9182 63 public static function isActive($contactType) {
6a488035
TO
64 $contact = self::contactTypeInfo(FALSE);
65 $active = array_key_exists($contactType, $contact) ? TRUE : FALSE;
66 return $active;
67 }
68
69 /**
c490a46a 70 * Retrieve basic contact type information.
6a488035 71 *
dd244018 72 * @param bool $all
6a488035 73 *
a6c01b45
CW
74 * @return array
75 * of basic contact types information.
dd244018 76 * @static
6a488035 77 */
00be9182 78 public static function &basicTypeInfo($all = FALSE) {
6a488035
TO
79 static $_cache = NULL;
80
81 if ($_cache === NULL) {
82 $_cache = array();
83 }
84
85 $argString = $all ? 'CRM_CT_BTI_1' : 'CRM_CT_BTI_0';
86 if (!array_key_exists($argString, $_cache)) {
87 $cache = CRM_Utils_Cache::singleton();
88 $_cache[$argString] = $cache->get($argString);
89 if (!$_cache[$argString]) {
90 $sql = "
91SELECT *
92FROM civicrm_contact_type
93WHERE parent_id IS NULL
94";
95 if ($all === FALSE) {
96 $sql .= " AND is_active = 1";
97 }
98
99 $dao = CRM_Core_DAO::executeQuery($sql,
100 CRM_Core_DAO::$_nullArray,
101 FALSE,
102 'CRM_Contact_DAO_ContactType'
103 );
104 while ($dao->fetch()) {
105 $value = array();
106 CRM_Core_DAO::storeValues($dao, $value);
107 $_cache[$argString][$dao->name] = $value;
108 }
109
110 $cache->set($argString, $_cache[$argString]);
111 }
112 }
113 return $_cache[$argString];
114 }
115
116 /**
c490a46a 117 * Retrieve all basic contact types.
6a488035 118 *
da6b46f4 119 * @param bool $all
6a488035 120 *
a6c01b45
CW
121 * @return array
122 * of basic contact types
da6b46f4 123 * @static
6a488035 124 */
00be9182 125 public static function basicTypes($all = FALSE) {
6a488035
TO
126 return array_keys(self::basicTypeInfo($all));
127 }
128
86538308
EM
129 /**
130 * @param bool $all
131 * @param string $key
132 *
133 * @return array
134 */
00be9182 135 public static function basicTypePairs($all = FALSE, $key = 'name') {
6a488035
TO
136 $subtypes = self::basicTypeInfo($all);
137
138 $pairs = array();
139 foreach ($subtypes as $name => $info) {
140 $index = ($key == 'name') ? $name : $info[$key];
141 $pairs[$index] = $info['label'];
142 }
143 return $pairs;
144 }
145
146 /**
c490a46a 147 * Retrieve all subtypes Information.
6a488035 148 *
77c5b619
TO
149 * @param array $contactType
150 * ..
fd31fa4c
EM
151 * @param bool $all
152 * @param bool $ignoreCache
153 * @param bool $reset
6a488035 154 *
a6c01b45
CW
155 * @return array
156 * of sub type information
fd31fa4c 157 * @static
6a488035 158 */
00be9182 159 public static function &subTypeInfo($contactType = NULL, $all = FALSE, $ignoreCache = FALSE, $reset = FALSE) {
6a488035
TO
160 static $_cache = NULL;
161
162 if ($reset === TRUE) {
163 $_cache = NULL;
164 }
165
166 if ($_cache === NULL) {
167 $_cache = array();
168 }
169 if ($contactType && !is_array($contactType)) {
170 $contactType = array($contactType);
171 }
172
173 $argString = $all ? 'CRM_CT_STI_1_' : 'CRM_CT_STI_0_';
174 if (!empty($contactType)) {
175 $argString .= implode('_', $contactType);
176 }
177
178 if ((!array_key_exists($argString, $_cache)) || $ignoreCache) {
179 $cache = CRM_Utils_Cache::singleton();
180 $_cache[$argString] = $cache->get($argString);
181 if (!$_cache[$argString] || $ignoreCache) {
182 $_cache[$argString] = array();
183
184 $ctWHERE = '';
185 if (!empty($contactType)) {
186 $ctWHERE = " AND parent.name IN ('" . implode("','", $contactType) . "')";
187 }
188
189 $sql = "
190SELECT subtype.*, parent.name as parent, parent.label as parent_label
191FROM civicrm_contact_type subtype
192INNER JOIN civicrm_contact_type parent ON subtype.parent_id = parent.id
193WHERE subtype.name IS NOT NULL AND subtype.parent_id IS NOT NULL {$ctWHERE}
194";
195 if ($all === FALSE) {
196 $sql .= " AND subtype.is_active = 1 AND parent.is_active = 1 ORDER BY parent.id";
197 }
198 $dao = CRM_Core_DAO::executeQuery($sql, array(),
199 FALSE, 'CRM_Contact_DAO_ContactType'
200 );
201 while ($dao->fetch()) {
202 $value = array();
203 CRM_Core_DAO::storeValues($dao, $value);
204 $value['parent'] = $dao->parent;
205 $value['parent_label'] = $dao->parent_label;
206 $_cache[$argString][$dao->name] = $value;
207 }
208
209 $cache->set($argString, $_cache[$argString]);
210 }
211 }
212 return $_cache[$argString];
213 }
214
215 /**
216 *
c490a46a 217 * retrieve all subtypes
6a488035 218 *
77c5b619
TO
219 * @param array $contactType
220 * ..
f4aaa82a
EM
221 * @param bool $all
222 * @param string $columnName
223 * @param bool $ignoreCache
6a488035 224 *
a6c01b45
CW
225 * @return array
226 * of all subtypes OR list of subtypes associated to
51ccfbbe 227 * a given basic contact type
f4aaa82a 228 * @static
6a488035 229 */
00be9182 230 public static function subTypes($contactType = NULL, $all = FALSE, $columnName = 'name', $ignoreCache = FALSE) {
6a488035
TO
231 if ($columnName == 'name') {
232 return array_keys(self::subTypeInfo($contactType, $all, $ignoreCache));
233 }
234 else {
235 return array_values(self::subTypePairs($contactType, FALSE, NULL, $ignoreCache));
236 }
237 }
238
239 /**
240 *
c490a46a 241 * retrieve subtype pairs with name as 'subtype-name' and 'label' as value
6a488035 242 *
77c5b619
TO
243 * @param array $contactType
244 * ..
f4aaa82a
EM
245 * @param bool $all
246 * @param string $labelPrefix
247 * @param bool $ignoreCache
6a488035 248 *
f4aaa82a
EM
249 * @return list of subtypes with name as 'subtype-name' and 'label' as value
250 * @static
6a488035 251 */
00be9182 252 public static function subTypePairs($contactType = NULL, $all = FALSE, $labelPrefix = '- ', $ignoreCache = FALSE) {
6a488035
TO
253 $subtypes = self::subTypeInfo($contactType, $all, $ignoreCache);
254
255 $pairs = array();
256 foreach ($subtypes as $name => $info) {
257 $pairs[$name] = $labelPrefix . $info['label'];
258 }
259 return $pairs;
260 }
261
262 /**
263 *
c490a46a 264 * retrieve list of all types i.e basic + subtypes.
6a488035 265 *
f4aaa82a 266 * @param bool $all
6a488035 267 *
a6c01b45
CW
268 * @return array
269 * of basic types + all subtypes.
f4aaa82a 270 * @static
6a488035 271 */
00be9182 272 public static function contactTypes($all = FALSE) {
6a488035
TO
273 return array_keys(self::contactTypeInfo($all));
274 }
275
276 /**
277 *
c490a46a 278 * retrieve info array about all types i.e basic + subtypes.
6a488035 279 *
f4aaa82a
EM
280 * @param bool $all
281 * @param bool $reset
6a488035 282 *
a6c01b45
CW
283 * @return array
284 * of basic types + all subtypes.
f4aaa82a 285 * @static
6a488035 286 */
00be9182 287 public static function contactTypeInfo($all = FALSE, $reset = FALSE) {
6a488035
TO
288 static $_cache = NULL;
289
290 if ($reset === TRUE) {
291 $_cache = NULL;
292 }
293
294 if ($_cache === NULL) {
295 $_cache = array();
296 }
297
298 $argString = $all ? 'CRM_CT_CTI_1' : 'CRM_CT_CTI_0';
299 if (!array_key_exists($argString, $_cache)) {
300 $cache = CRM_Utils_Cache::singleton();
301 $_cache[$argString] = $cache->get($argString);
302 if (!$_cache[$argString]) {
303 $_cache[$argString] = array();
304
305 $sql = "
306SELECT type.*, parent.name as parent, parent.label as parent_label
307FROM civicrm_contact_type type
308LEFT JOIN civicrm_contact_type parent ON type.parent_id = parent.id
309WHERE type.name IS NOT NULL
310";
311 if ($all === FALSE) {
312 $sql .= " AND type.is_active = 1";
313 }
314
315 $dao = CRM_Core_DAO::executeQuery($sql,
316 CRM_Core_DAO::$_nullArray,
317 FALSE,
318 'CRM_Contact_DAO_ContactType'
319 );
320 while ($dao->fetch()) {
321 $value = array();
322 CRM_Core_DAO::storeValues($dao, $value);
323 if (array_key_exists('parent_id', $value)) {
324 $value['parent'] = $dao->parent;
325 $value['parent_label'] = $dao->parent_label;
326 }
327 $_cache[$argString][$dao->name] = $value;
328 }
329
330 $cache->set($argString, $_cache[$argString]);
331 }
332 }
333
334 return $_cache[$argString];
335 }
336
337 /**
c490a46a 338 * Retrieve basic type pairs with name as 'built-in name' and 'label' as value
6a488035 339 *
f4aaa82a
EM
340 * @param bool $all
341 * @param null $typeName
342 * @param null $delimiter
6a488035 343 *
a6c01b45
CW
344 * @return array
345 * of basictypes with name as 'built-in name' and 'label' as value
f4aaa82a 346 * @static
6a488035 347 */
00be9182 348 public static function contactTypePairs($all = FALSE, $typeName = NULL, $delimiter = NULL) {
6a488035
TO
349 $types = self::contactTypeInfo($all);
350
351 if ($typeName && !is_array($typeName)) {
352 $typeName = explode(CRM_Core_DAO::VALUE_SEPARATOR, trim($typeName, CRM_Core_DAO::VALUE_SEPARATOR));
353 }
354
355 $pairs = array();
356 if ($typeName) {
357 foreach ($typeName as $type) {
358 if (array_key_exists($type, $types)) {
359 $pairs[$type] = $types[$type]['label'];
360 }
361 }
362 }
363 else {
364 foreach ($types as $name => $info) {
365 $pairs[$name] = $info['label'];
366 }
367 }
368
369 return !$delimiter ? $pairs : implode($delimiter, $pairs);
370 }
371
b500fbea
EM
372 /**
373 * Get a list of elements for select box
374 * Note that this used to default to using the hex(01) character - which results in an invalid character being used in form fields
375 * which was not handled well be anything that loaded & resaved the html (outside core)
376 * The use of this separator is now explicit in the calling functions as a step towards it's removal
377 *
378 * @param bool $all
379 * @param bool $isSeparator
380 * @param string $separator
381 *
382 * @return mixed
383 */
51ccfbbe
TO
384 static function getSelectElements(
385 $all = FALSE,
b500fbea
EM
386 $isSeparator = TRUE,
387 $separator = '__'
6a488035
TO
388 ) {
389 static $_cache = NULL;
390
391 if ($_cache === NULL) {
392 $_cache = array();
393 }
394
395 $argString = $all ? 'CRM_CT_GSE_1' : 'CRM_CT_GSE_0';
b500fbea 396 $argString .= $isSeparator ? '_1' : '_0';
6a488035
TO
397 if (!array_key_exists($argString, $_cache)) {
398 $cache = CRM_Utils_Cache::singleton();
399 $_cache[$argString] = $cache->get($argString);
400
401 if (!$_cache[$argString]) {
402 $_cache[$argString] = array();
403
404 $sql = "
405SELECT c.name as child_name , c.label as child_label , c.id as child_id,
406 p.name as parent_name, p.label as parent_label, p.id as parent_id
407FROM civicrm_contact_type c
408LEFT JOIN civicrm_contact_type p ON ( c.parent_id = p.id )
409WHERE ( c.name IS NOT NULL )
410";
411
412 if ($all === FALSE) {
413 $sql .= "
414AND c.is_active = 1
415AND ( p.is_active = 1 OR p.id IS NULL )
416";
417 }
418 $sql .= " ORDER BY c.id";
419
420 $values = array();
421 $dao = CRM_Core_DAO::executeQuery($sql);
422 while ($dao->fetch()) {
423 if (!empty($dao->parent_id)) {
b500fbea 424 $key = $isSeparator ? $dao->parent_name . $separator . $dao->child_name : $dao->child_name;
bee6039a 425 $label = "- {$dao->child_label}";
6a488035
TO
426 $pName = $dao->parent_name;
427 }
428 else {
429 $key = $dao->child_name;
430 $label = $dao->child_label;
431 $pName = $dao->child_name;
432 }
433
434 if (!isset($values[$pName])) {
435 $values[$pName] = array();
436 }
437 $values[$pName][] = array('key' => $key, 'label' => $label);
438 }
439
440 $selectElements = array();
441 foreach ($values as $pName => $elements) {
442 foreach ($elements as $element) {
443 $selectElements[$element['key']] = $element['label'];
444 }
445 }
446 $_cache[$argString] = $selectElements;
447
448 $cache->set($argString, $_cache[$argString]);
449 }
450 }
451 return $_cache[$argString];
452 }
453
454 /**
100fef9d 455 * Check if a given type is a subtype
6a488035 456 *
77c5b619
TO
457 * @param string $subType
458 * Contact subType.
f4aaa82a 459 * @param bool $ignoreCache
6a488035 460 *
a6c01b45
CW
461 * @return boolean
462 * true if subType, false otherwise.
f4aaa82a 463 * @static
6a488035 464 */
00be9182 465 public static function isaSubType($subType, $ignoreCache = FALSE) {
6a488035
TO
466 return in_array($subType, self::subTypes(NULL, TRUE, 'name', $ignoreCache));
467 }
468
469 /**
100fef9d 470 * Retrieve the basic contact type associated with given subType.
6a488035 471 *
51ccfbbe
TO
472 * @param array/string $subType contact subType.
473 * @return array/string of basicTypes.
474 * @static
6a488035 475 */
00be9182 476 public static function getBasicType($subType) {
6a488035
TO
477 static $_cache = NULL;
478 if ($_cache === NULL) {
479 $_cache = array();
480 }
481
482 $isArray = TRUE;
483 if ($subType && !is_array($subType)) {
484 $subType = array($subType);
485 $isArray = FALSE;
486 }
487 $argString = implode('_', $subType);
488
489 if (!array_key_exists($argString, $_cache)) {
490 $_cache[$argString] = array();
491
492 $sql = "
493SELECT subtype.name as contact_subtype, type.name as contact_type
494FROM civicrm_contact_type subtype
495INNER JOIN civicrm_contact_type type ON ( subtype.parent_id = type.id )
496WHERE subtype.name IN ('" . implode("','", $subType) . "' )";
497 $dao = CRM_Core_DAO::executeQuery($sql);
498 while ($dao->fetch()) {
499 if (!$isArray) {
500 $_cache[$argString] = $dao->contact_type;
501 break;
502 }
503 $_cache[$argString][$dao->contact_subtype] = $dao->contact_type;
504 }
505 }
506 return $_cache[$argString];
507 }
508
509 /**
c490a46a 510 * Suppress all subtypes present in given array.
6a488035 511 *
77c5b619
TO
512 * @param array $subTypes
513 * Contact subTypes.
f4aaa82a 514 * @param bool $ignoreCache
6a488035 515 *
a6c01b45
CW
516 * @return array
517 * of suppressed subTypes.
f4aaa82a 518 * @static
6a488035 519 */
00be9182 520 public static function suppressSubTypes(&$subTypes, $ignoreCache = FALSE) {
6a488035
TO
521 $subTypes = array_diff($subTypes, self::subTypes(NULL, TRUE, 'name', $ignoreCache));
522 return $subTypes;
523 }
524
525 /**
100fef9d 526 * Verify if a given subtype is associated with a given basic contact type.
6a488035 527 *
77c5b619
TO
528 * @param string $subType
529 * Contact subType.
530 * @param string $contactType
531 * Contact Type.
f4aaa82a
EM
532 * @param bool $ignoreCache
533 * @param string $columnName
6a488035 534 *
a6c01b45
CW
535 * @return boolean
536 * true if contact extends, false otherwise.
f4aaa82a 537 * @static
6a488035 538 */
00be9182 539 public static function isExtendsContactType($subType, $contactType, $ignoreCache = FALSE, $columnName = 'name') {
6a488035
TO
540 if (!is_array($subType)) {
541 $subType = explode(CRM_Core_DAO::VALUE_SEPARATOR, trim($subType, CRM_Core_DAO::VALUE_SEPARATOR));
542 }
543 $subtypeList = self::subTypes($contactType, TRUE, $columnName, $ignoreCache);
544 $intersection = array_intersect($subType, $subtypeList);
545 return $subType == $intersection;
546 }
547
548 /**
100fef9d 549 * Create shortcuts menu for contactTypes
6a488035 550 *
a6c01b45
CW
551 * @return array
552 * of contactTypes
c490a46a 553 * @static
6a488035 554 */
00be9182 555 public static function getCreateNewList() {
6a488035 556 $shortCuts = array();
b500fbea
EM
557 //@todo FIXME - using the CRM_Core_DAO::VALUE_SEPARATOR creates invalid html - if you can find the form
558 // this is loaded onto then replace with something like '__' & test
559 $separator = CRM_Core_DAO::VALUE_SEPARATOR;
560 $contactTypes = self::getSelectElements(FALSE, TRUE, $separator);
6a488035
TO
561 foreach ($contactTypes as $key => $value) {
562 if ($key) {
563 $typeValue = explode(CRM_Core_DAO::VALUE_SEPARATOR, $key);
7926b999 564 $cType = CRM_Utils_Array::value('0', $typeValue);
565 $typeUrl = 'ct=' . $cType;
6a488035
TO
566 if ($csType = CRM_Utils_Array::value('1', $typeValue)) {
567 $typeUrl .= "&cst=$csType";
568 }
7926b999 569 $shortCut = array(
6a488035
TO
570 'path' => 'civicrm/contact/add',
571 'query' => "$typeUrl&reset=1",
572 'ref' => "new-$value",
573 'title' => $value,
574 );
7926b999 575 if ($csType = CRM_Utils_Array::value('1', $typeValue)) {
576 $shortCuts[$cType]['shortCuts'][] = $shortCut;
577 }
578 else {
579 $shortCuts[$cType] = $shortCut;
580 }
6a488035
TO
581 }
582 }
583 return $shortCuts;
584 }
585
586 /**
100fef9d 587 * Delete Contact SubTypes
6a488035 588 *
77c5b619
TO
589 * @param int $contactTypeId
590 * ID of the Contact Subtype to be deleted.
6a488035 591 *
f4aaa82a 592 * @return bool
6a488035
TO
593 * @static
594 */
00be9182 595 public static function del($contactTypeId) {
6a488035
TO
596
597 if (!$contactTypeId) {
598 return FALSE;
599 }
600
601 $params = array('id' => $contactTypeId);
602 self::retrieve($params, $typeInfo);
603 $name = $typeInfo['name'];
604 // check if any custom group
605 $custom = new CRM_Core_DAO_CustomGroup();
606 $custom->whereAdd("extends_entity_column_value LIKE '%" .
607 CRM_Core_DAO::VALUE_SEPARATOR .
608 $name .
609 CRM_Core_DAO::VALUE_SEPARATOR . "%'"
610 );
611 if ($custom->find()) {
612 return FALSE;
613 }
614
615 // remove subtype for existing contacts
616 $sql = "
617UPDATE civicrm_contact SET contact_sub_type = NULL
618WHERE contact_sub_type = '$name'";
619 CRM_Core_DAO::executeQuery($sql);
620
621 // remove subtype from contact type table
622 $contactType = new CRM_Contact_DAO_ContactType();
623 $contactType->id = $contactTypeId;
624 $contactType->delete();
625
626 // remove navigation entry if any
627 if ($name) {
628 $sql = "
629DELETE
630FROM civicrm_navigation
631WHERE name = %1";
632 $params = array(1 => array("New $name", 'String'));
633 $dao = CRM_Core_DAO::executeQuery($sql, $params);
634 CRM_Core_BAO_Navigation::resetNavigation();
635 }
636 return TRUE;
637 }
638
639 /**
100fef9d 640 * Add or update Contact SubTypes
6a488035 641 *
77c5b619
TO
642 * @param array $params
643 * An assoc array of name/value pairs.
6a488035
TO
644 *
645 * @return object
6a488035
TO
646 * @static
647 */
00be9182 648 public static function add(&$params) {
6a488035
TO
649
650 // label or name
0f77a625 651 if (empty($params['id']) && empty($params['label'])) {
6a488035
TO
652 return;
653 }
a7488080 654 if (!empty($params['parent_id']) &&
6a488035
TO
655 !CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_ContactType', $params['parent_id'])
656 ) {
657 return;
658 }
659
660 $contactType = new CRM_Contact_DAO_ContactType();
661 $contactType->copyValues($params);
662 $contactType->id = CRM_Utils_Array::value('id', $params);
663 $contactType->is_active = CRM_Utils_Array::value('is_active', $params, 0);
664
6a488035
TO
665 $contactType->save();
666 if ($contactType->find(TRUE)) {
667 $contactName = $contactType->name;
668 $contact = ucfirst($contactType->label);
669 $active = $contactType->is_active;
670 }
671
a7488080 672 if (!empty($params['id'])) {
6a488035
TO
673 $params = array('name' => "New $contactName");
674 $newParams = array(
675 'label' => "New $contact",
676 'is_active' => $active,
677 );
678 CRM_Core_BAO_Navigation::processUpdate($params, $newParams);
679 }
680 else {
681 $name = self::getBasicType($contactName);
682 if (!$name) {
683 return;
684 }
685 $value = array('name' => "New $name");
686 CRM_Core_BAO_Navigation::retrieve($value, $navinfo);
687 $navigation = array(
688 'label' => "New $contact",
689 'name' => "New $contactName",
15a7ea79 690 'url' => "civicrm/contact/add?ct=$name&cst=$contactName&reset=1",
6a488035
TO
691 'permission' => 'add contacts',
692 'parent_id' => $navinfo['id'],
693 'is_active' => $active,
694 );
695 CRM_Core_BAO_Navigation::add($navigation);
696 }
697 CRM_Core_BAO_Navigation::resetNavigation();
698
699 // reset the cache after adding
700 self::subTypeInfo(NULL, FALSE, FALSE, TRUE);
701
702 return $contactType;
703 }
704
705 /**
100fef9d 706 * Update the is_active flag in the db
6a488035 707 *
77c5b619
TO
708 * @param int $id
709 * Id of the database record.
710 * @param bool $is_active
711 * Value we want to set the is_active field.
6a488035 712 *
a6c01b45
CW
713 * @return Object
714 * DAO object on success, null otherwise
6a488035
TO
715 * @static
716 */
00be9182 717 public static function setIsActive($id, $is_active) {
6a488035
TO
718 $params = array('id' => $id);
719 self::retrieve($params, $contactinfo);
720 $params = array('name' => "New $contactinfo[name]");
721 $newParams = array('is_active' => $is_active);
722 CRM_Core_BAO_Navigation::processUpdate($params, $newParams);
723 CRM_Core_BAO_Navigation::resetNavigation();
724 return CRM_Core_DAO::setFieldValue('CRM_Contact_DAO_ContactType', $id,
725 'is_active', $is_active
726 );
727 }
728
86538308 729 /**
100fef9d 730 * @param string $typeName
86538308
EM
731 *
732 * @return mixed
733 */
00be9182 734 public static function getLabel($typeName) {
6a488035
TO
735 $types = self::contactTypeInfo(TRUE);
736
737 if (array_key_exists($typeName, $types)) {
738 return $types[$typeName]['label'];
739 }
740 return $typeName;
741 }
742
743 /**
100fef9d 744 * Check whether allow to change any contact's subtype
6a488035
TO
745 * on the basis of custom data and relationship of specific subtype
746 * currently used in contact/edit form amd in import validation
747 *
77c5b619
TO
748 * @param int $contactId
749 * Contact id.
750 * @param string $subType
751 * Subtype.
6a488035 752 *
a6c01b45 753 * @return boolean
6a488035
TO
754 * @static
755 */
00be9182 756 public static function isAllowEdit($contactId, $subType = NULL) {
6a488035
TO
757
758 if (!$contactId) {
759 return TRUE;
760 }
761
762 if (empty($subType)) {
763 $subType = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
764 $contactId,
765 'contact_sub_type'
766 );
767 }
768
769 if (self::hasCustomData($subType, $contactId) || self::hasRelationships($contactId, $subType)) {
770 return FALSE;
771 }
772
773 return TRUE;
774 }
775
86538308
EM
776 /**
777 * @param $contactType
100fef9d 778 * @param int $contactId
86538308
EM
779 *
780 * @return bool
781 */
00be9182 782 public static function hasCustomData($contactType, $contactId = NULL) {
6a488035
TO
783 $subTypeClause = '';
784
785 if (self::isaSubType($contactType)) {
786 $subType = $contactType;
787 $contactType = self::getBasicType($subType);
788
789 // check for empty custom data which extends subtype
790 $subTypeValue = CRM_Core_DAO::VALUE_SEPARATOR . $subType . CRM_Core_DAO::VALUE_SEPARATOR;
791 $subTypeClause = " AND extends_entity_column_value LIKE '%{$subTypeValue}%' ";
792 }
793 $query = "SELECT table_name FROM civicrm_custom_group WHERE extends = '{$contactType}' {$subTypeClause}";
794
795 $dao = CRM_Core_DAO::executeQuery($query);
796 while ($dao->fetch()) {
797 $sql = "SELECT count(id) FROM {$dao->table_name}";
798 if ($contactId) {
799 $sql .= " WHERE entity_id = {$contactId}";
800 }
801 $sql .= " LIMIT 1";
802
803 $customDataCount = CRM_Core_DAO::singleValueQuery($sql);
804 if (!empty($customDataCount)) {
805 $dao->free();
806 return TRUE;
807 }
808 }
809 return FALSE;
810 }
811
f4aaa82a
EM
812 /**
813 * @todo what does this function do?
100fef9d 814 * @param int $contactId
f4aaa82a
EM
815 * @param $contactType
816 *
817 * @return bool
818 */
00be9182 819 public static function hasRelationships($contactId, $contactType) {
6a488035
TO
820 $subTypeClause = NULL;
821 if (self::isaSubType($contactType)) {
822 $subType = $contactType;
823 $contactType = self::getBasicType($subType);
824 $subTypeClause = " AND ( ( crt.contact_type_a = '{$contactType}' AND crt.contact_sub_type_a = '{$subType}') OR
825 ( crt.contact_type_b = '{$contactType}' AND crt.contact_sub_type_b = '{$subType}') ) ";
826 }
827 else {
828 $subTypeClause = " AND ( crt.contact_type_a = '{$contactType}' OR crt.contact_type_b = '{$contactType}' ) ";
829 }
830
831 // check relationships for
832 $relationshipQuery = "
833SELECT count(cr.id) FROM civicrm_relationship cr
834INNER JOIN civicrm_relationship_type crt ON
835( cr.relationship_type_id = crt.id {$subTypeClause} )
836WHERE ( cr.contact_id_a = {$contactId} OR cr.contact_id_b = {$contactId} )
837LIMIT 1";
838
839 $relationshipCount = CRM_Core_DAO::singleValueQuery($relationshipQuery);
840
841 if (!empty($relationshipCount)) {
842 return TRUE;
843 }
844
845 return FALSE;
846 }
847
f4aaa82a
EM
848 /**
849 * @todo what does this function do?
850 * @param $contactType
851 * @param array $subtypeSet
852 *
853 * @return array
854 */
00be9182 855 public static function getSubtypeCustomPair($contactType, $subtypeSet = array()) {
6a488035
TO
856 if (empty($subtypeSet)) {
857 return $subtypeSet;
858 }
859
860 $customSet = $subTypeClause = array();
861 foreach ($subtypeSet as $subtype) {
862 $subtype = CRM_Utils_Type::escape($subtype, 'String');
863 $subType = CRM_Core_DAO::VALUE_SEPARATOR . $subtype . CRM_Core_DAO::VALUE_SEPARATOR;
864 $subTypeClause[] = "extends_entity_column_value LIKE '%{$subtype}%' ";
865 }
866 $query = "SELECT table_name
867FROM civicrm_custom_group
868WHERE extends = %1 AND " . implode(" OR ", $subTypeClause);
869 $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($contactType, 'String')));
870 while ($dao->fetch()) {
871 $customSet[] = $dao->table_name;
872 }
873 return array_unique($customSet);
874 }
875
f4aaa82a
EM
876 /**
877 * Function that does something
878 * @todo what does this function do?
879 *
100fef9d 880 * @param int $contactID
f4aaa82a
EM
881 * @param $contactType
882 * @param array $oldSubtypeSet
883 * @param array $newSubtypeSet
884 *
885 * @return bool
886 */
51ccfbbe
TO
887 static function deleteCustomSetForSubtypeMigration(
888 $contactID,
6a488035
TO
889 $contactType,
890 $oldSubtypeSet = array(),
891 $newSubtypeSet = array()
892 ) {
893 $oldCustomSet = self::getSubtypeCustomPair($contactType, $oldSubtypeSet);
894 $newCustomSet = self::getSubtypeCustomPair($contactType, $newSubtypeSet);
895
896 $customToBeRemoved = array_diff($oldCustomSet, $newCustomSet);
897 foreach ($customToBeRemoved as $customTable) {
898 self::deleteCustomRowsForEntityID($customTable, $contactID);
899 }
900 return TRUE;
901 }
902
903 /**
904 * Delete content / rows of a custom table specific to a subtype for a given custom-group.
905 * This function currently works for contact subtypes only and could be later improved / genralized
906 * to work for other subtypes as well.
907 *
77c5b619
TO
908 * @param int $gID
909 * Custom group id.
910 * @param array $subtypes
911 * List of subtypes related to which entry is to be removed.
6a488035
TO
912 *
913 * @return void
6a488035 914 */
66ed0bee 915 public static function deleteCustomRowsOfSubtype($gID, $subtypes = array()) {
6a488035
TO
916 if (!$gID or empty($subtypes)) {
917 return FALSE;
918 }
919
920 $tableName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $gID, 'table_name');
921
66ed0bee 922 // drop triggers CRM-13587
923 CRM_Core_DAO::dropTriggers($tableName);
924
6a488035
TO
925 $subtypeClause = array();
926 foreach ($subtypes as $subtype) {
927 $subtype = CRM_Utils_Type::escape($subtype, 'String');
928 $subtypeClause[] = "civicrm_contact.contact_sub_type LIKE '%" . CRM_Core_DAO::VALUE_SEPARATOR . $subtype . CRM_Core_DAO::VALUE_SEPARATOR . "%'";
929 }
930 $subtypeClause = implode(' OR ', $subtypeClause);
931
932 $query = "DELETE custom.*
933FROM {$tableName} custom
934INNER JOIN civicrm_contact ON civicrm_contact.id = custom.entity_id
935WHERE ($subtypeClause)";
66ed0bee 936
937 CRM_Core_DAO::singleValueQuery($query);
938
939 // rebuild triggers CRM-13587
940 CRM_Core_DAO::triggerRebuild($tableName);
6a488035
TO
941 }
942
943 /**
944 * Delete content / rows of a custom table specific entity-id for a given custom-group table.
945 *
77c5b619
TO
946 * @param int $customTable
947 * Custom table name.
948 * @param int $entityID
949 * Entity id.
6a488035
TO
950 *
951 * @return void
6a488035 952 */
00be9182 953 public function deleteCustomRowsForEntityID($customTable, $entityID) {
6a488035
TO
954 $customTable = CRM_Utils_Type::escape($customTable, 'String');
955 $query = "DELETE FROM {$customTable} WHERE entity_id = %1";
956 return CRM_Core_DAO::singleValueQuery($query, array(1 => array($entityID, 'Integer')));
957 }
958}