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