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