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