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