preliminary whitespace cleanup
[civicrm-core.git] / CRM / Core / BAO / UFField.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.3 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2013
32 * $Id$
33 *
34 */
35
36 /**
37 * This class contains function for UFField
38 *
39 */
40 class CRM_Core_BAO_UFField extends CRM_Core_DAO_UFField {
41
42 /**
43 * Batch entry fields
44 */
45 private static $_contriBatchEntryFields = NULL;
46 private static $_memberBatchEntryFields = NULL;
47
48
49 /**
50 * Takes a bunch of params that are needed to match certain criteria and
51 * retrieves the relevant objects. Typically the valid params are only
52 * contact_id. We'll tweak this function to be more full featured over a period
53 * of time. This is the inverse function of create. It also stores all the retrieved
54 * values in the default array
55 *
56 * @param array $params (reference ) an assoc array of name/value pairs
57 * @param array $defaults (reference ) an assoc array to hold the flattened values
58 *
59 * @return object CRM_Core_BAO_UFField object
60 * @access public
61 * @static
62 */
63 static function retrieve(&$params, &$defaults) {
64 return CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_UFField', $params, $defaults);
65 }
66
67 /**
68 * Get the form title.
69 *
70 * @param int $id id of uf_form
71 *
72 * @return string title
73 *
74 * @access public
75 * @static
76 *
77 */
78 public static function getTitle($id) {
79 return CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFField', $groupId, 'title');
80 }
81
82 /**
83 * update the is_active flag in the db
84 *
85 * @param int $id id of the database record
86 * @param boolean $is_active value we want to set the is_active field
87 *
88 * @return Object DAO object on sucess, null otherwise
89 * @access public
90 * @static
91 */
92 static function setIsActive($id, $is_active) {
93 //check if custom data profile field is disabled
94 if ($is_active) {
95 if (CRM_Core_BAO_UFField::checkUFStatus($id)) {
96 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFField', $id, 'is_active', $is_active);
97 }
98 else {
99 CRM_Core_Session::setStatus(ts('Cannot enable this UF field since the used custom field is disabled.'), ts('Check Custom Field'), 'error');
100 }
101 }
102 else {
103 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFField', $id, 'is_active', $is_active);
104 }
105 }
106
107 /**
108 * Delete the profile Field.
109 *
110 * @param int $id Field Id
111 *
112 * @return boolean
113 *
114 * @access public
115 * @static
116 *
117 */
118 public static function del($id) {
119 //delete field field
120 $field = new CRM_Core_DAO_UFField();
121 $field->id = $id;
122 $field->delete();
123 return TRUE;
124 }
125
126 /**
127 * Function to check duplicate for duplicate field in a group
128 *
129 * @param array $params an associative array with field and values
130 * @ids array $ids array that containd ids
131 *
132 * @access public
133 * @static
134 */
135 public static function duplicateField($params, $ids) {
136 $ufField = new CRM_Core_DAO_UFField();
137 $ufField->uf_group_id = CRM_Utils_Array::value('uf_group', $ids);
138 $ufField->field_type = $params['field_name'][0];
139 $ufField->field_name = $params['field_name'][1];
140 $ufField->location_type_id = (CRM_Utils_Array::value(2, $params['field_name'])) ? $params['field_name'][2] : 'NULL';
141 $ufField->phone_type_id = CRM_Utils_Array::value(3, $params['field_name']);
142
143 if (CRM_Utils_Array::value('uf_field', $ids)) {
144 $ufField->whereAdd("id <> " . CRM_Utils_Array::value('uf_field', $ids));
145 }
146
147 return $ufField->find(TRUE);
148 }
149
150 /*
151 *Does profile consists of a multi-record custom field
152 */
153 public static function checkMultiRecordFieldExists($gId) {
154 $queryString = "SELECT f.field_name
155 FROM civicrm_uf_field f, civicrm_uf_group g
156 WHERE f.uf_group_id = g.id
157 AND g.id = %1 AND f.field_name LIKE 'custom%'";
158 $p = array(1 => array($gId, 'Integer'));
159 $dao = CRM_Core_DAO::executeQuery($queryString, $p);
160 $customFieldIds = array();
161 $isMultiRecordFieldPresent = FALSE;
162 while ($dao->fetch()) {
163 if ($customId = CRM_Core_BAO_CustomField::getKeyID($dao->field_name)) {
164 if (is_numeric($customId)) {
165 $customFieldIds[] = $customId;
166 }
167 }
168 }
169
170 if (!empty($customFieldIds) && count($customFieldIds) == 1) {
171 $customFieldId = array_pop($customFieldIds);
172 $isMultiRecordFieldPresent = CRM_Core_BAO_CustomField::isMultiRecordField($customFieldId);
173 }
174 elseif (count($customFieldIds) > 1) {
175 $customFieldIds = implode(", ", $customFieldIds);
176 $queryString = "
177 SELECT cg.id as cgId
178 FROM civicrm_custom_group cg
179 INNER JOIN civicrm_custom_field cf
180 ON cg.id = cf.custom_group_id
181 WHERE cf.id IN (" . $customFieldIds . ") AND is_multiple = 1 LIMIT 0,1";
182
183 $dao = CRM_Core_DAO::executeQuery($queryString);
184 if ($dao->fetch()) {
185 $isMultiRecordFieldPresent = ($dao->cgId) ? $dao->cgId : FALSE;
186 }
187 }
188
189 return $isMultiRecordFieldPresent;
190 }
191
192 /**
193 * function to add the UF Field
194 *
195 * @param array $params (reference) array containing the values submitted by the form
196 * @param array $ids (reference) array containing the id
197 *
198 * @return object CRM_Core_BAO_UFField object
199 *
200 * @access public
201 * @static
202 *
203 */
204 static function add(&$params, &$ids) {
205 // set values for uf field properties and save
206 $ufField = new CRM_Core_DAO_UFField();
207 $ufField->field_type = $params['field_name'][0];
208 $ufField->field_name = $params['field_name'][1];
209
210 //should not set location type id for Primary
211 $locationTypeId = CRM_Utils_Array::value(2, $params['field_name']);
212 if ($locationTypeId) {
213 $ufField->location_type_id = $locationTypeId;
214 }
215 else {
216 $ufField->location_type_id = 'null';
217 }
218
219 $ufField->phone_type_id = CRM_Utils_Array::value(3, $params['field_name'], 'NULL');
220 $ufField->listings_title = CRM_Utils_Array::value('listings_title', $params);
221 $ufField->visibility = CRM_Utils_Array::value('visibility', $params);
222 $ufField->help_pre = CRM_Utils_Array::value('help_pre', $params);
223 $ufField->help_post = CRM_Utils_Array::value('help_post', $params);
224 $ufField->label = CRM_Utils_Array::value('label', $params);
225 $ufField->is_required = CRM_Utils_Array::value('is_required', $params, FALSE);
226 $ufField->is_active = CRM_Utils_Array::value('is_active', $params, FALSE);
227 $ufField->in_selector = CRM_Utils_Array::value('in_selector', $params, FALSE);
228 $ufField->is_view = CRM_Utils_Array::value('is_view', $params, FALSE);
229 $ufField->is_registration = CRM_Utils_Array::value('is_registration', $params, FALSE);
230 $ufField->is_match = CRM_Utils_Array::value('is_match', $params, FALSE);
231 $ufField->is_searchable = CRM_Utils_Array::value('is_searchable', $params, FALSE);
232 $ufField->is_multi_summary = CRM_Utils_Array::value('is_multi_summary', $params, FALSE);
233 $ufField->weight = CRM_Utils_Array::value('weight', $params, 0);
234
235 // need the FKEY - uf group id
236 $ufField->uf_group_id = CRM_Utils_Array::value('uf_group', $ids, FALSE);
237 $ufField->id = CRM_Utils_Array::value('uf_field', $ids, FALSE);
238
239 return $ufField->save();
240 }
241
242 /**
243 * Automatically determine one weight and modify others
244 *
245 * @param array $params UFField record, e.g. with 'weight', 'uf_group_id', and 'field_id'
246 * @return int
247 */
248 public static function autoWeight($params) {
249 // fix for CRM-316
250 $oldWeight = NULL;
251
252 if (CRM_Utils_Array::value('field_id', $params)) {
253 $oldWeight = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFField', $params['field_id'], 'weight', 'id');
254 }
255 $fieldValues = array('uf_group_id' => $params['group_id']);
256 return CRM_Utils_Weight::updateOtherWeights('CRM_Core_DAO_UFField', $oldWeight, $params['weight'], $fieldValues);
257 }
258
259 /**
260 * Function to enable/disable profile field given a custom field id
261 *
262 * @param int $customFieldId custom field id
263 * @param boolean $is_active set the is_active field
264 *
265 * @return void
266 * @static
267 * @access public
268 */
269 static function setUFField($customFieldId, $is_active) {
270 //find the profile id given custom field
271 $ufField = new CRM_Core_DAO_UFField();
272 $ufField->field_name = "custom_" . $customFieldId;
273
274 $ufField->find();
275 while ($ufField->fetch()) {
276 //enable/ disable profile
277 CRM_Core_BAO_UFField::setIsActive($ufField->id, $is_active);
278 }
279 }
280
281 /**
282 * Function to copy exisiting profile fields to
283 * new profile from the already built profile
284 *
285 * @param int $old_id from which we need to copy
286 * @param boolean $new_id in which to copy
287 *
288 * @return void
289 * @static
290 * @access public
291 */
292 static function copy($old_id, $new_id) {
293 $ufField = new CRM_Core_DAO_UFField();
294 $ufField->uf_group_id = $old_id;
295 $ufField->find();
296 while ($ufField->fetch()) {
297 //copy the field records as it is on new ufgroup id
298 $ufField->uf_group_id = $new_id;
299 $ufField->id = NULL;
300 $ufField->save();
301 }
302 }
303
304 /**
305 * Function to delete profile field given a custom field
306 *
307 * @param int $customFieldId ID of the custom field to be deleted
308 *
309 * @return void
310 *
311 * @static
312 * @access public
313 */
314 static function delUFField($customFieldId) {
315 //find the profile id given custom field id
316 $ufField = new CRM_Core_DAO_UFField();
317 $ufField->field_name = "custom_" . $customFieldId;
318
319 $ufField->find();
320 while ($ufField->fetch()) {
321 //enable/ disable profile
322 CRM_Core_BAO_UFField::del($ufField->id);
323 }
324 }
325
326 /**
327 * Function to enable/disable profile field given a custom group id
328 *
329 * @param int $customGroupId custom group id
330 * @param boolean $is_active value we want to set the is_active field
331 *
332 * @return void
333 * @static
334 * @access public
335 */
336 function setUFFieldStatus($customGroupId, $is_active) {
337 //find the profile id given custom group id
338 $queryString = "SELECT civicrm_custom_field.id as custom_field_id
339 FROM civicrm_custom_field, civicrm_custom_group
340 WHERE civicrm_custom_field.custom_group_id = civicrm_custom_group.id
341 AND civicrm_custom_group.id = %1";
342 $p = array(1 => array($customGroupId, 'Integer'));
343 $dao = CRM_Core_DAO::executeQuery($queryString, $p);
344
345 while ($dao->fetch()) {
346 //enable/ disable profile
347 CRM_Core_BAO_UFField::setUFField($dao->custom_field_id, $is_active);
348 }
349 }
350
351 /**
352 * Function to check the status of custom field used in uf fields
353 *
354 * @params int $UFFieldId uf field id
355 *
356 * @return boolean false if custom field are disabled else true
357 * @static
358 * @access public
359 */
360 static function checkUFStatus($UFFieldId) {
361 $fieldName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFField', $UFFieldId, 'field_name');
362 // return if field is not a custom field
363 if (!$customFieldId = CRM_Core_BAO_CustomField::getKeyID($fieldName)) {
364 return TRUE;
365 }
366
367 $customField = new CRM_Core_DAO_CustomField();
368 $customField->id = $customFieldId;
369 // if uf field is custom field
370 if ($customField->find(TRUE)) {
371 if (!$customField->is_active) {
372 return FALSE;
373 }
374 else {
375 return TRUE;
376 }
377 }
378 }
379
380 /*
381 * Function to find out whether given profile group using Activity
382 * Profile fields with contact fields
383 */
384 static function checkContactActivityProfileType($ufGroupId) {
385 $ufGroup = new CRM_Core_DAO_UFGroup();
386 $ufGroup->id = $ufGroupId;
387 $ufGroup->find(TRUE);
388
389 return self::checkContactActivityProfileTypeByGroupType($ufGroup->group_type);
390 }
391
392 /**
393 * FIXME say 10 ha
394 * @param $ufGroupType
395 * @return bool
396 */
397 public static function checkContactActivityProfileTypeByGroupType($ufGroupType) {
398 $profileTypes = array();
399 if ($ufGroupType) {
400 $typeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $ufGroupType);
401 $profileTypes = explode(',', $typeParts[0]);
402 }
403
404 if (empty($profileTypes)) {
405 return FALSE;
406 }
407 $components = array('Contribution', 'Participant', 'Membership');
408 if (!in_array('Activity', $profileTypes)) {
409 return FALSE;
410 }
411 elseif (count($profileTypes) == 1) {
412 return FALSE;
413 }
414
415 if ($index = array_search('Contact', $profileTypes)) {
416 unset($profileTypes[$index]);
417 if (count($profileTypes) == 1) {
418 return TRUE;
419 }
420 }
421
422 $contactTypes = array('Individual', 'Household', 'Organization');
423 $subTypes = CRM_Contact_BAO_ContactType::subTypes();
424
425 $profileTypeComponent = array_intersect($components, $profileTypes);
426 if (!empty($profileTypeComponent) ||
427 count(array_intersect($contactTypes, $profileTypes)) > 1 ||
428 count(array_intersect($subTypes, $profileTypes)) > 1
429 ) {
430 return FALSE;
431 }
432
433 return TRUE;
434 }
435
436 /* Function to find out whether given profile group uses $required
437 * and/or $optionalprofile types
438 *
439 * @param integer $ufGroupId profile id
440 * @param array $required array of types those are required
441 * @param array $optional array of types those are optional
442 *
443 * @return boolean $valid
444 * @static
445 */
446 static function checkValidProfileType($ufGroupId, $required, $optional = NULL) {
447 if (!is_array($required) || empty($required)) {
448 return;
449 }
450
451 $ufGroup = new CRM_Core_DAO_UFGroup();
452 $ufGroup->id = $ufGroupId;
453 $ufGroup->find(TRUE);
454
455 $profileTypes = array();
456 if ($ufGroup->group_type) {
457 $typeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $ufGroup->group_type);
458 $profileTypes = explode(',', $typeParts[0]);
459 }
460
461 if (empty($profileTypes)) {
462 return FALSE;
463 }
464
465 $valid = TRUE;
466 foreach ($required as $key => $val) {
467 if (!in_array($val, $profileTypes)) {
468 $valid = FALSE;
469 break;
470 }
471 }
472
473 if ($valid && is_array($optional)) {
474 foreach ($optional as $key => $val) {
475 if (in_array($val, $profileTypes)) {
476 $valid = TRUE;
477 break;
478 }
479 }
480 }
481
482 return $valid;
483 }
484
485 /**
486 * function to check for mix profile fields (eg: individual + other contact types)
487 *
488 * @params int $ufGroupId uf group id
489 * @params boolean $check this is to check mix profile (if true it will check if profile is
490 * pure ie. it contains only one contact type)
491 *
492 * @return true for mix profile else false
493 * @acess public
494 * @static
495 */
496 static function checkProfileType($ufGroupId) {
497 $ufGroup = new CRM_Core_DAO_UFGroup();
498 $ufGroup->id = $ufGroupId;
499 $ufGroup->find(TRUE);
500
501 $profileTypes = array();
502 if ($ufGroup->group_type) {
503 $typeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $ufGroup->group_type);
504 $profileTypes = explode(',', $typeParts[0]);
505 }
506
507 //early return if new profile.
508 if (empty($profileTypes)) {
509 return FALSE;
510 }
511
512 //we need to unset Contact
513 if (count($profileTypes) > 1) {
514 $index = array_search('Contact', $profileTypes);
515 if ($index !== FALSE) {
516 unset($profileTypes[$index]);
517 }
518 }
519
520 // suppress any subtypes if present
521 CRM_Contact_BAO_ContactType::suppressSubTypes($profileTypes);
522
523 $contactTypes = array('Contact', 'Individual', 'Household', 'Organization');
524 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
525 $fields = array();
526
527 // check for mix profile condition
528 if (count($profileTypes) > 1) {
529 //check the there are any components include in profile
530 foreach ($components as $value) {
531 if (in_array($value, $profileTypes)) {
532 return TRUE;
533 }
534 }
535 //check if there are more than one contact types included in profile
536 if (count($profileTypes) > 1) {
537 return TRUE;
538 }
539 }
540 elseif (count($profileTypes) == 1) {
541 // note for subtype case count would be zero
542 $profileTypes = array_values($profileTypes);
543 if (!in_array($profileTypes[0], $contactTypes)) {
544 return TRUE;
545 }
546 }
547
548 return FALSE;
549 }
550
551 /**
552 * function to get the profile type (eg: individual/organization/household)
553 *
554 * @param int $ufGroupId uf group id
555 * @param boolean $returnMixType this is true, then field type of mix profile field is returned
556 * @param boolean $onlyPure true if only pure profiles are required
557 *
558 * @return profile group_type
559 * @acess public
560 * @static
561 *
562 * TODO Why is this function in this class? It seems to be about the UFGroup.
563 */
564 static function getProfileType($ufGroupId, $returnMixType = TRUE, $onlyPure = FALSE, $skipComponentType = FALSE) {
565 $ufGroup = new CRM_Core_DAO_UFGroup();
566 $ufGroup->id = $ufGroupId;
567 $ufGroup->is_active = 1;
568
569 $ufGroup->find(TRUE);
570 return self::calculateProfileType($ufGroup->group_type, $returnMixType, $onlyPure, $skipComponentType);
571 }
572
573 /**
574 * function to get the profile type (eg: individual/organization/household)
575 *
576 * @param int $ufGroupId uf group id
577 * @param boolean $returnMixType this is true, then field type of mix profile field is returned
578 * @param boolean $onlyPure true if only pure profiles are required
579 *
580 * @return profile group_type
581 * @acess public
582 * @static
583 *
584 * TODO Why is this function in this class? It seems to be about the UFGroup.
585 */
586 public static function calculateProfileType($ufGroupType, $returnMixType = TRUE, $onlyPure = FALSE, $skipComponentType= FALSE) {
587 // profile types
588 $contactTypes = array('Contact', 'Individual', 'Household', 'Organization');
589 $subTypes = CRM_Contact_BAO_ContactType::subTypes();
590 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
591
592 $profileTypes = array();
593 if ($ufGroupType) {
594 $typeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $ufGroupType);
595 $profileTypes = explode(',', $typeParts[0]);
596 }
597
598 if ($onlyPure) {
599 if (count($profileTypes) == 1) {
600 return $profileTypes[0];
601 }
602 else {
603 return NULL;
604 }
605 }
606
607 //we need to unset Contact
608 if (count($profileTypes) > 1) {
609 $index = array_search('Contact', $profileTypes);
610 if ($index !== FALSE) {
611 unset($profileTypes[$index]);
612 }
613 }
614
615 $profileType = $mixProfileType = NULL;
616
617 // this case handles pure profile
618 if (count($profileTypes) == 1) {
619 $profileType = array_pop($profileTypes);
620 }
621 else {
622 //check the there are any components include in profile
623 $componentCount = array();
624 foreach ($components as $value) {
625 if (in_array($value, $profileTypes)) {
626 $componentCount[] = $value;
627 }
628 }
629
630 //check contact type included in profile
631 $contactTypeCount = array();
632 foreach ($contactTypes as $value) {
633 if (in_array($value, $profileTypes)) {
634 $contactTypeCount[] = $value;
635 }
636 }
637 // subtype counter
638 $subTypeCount = array();
639 foreach ($subTypes as $value) {
640 if (in_array($value, $profileTypes)) {
641 $subTypeCount[] = $value;
642 }
643 }
644 if (!$skipComponentType && count($componentCount) == 1) {
645 $profileType = $componentCount[0];
646 }
647 elseif (count($componentCount) > 1) {
648 $mixProfileType = $componentCount[1];
649 }
650 elseif (count($subTypeCount) == 1) {
651 $profileType = $subTypeCount[0];
652 }
653 elseif (count($contactTypeCount) == 1) {
654 $profileType = $contactTypeCount[0];
655 }
656 elseif (count($subTypeCount) > 1) {
657 // this is mix subtype profiles
658 $mixProfileType = $subTypeCount[1];
659 }
660 elseif (count($contactTypeCount) > 1) {
661 // this is mix contact profiles
662 $mixProfileType = $contactTypeCount[1];
663 }
664 }
665
666 if ($mixProfileType) {
667 if ($returnMixType) {
668 return $mixProfileType;
669 }
670 else {
671 return 'Mixed';
672 }
673 }
674 else {
675 return $profileType;
676 }
677 }
678
679 /**
680 * function to check for mix profiles groups (eg: individual + other contact types)
681 *
682 * @return true for mix profile group else false
683 * @acess public
684 * @static
685 */
686 static function checkProfileGroupType($ctype) {
687 $ufGroup = new CRM_Core_DAO_UFGroup();
688
689 $query = "
690 SELECT ufg.id as id
691 FROM civicrm_uf_group as ufg, civicrm_uf_join as ufj
692 WHERE ufg.id = ufj.uf_group_id
693 AND ufj.module = 'User Registration'
694 AND ufg.is_active = 1 ";
695
696 $ufGroup = CRM_Core_DAO::executeQuery($query);
697
698 $fields = array();
699 $validProfiles = array('Individual', 'Organization', 'Household', 'Contribution');
700 while ($ufGroup->fetch()) {
701 $profileType = self::getProfileType($ufGroup->id);
702 if (in_array($profileType, $validProfiles)) {
703 continue;
704 }
705 elseif ($profileType) {
706 return FALSE;
707 }
708 }
709
710 return TRUE;
711 }
712
713 /**
714 * check for searchable or in selector field for given profile.
715 *
716 * @params int $profileID profile id.
717 *
718 * @return boolean $result true/false.
719 */
720 static function checkSearchableORInSelector($profileID) {
721 $result = FALSE;
722 if (!$profileID) {
723 return $result;
724 }
725
726 $query = "
727 SELECT id
728 From civicrm_uf_field
729 WHERE (in_selector = 1 OR is_searchable = 1)
730 AND uf_group_id = {$profileID}";
731
732 $ufFields = CRM_Core_DAO::executeQuery($query);
733 while ($ufFields->fetch()) {
734 $result = TRUE;
735 break;
736 }
737
738 return $result;
739 }
740
741 /**
742 *Reset In selector and is seachable values for given $profileID.
743 *
744 * @params int $profileID profile id.
745 *
746 * @return void.
747 */
748 function resetInSelectorANDSearchable($profileID) {
749 if (!$profileID) {
750 return;
751 }
752 $query = "UPDATE civicrm_uf_field SET in_selector = 0, is_searchable = 0 WHERE uf_group_id = {$profileID}";
753 CRM_Core_DAO::executeQuery($query);
754 }
755
756 /**
757 * Add fields to $profileAddressFields as appropriate.
758 * profileAddressFields is assigned to the template to tell it
759 * what fields are in the profile address
760 * that potentially should be copied to the Billing fields
761 * we want to give precedence to
762 * 1) Billing &
763 * 2) then Primary designated as 'Primary
764 * 3) location_type is primary
765 * 4) if none of these apply then it just uses the first one
766 *
767 * as this will be used to
768 * transfer profile address data to billing fields
769 * http://issues.civicrm.org/jira/browse/CRM-5869
770 * @param string $key Field key - e.g. street_address-Primary, first_name
771 * @params array $profileAddressFields array of profile fields that relate to address fields
772 */
773 static function assignAddressField($key, &$profileAddressFields) {
774 $billing_id = CRM_Core_BAO_LocationType::getBilling();
775 list($prefixName, $index) = CRM_Utils_System::explode('-', $key, 2);
776
777 //check for valid fields ( fields that are present in billing block )
778 $validBillingFields = array(
779 'first_name',
780 'middle_name',
781 'last_name',
782 'street_address',
783 'supplemental_address_1',
784 'city',
785 'state_province',
786 'postal_code',
787 'country'
788 );
789
790 if (!in_array($prefixName, $validBillingFields)) {
791 return;
792 }
793
794 if (!empty($index) && (
795 // it's empty so we set it OR
796 !CRM_Utils_array::value($prefixName, $profileAddressFields)
797 //we are dealing with billing id (precedence)
798 || $index == $billing_id
799 // we are dealing with primary & billing not set
800 || ($index == 'Primary' && $profileAddressFields[$prefixName] != $billing_id)
801 || ($index == CRM_Core_BAO_LocationType::getDefault()->id
802 && $profileAddressFields[$prefixName] != $billing_id
803 && $profileAddressFields[$prefixName] != 'Primary'
804 )
805 )
806 ) {
807 $profileAddressFields[$prefixName] = $index;
808 }
809 }
810
811 /**
812 * Get a list of fields which can be added to profiles
813 *
814 * @param int $gid: UF group ID
815 * @param array $defaults: Form defaults
816 * @return array, multidimensional; e.g. $result['FieldGroup']['field_name']['label']
817 * @static
818 */
819 public static function getAvailableFields($gid = NULL, $defaults = array()) {
820 $fields = array(
821 'Contact' => array(),
822 'Individual' => CRM_Contact_BAO_Contact::importableFields('Individual', FALSE, FALSE, TRUE, TRUE, TRUE),
823 'Household' => CRM_Contact_BAO_Contact::importableFields('Household', FALSE, FALSE, TRUE, TRUE, TRUE),
824 'Organization' => CRM_Contact_BAO_Contact::importableFields('Organization', FALSE, FALSE, TRUE, TRUE, TRUE),
825 );
826
827 // add current employer for individuals
828 $fields['Individual']['current_employer'] = array(
829 'name' => 'organization_name',
830 'title' => ts('Current Employer'),
831 );
832
833 $addressOptions = CRM_Core_BAO_Setting::valueOptions(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
834 'address_options', TRUE, NULL, TRUE
835 );
836
837 if (!$addressOptions['county']) {
838 unset($fields['Individual']['county'], $fields['Household']['county'], $fields['Organization']['county']);
839 }
840
841 // break out common contact fields array CRM-3037.
842 // from a UI perspective this makes very little sense
843 foreach ($fields['Individual'] as $key => $value) {
844 if (!empty($fields['Household'][$key]) && !empty($fields['Organization'][$key])) {
845 $fields['Contact'][$key] = $value;
846 unset($fields['Individual'][$key], $fields['Household'][$key], $fields['Organization'][$key]);
847 }
848 }
849
850 // Internal field not exposed to forms
851 unset($fields['Contact']['contact_type']);
852 unset($fields['Contact']['master_id']);
853
854 // convert phone extension in to psedo-field phone + phone extension
855 //unset extension
856 unset($fields['Contact']['phone_ext']);
857 //add psedo field
858 $fields['Contact']['phone_and_ext'] = array(
859 'name' => 'phone_and_ext',
860 'title' => ts('Phone and Extension'),
861 'hasLocationType' => 1,
862 );
863
864 // include Subtypes For Profile
865 $subTypes = CRM_Contact_BAO_ContactType::subTypeInfo();
866 foreach ($subTypes as $name => $val) {
867 //custom fields for sub type
868 $subTypeFields = CRM_Core_BAO_CustomField::getFieldsForImport($name, FALSE, FALSE, FALSE, TRUE, TRUE);
869 if (array_key_exists($val['parent'], $fields)) {
870 $fields[$name] = $fields[$val['parent']] + $subTypeFields;
871 }
872 else {
873 $fields[$name] = $subTypeFields;
874 }
875 }
876
877 if (CRM_Core_Permission::access('CiviContribute')) {
878 $contribFields = CRM_Contribute_BAO_Contribution::getContributionFields(FALSE);
879 if (!empty($contribFields)) {
880 unset($contribFields['is_test']);
881 unset($contribFields['is_pay_later']);
882 unset($contribFields['contribution_id']);
883 $contribFields['contribution_note'] = array(
884 'name' => 'contribution_note',
885 'title' => ts('Contribution Note'),
886 );
887 if ($gid && CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'name') == 'contribution_batch_entry') {
888 $fields['Contribution'] = array_merge($contribFields, self::getContribBatchEntryFields());
889 }
890 else {
891 $fields['Contribution'] = $contribFields;
892 }
893 }
894 }
895
896 if (CRM_Core_Permission::access('CiviEvent')) {
897 $participantFields = CRM_Event_BAO_Query::getParticipantFields();
898 if ($participantFields) {
899 // Remove fields not supported by profiles
900 CRM_Utils_Array::remove($participantFields,
901 'external_identifier',
902 'event_id',
903 'participant_contact_id',
904 'participant_role_id',
905 'participant_status_id',
906 'participant_is_test',
907 'participant_fee_level',
908 'participant_id',
909 'participant_is_pay_later',
910 'participant_campaign'
911 );
912 if (isset($participantFields['participant_campaign_id'])) {
913 $participantFields['participant_campaign_id']['title'] = ts('Campaign');
914 }
915 $fields['Participant'] = $participantFields;
916 }
917 }
918
919 if (CRM_Core_Permission::access('CiviMember')) {
920 $membershipFields = CRM_Member_BAO_Membership::getMembershipFields();
921 // Remove fields not supported by profiles
922 CRM_Utils_Array::remove($membershipFields,
923 'membership_id',
924 'membership_type_id',
925 'member_is_test',
926 'is_override',
927 'status_id',
928 'member_is_pay_later'
929 );
930 if ($gid && CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'name') == 'membership_batch_entry') {
931 $fields['Membership'] = array_merge($membershipFields, self::getMemberBatchEntryFields());
932 }
933 else {
934 $fields['Membership'] = $membershipFields;
935 }
936 }
937
938 $activityFields = CRM_Activity_BAO_Activity::getProfileFields();
939 if ($activityFields) {
940 // campaign related fields.
941 if (isset($activityFields['activity_campaign_id'])) {
942 $activityFields['activity_campaign_id']['title'] = ts('Campaign');
943 }
944 $fields['Activity'] = $activityFields;
945 }
946
947 $fields['Formatting']['format_free_html_' . rand(1000, 9999)] = array(
948 'name' => 'free_html',
949 'import' => FALSE,
950 'export' => FALSE,
951 'title' => 'Free HTML',
952 );
953
954 // Sort by title
955 foreach ($fields as &$values) {
956 $values = CRM_Utils_Array::crmArraySortByField($values, 'title');
957 }
958
959 //group selected and unwanted fields list
960 $ufFields = $gid ? CRM_Core_BAO_UFGroup::getFields($gid, FALSE, NULL, NULL, NULL, TRUE, NULL, TRUE) : array();
961 $groupFieldList = array_merge($ufFields, array(
962 'note',
963 'email_greeting_custom',
964 'postal_greeting_custom',
965 'addressee_custom',
966 'id',
967 ));
968 //unset selected fields
969 foreach ($groupFieldList as $key => $value) {
970 if (is_integer($key)) {
971 unset($fields['Individual'][$value], $fields['Household'][$value], $fields['Organization'][$value]);
972 continue;
973 }
974 if (!empty($defaults['field_name'])
975 && $defaults['field_name']['0'] == $value['field_type']
976 && $defaults['field_name']['1'] == $key
977 ) {
978 continue;
979 }
980 unset($fields[$value['field_type']][$key]);
981 }
982
983 return $fields;
984 }
985
986 /**
987 * Get a list of fields which can be added to profiles
988 *
989 * @return array, multidimensional; e.g. $result['field_name']['label']
990 * @static
991 */
992 public static function getAvailableFieldsFlat($force = FALSE) {
993 // FIXME reset when data model changes
994 static $result = NULL;
995 if ($result === NULL || $force) {
996 $fieldTree = self::getAvailableFields();
997 $result = array();
998 foreach ($fieldTree as $field_type => $fields) {
999 foreach ($fields as $field_name => $field) {
1000 if (!isset($result[$field_name])) {
1001 $field['field_type'] = $field_type;
1002 $result[$field_name] = $field;
1003 }
1004 }
1005 }
1006 }
1007 return $result;
1008 }
1009
1010 /**
1011 * Determine whether the given field_name is valid
1012 *
1013 * @param string $fieldName
1014 * @return bool
1015 */
1016 static function isValidFieldName($fieldName) {
1017 $availableFields = CRM_Core_BAO_UFField::getAvailableFieldsFlat();
1018 return isset($availableFields[$fieldName]);
1019 }
1020
1021 static function getContribBatchEntryFields() {
1022 if (self::$_contriBatchEntryFields === NULL) {
1023 self::$_contriBatchEntryFields = array(
1024 'send_receipt' => array(
1025 'name' => 'send_receipt',
1026 'title' => ts('Send Receipt'),
1027 ),
1028 'soft_credit' => array(
1029 'name' => 'soft_credit',
1030 'title' => ts('Soft Credit'),
1031 ),
1032 'product_name' => array(
1033 'name' => 'product_name',
1034 'title' => ts('Premiums'),
1035 ),
1036 'contribution_note' => array(
1037 'name' => 'contribution_note',
1038 'title' => ts('Contribution Note'),
1039 ),
1040 );
1041 }
1042 return self::$_contriBatchEntryFields;
1043 }
1044
1045 public static function getMemberBatchEntryFields() {
1046 if (self::$_memberBatchEntryFields === NULL) {
1047 self::$_memberBatchEntryFields = array(
1048 'send_receipt' => array(
1049 'name' => 'send_receipt',
1050 'title' => ts('Send Receipt'),
1051 ),
1052 'soft_credit' => array(
1053 'name' => 'soft_credit',
1054 'title' => ts('Soft Credit'),
1055 ),
1056 'product_name' => array(
1057 'name' => 'product_name',
1058 'title' => ts('Premiums'),
1059 ),
1060 'financial_type' => array(
1061 'name' => 'financial_type',
1062 'title' => ts('Financial Type'),
1063 ),
1064 'total_amount' => array(
1065 'name' => 'total_amount',
1066 'title' => ts('Total Amount'),
1067 ),
1068 'receive_date' => array(
1069 'name' => 'receive_date',
1070 'title' => ts('Receive Date'),
1071 ),
1072 'payment_instrument' => array(
1073 'name' => 'payment_instrument',
1074 'title' => ts('Payment Instrument'),
1075 ),
1076 'contribution_status_id' => array(
1077 'name' => 'contribution_status_id',
1078 'title' => ts('Contribution Status'),
1079 ),
1080 );
1081 }
1082 return self::$_memberBatchEntryFields;
1083 }
1084 }
1085