Merge pull request #9773 from monishdeb/CRM-19663
[civicrm-core.git] / CRM / Core / BAO / UFGroup.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2017 |
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-2017
32 */
33
34 /**
35 * UF group BAO class.
36 */
37 class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup {
38 const PUBLIC_VISIBILITY = 1,
39 ADMIN_VISIBILITY = 2,
40 LISTINGS_VISIBILITY = 4;
41
42 /**
43 * Cache the match clause used in this transaction.
44 *
45 * @var string
46 */
47 static $_matchFields = NULL;
48
49 /**
50 * Fetch object based on array of properties.
51 *
52 * @param array $params
53 * (reference) an assoc array of name/value pairs.
54 * @param array $defaults
55 * (reference) an assoc array to hold the flattened values.
56 *
57 * @return object
58 * CRM_Core_DAO_UFGroup object
59 */
60 public static function retrieve(&$params, &$defaults) {
61 return CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_UFGroup', $params, $defaults);
62 }
63
64 /**
65 * Retrieve the first non-generic contact type
66 *
67 * @param int $id
68 * Id of uf_group.
69 *
70 * @return string
71 * contact type
72 */
73 public static function getContactType($id) {
74
75 $validTypes = array_filter(array_keys(CRM_Core_SelectValues::contactType()));
76 $validSubTypes = CRM_Contact_BAO_ContactType::subTypeInfo();
77
78 $typesParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $id, 'group_type'));
79 $types = explode(',', $typesParts[0]);
80
81 $cType = NULL;
82 foreach ($types as $type) {
83 if (in_array($type, $validTypes)) {
84 $cType = $type;
85 }
86 elseif (array_key_exists($type, $validSubTypes)) {
87 $cType = CRM_Utils_Array::value('parent', $validSubTypes[$type]);
88 }
89 if ($cType) {
90 break;
91 }
92 }
93
94 return $cType;
95 }
96
97 /**
98 * Get the form title.
99 *
100 * @param int $id
101 * Id of uf_form.
102 *
103 * @return string
104 * title
105 *
106 */
107 public static function getTitle($id) {
108 return CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $id, 'title');
109 }
110
111 /**
112 * Update the is_active flag in the db.
113 *
114 * @param int $id
115 * Id of the database record.
116 * @param bool $is_active
117 * Value we want to set the is_active field.
118 *
119 * @return Object
120 * CRM_Core_DAO_UFGroup object on success, null otherwise
121 */
122 public static function setIsActive($id, $is_active) {
123 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFGroup', $id, 'is_active', $is_active);
124 }
125
126 /**
127 * Get all the registration fields.
128 *
129 * @param int $action
130 * What action are we doing.
131 * @param int $mode
132 * Mode.
133 *
134 * @param null $ctype
135 *
136 * @return array
137 * the fields that are needed for registration
138 */
139 public static function getRegistrationFields($action, $mode, $ctype = NULL) {
140 if ($mode & CRM_Profile_Form::MODE_REGISTER) {
141 $ufGroups = CRM_Core_BAO_UFGroup::getModuleUFGroup('User Registration');
142 }
143 else {
144 $ufGroups = CRM_Core_BAO_UFGroup::getModuleUFGroup('Profile');
145 }
146
147 if (!is_array($ufGroups)) {
148 return FALSE;
149 }
150
151 $fields = array();
152
153 foreach ($ufGroups as $id => $title) {
154 if ($ctype) {
155 $fieldType = CRM_Core_BAO_UFField::getProfileType($id);
156 if (($fieldType != 'Contact') &&
157 ($fieldType != $ctype) &&
158 !CRM_Contact_BAO_ContactType::isExtendsContactType($fieldType, $ctype)
159 ) {
160 continue;
161 }
162 if (CRM_Contact_BAO_ContactType::isaSubType($fieldType)) {
163 $profileSubType = $fieldType;
164 }
165 }
166
167 $subset = self::getFields($id, TRUE, $action,
168 NULL, NULL, FALSE, NULL, TRUE, $ctype
169 );
170
171 // we do not allow duplicates. the first field is the winner
172 foreach ($subset as $name => $field) {
173 if (empty($fields[$name])) {
174 $fields[$name] = $field;
175 }
176 }
177 }
178
179 return $fields;
180 }
181
182 /**
183 * Get all the listing fields.
184 *
185 * @param int $action
186 * What action are we doing.
187 * @param int $visibility
188 * Visibility of fields we are interested in.
189 * @param bool $considerSelector
190 * Whether to consider the in_selector parameter.
191 * @param array $ufGroupIds
192 * @param bool $searchable
193 *
194 * @param null $restrict
195 * @param bool $skipPermission
196 * @param int $permissionType
197 * @return array
198 * the fields that are listings related
199 */
200 public static function getListingFields(
201 $action,
202 $visibility,
203 $considerSelector = FALSE,
204 $ufGroupIds = NULL,
205 $searchable = NULL,
206 $restrict = NULL,
207 $skipPermission = FALSE,
208 $permissionType = CRM_Core_Permission::SEARCH
209 ) {
210 if ($ufGroupIds) {
211 $subset = self::getFields($ufGroupIds, FALSE, $action,
212 $visibility, $searchable,
213 FALSE, $restrict,
214 $skipPermission,
215 NULL,
216 $permissionType
217 );
218 if ($considerSelector) {
219 // drop the fields not meant for the selector
220 foreach ($subset as $name => $field) {
221 if (!$field['in_selector']) {
222 unset($subset[$name]);
223 }
224 }
225 }
226 $fields = $subset;
227 }
228 else {
229 $ufGroups = CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id');
230
231 $fields = array();
232 foreach ($ufGroups as $id => $title) {
233 $subset = self::getFields($id, FALSE, $action,
234 $visibility, $searchable,
235 FALSE, $restrict,
236 $skipPermission,
237 NULL,
238 $permissionType
239 );
240 if ($considerSelector) {
241 // drop the fields not meant for the selector
242 foreach ($subset as $name => $field) {
243 if (!$field['in_selector']) {
244 unset($subset[$name]);
245 }
246 }
247 }
248 $fields = array_merge($fields, $subset);
249 }
250 }
251 return $fields;
252 }
253
254 /**
255 * Get all the fields that belong to the group with the name title,
256 * and format for use with buildProfile. This is the SQL analog of
257 * formatUFFields().
258 *
259 * @param mix $id
260 * The id of the UF group or ids of ufgroup.
261 * @param bool|int $register are we interested in registration fields
262 * @param int $action
263 * What action are we doing.
264 * @param int $visibility
265 * Visibility of fields we are interested in.
266 * @param $searchable
267 * @param bool $showAll
268 * @param string $restrict
269 * Should we restrict based on a specified profile type.
270 * @param bool $skipPermission
271 * @param null $ctype
272 * @param int $permissionType
273 * @param string $orderBy
274 * @param null $orderProfiles
275 *
276 * @param bool $eventProfile
277 *
278 * @return array
279 * The fields that belong to this ufgroup(s)
280 * @throws \Exception
281 */
282 public static function getFields(
283 $id,
284 $register = FALSE,
285 $action = NULL,
286 $visibility = NULL,
287 $searchable = NULL,
288 $showAll = FALSE,
289 $restrict = NULL,
290 $skipPermission = FALSE,
291 $ctype = NULL,
292 $permissionType = CRM_Core_Permission::CREATE,
293 $orderBy = 'field_name',
294 $orderProfiles = NULL,
295 $eventProfile = FALSE
296 ) {
297 if (!is_array($id)) {
298 $id = CRM_Utils_Type::escape($id, 'Positive');
299 $profileIds = array($id);
300 }
301 else {
302 $profileIds = $id;
303 }
304
305 $gids = implode(',', $profileIds);
306 $params = array();
307 if ($restrict) {
308 $query = "SELECT g.* from civicrm_uf_group g
309 LEFT JOIN civicrm_uf_join j ON (j.uf_group_id = g.id)
310 WHERE g.id IN ( {$gids} )
311 AND ((j.uf_group_id IN ( {$gids} ) AND j.module = %1) OR g.is_reserved = 1 )
312 ";
313 $params = array(1 => array($restrict, 'String'));
314 }
315 else {
316 $query = "SELECT g.* from civicrm_uf_group g WHERE g.id IN ( {$gids} ) ";
317 }
318
319 if (!$showAll) {
320 $query .= " AND g.is_active = 1";
321 }
322
323 $checkPermission = array(
324 array(
325 'administer CiviCRM',
326 'manage event profiles',
327 ),
328 );
329 if ($eventProfile && CRM_Core_Permission::check($checkPermission)) {
330 $skipPermission = TRUE;
331 }
332
333 // add permissioning for profiles only if not registration
334 if (!$skipPermission) {
335 $permissionClause = CRM_Core_Permission::ufGroupClause($permissionType, 'g.');
336 $query .= " AND $permissionClause ";
337 }
338
339 if ($orderProfiles AND count($profileIds) > 1) {
340 $query .= " ORDER BY FIELD( g.id, {$gids} )";
341 }
342 $group = CRM_Core_DAO::executeQuery($query, $params);
343 $fields = array();
344 $validGroup = FALSE;
345
346 while ($group->fetch()) {
347 $validGroup = TRUE;
348 $query = self::createUFFieldQuery($group->id, $searchable, $showAll, $visibility, $orderBy);
349 $field = CRM_Core_DAO::executeQuery($query);
350
351 $importableFields = self::getProfileFieldMetadata($showAll);
352 list($customFields, $addressCustomFields) = self::getCustomFields($ctype);
353
354 while ($field->fetch()) {
355 list($name, $formattedField) = self::formatUFField($group, $field, $customFields, $addressCustomFields, $importableFields, $permissionType);
356 if ($formattedField !== NULL) {
357 $fields[$name] = $formattedField;
358 }
359 }
360 $field->free();
361 }
362
363 if (empty($fields) && !$validGroup) {
364 CRM_Core_Error::fatal(ts('The requested Profile (gid=%1) is disabled OR it is not configured to be used for \'Profile\' listings in its Settings OR there is no Profile with that ID OR you do not have permission to access this profile. Please contact the site administrator if you need assistance.',
365 array(1 => implode(',', $profileIds))
366 ));
367 }
368 else {
369 self::reformatProfileFields($fields);
370 }
371
372 return $fields;
373 }
374
375 /**
376 * Format a list of UFFields for use with buildProfile. This is the in-memory analog
377 * of getFields().
378 *
379 * @param array $groupArr
380 * (mimic CRM_UF_DAO_UFGroup).
381 * @param array $fieldArrs
382 * List of fields (each mimics CRM_UF_DAO_UFField).
383 * @param bool $visibility
384 * Visibility of fields we are interested in.
385 * @param bool $searchable
386 * @param bool $showAll
387 * @param null $ctype
388 * @param int $permissionType
389 *
390 * @return array
391 * @see self::getFields
392 */
393 public static function formatUFFields(
394 $groupArr,
395 $fieldArrs,
396 $visibility = NULL,
397 $searchable = NULL,
398 $showAll = FALSE,
399 $ctype = NULL,
400 $permissionType = CRM_Core_Permission::CREATE
401 ) {
402 // $group = new CRM_Core_DAO_UFGroup();
403 // $group->copyValues($groupArr); // no... converts string('') to string('null')
404 $group = (object) $groupArr;
405
406 // Refactoring note: The $fieldArrs here may be slightly different than the $ufFields
407 // used by calculateGroupType, but I don't think the missing fields matter, and -- if
408 // they did -- the obvious fix would produce mutual recursion.
409 $ufGroupType = self::_calculateGroupType($fieldArrs);
410 $profileType = CRM_Core_BAO_UFField::calculateProfileType(implode(',', $ufGroupType));
411 $contactActivityProfile = CRM_Core_BAO_UFField::checkContactActivityProfileTypeByGroupType(implode(',', $ufGroupType));
412 $importableFields = self::getImportableFields($showAll, $profileType, $contactActivityProfile);
413 list($customFields, $addressCustomFields) = self::getCustomFields($ctype);
414
415 $formattedFields = array();
416 foreach ($fieldArrs as $fieldArr) {
417 $field = (object) $fieldArr;
418 if (!self::filterUFField($field, $searchable, $showAll, $visibility)) {
419 continue;
420 }
421
422 list($name, $formattedField) = self::formatUFField($group, $field, $customFields, $addressCustomFields, $importableFields, $permissionType);
423 if ($formattedField !== NULL) {
424 $formattedFields[$name] = $formattedField;
425 }
426 }
427 return $formattedFields;
428 }
429
430 /**
431 * Prepare a field for rendering with CRM_Core_BAO_UFGroup::buildProfile.
432 *
433 * @param CRM_Core_DAO_UFGroup|CRM_Core_DAO $group
434 * @param CRM_Core_DAO_UFField|CRM_Core_DAO $field
435 * @param array $customFields
436 * @param array $addressCustomFields
437 * @param array $importableFields
438 * @param int $permissionType
439 * Eg CRM_Core_Permission::CREATE.
440 * @return array
441 */
442 protected static function formatUFField(
443 $group,
444 $field,
445 $customFields,
446 $addressCustomFields,
447 $importableFields,
448 $permissionType = CRM_Core_Permission::CREATE
449 ) {
450 $name = $field->field_name;
451 $title = $field->label;
452
453 $addressCustom = FALSE;
454 if (in_array($permissionType, array(
455 CRM_Core_Permission::CREATE,
456 CRM_Core_Permission::EDIT,
457 )) &&
458 in_array($field->field_name, array_keys($addressCustomFields))
459 ) {
460 $addressCustom = TRUE;
461 $name = "address_{$name}";
462 }
463 if ($field->field_name == 'url') {
464 $name .= "-{$field->website_type_id}";
465 }
466 elseif (!empty($field->location_type_id)) {
467 $name .= "-{$field->location_type_id}";
468 }
469 else {
470 $locationFields = self::getLocationFields();
471 if (in_array($field->field_name, $locationFields) || $addressCustom) {
472 $name .= '-Primary';
473 }
474 }
475
476 if (isset($field->phone_type_id)) {
477 $name .= "-{$field->phone_type_id}";
478 }
479 $fieldMetaData = CRM_Utils_Array::value($name, $importableFields, (isset($importableFields[$field->field_name]) ? $importableFields[$field->field_name] : array()));
480
481 // No lie: this is bizarre; why do we need to mix so many UFGroup properties into UFFields?
482 // I guess to make field self sufficient with all the required data and avoid additional calls
483 $formattedField = array(
484 'name' => $name,
485 'groupTitle' => $group->title,
486 'groupName' => $group->name,
487 'groupHelpPre' => empty($group->help_pre) ? '' : $group->help_pre,
488 'groupHelpPost' => empty($group->help_post) ? '' : $group->help_post,
489 'title' => $title,
490 'where' => CRM_Utils_Array::value('where', CRM_Utils_Array::value($field->field_name, $importableFields)),
491 'attributes' => CRM_Core_DAO::makeAttribute(CRM_Utils_Array::value($field->field_name, $importableFields)),
492 'is_required' => $field->is_required,
493 'is_view' => $field->is_view,
494 'help_pre' => $field->help_pre,
495 'help_post' => $field->help_post,
496 'visibility' => $field->visibility,
497 'in_selector' => $field->in_selector,
498 'rule' => CRM_Utils_Array::value('rule', CRM_Utils_Array::value($field->field_name, $importableFields)),
499 'location_type_id' => isset($field->location_type_id) ? $field->location_type_id : NULL,
500 'website_type_id' => isset($field->website_type_id) ? $field->website_type_id : NULL,
501 'phone_type_id' => isset($field->phone_type_id) ? $field->phone_type_id : NULL,
502 'group_id' => $group->id,
503 'add_to_group_id' => isset($group->add_to_group_id) ? $group->add_to_group_id : NULL,
504 'add_captcha' => isset($group->add_captcha) ? $group->add_captcha : NULL,
505 'field_type' => $field->field_type,
506 'field_id' => $field->id,
507 'pseudoconstant' => CRM_Utils_Array::value(
508 'pseudoconstant',
509 CRM_Utils_Array::value($field->field_name, $importableFields)
510 ),
511 // obsolete this when we remove the name / dbName discrepancy with gender/suffix/prefix
512 'dbName' => CRM_Utils_Array::value(
513 'dbName',
514 CRM_Utils_Array::value($field->field_name, $importableFields)
515 ),
516 'skipDisplay' => 0,
517 'data_type' => CRM_Utils_Type::getDataTypeFromFieldMetadata($fieldMetaData),
518 'bao' => CRM_Utils_Array::value('bao', $fieldMetaData),
519 );
520
521 $formattedField = CRM_Utils_Date::addDateMetadataToField($fieldMetaData, $formattedField);
522
523 //adding custom field property
524 if (substr($field->field_name, 0, 6) == 'custom' ||
525 substr($field->field_name, 0, 14) === 'address_custom'
526 ) {
527 // if field is not present in customFields, that means the user
528 // DOES NOT HAVE permission to access that field
529 if (array_key_exists($field->field_name, $customFields)) {
530 $formattedField['is_search_range'] = $customFields[$field->field_name]['is_search_range'];
531 // fix for CRM-1994
532 $formattedField['options_per_line'] = $customFields[$field->field_name]['options_per_line'];
533 $formattedField['html_type'] = $customFields[$field->field_name]['html_type'];
534
535 if (CRM_Utils_Array::value('html_type', $formattedField) == 'Select Date') {
536 $formattedField['date_format'] = $customFields[$field->field_name]['date_format'];
537 $formattedField['time_format'] = $customFields[$field->field_name]['time_format'];
538 $formattedField['is_datetime_field'] = TRUE;
539 $formattedField['smarty_view_format'] = CRM_Utils_Date::getDateFieldViewFormat($formattedField['date_format']);
540 }
541
542 $formattedField['is_multi_summary'] = $field->is_multi_summary;
543 return array($name, $formattedField);
544 }
545 else {
546 $formattedField = NULL;
547 return array($name, $formattedField);
548 }
549 }
550 return array($name, $formattedField);
551 }
552
553 /**
554 * Create a query to find all visible UFFields in a UFGroup.
555 *
556 * This is the SQL-variant of checkUFFieldDisplayable().
557 *
558 * @param int $groupId
559 * @param bool $searchable
560 * @param bool $showAll
561 * @param int $visibility
562 * @param string $orderBy
563 * Comma-delimited list of SQL columns.
564 * @return string
565 */
566 protected static function createUFFieldQuery($groupId, $searchable, $showAll, $visibility, $orderBy) {
567 $where = " WHERE uf_group_id = {$groupId}";
568
569 if ($searchable) {
570 $where .= " AND is_searchable = 1";
571 }
572
573 if (!$showAll) {
574 $where .= " AND is_active = 1";
575 }
576
577 if ($visibility) {
578 $clause = array();
579 if ($visibility & self::PUBLIC_VISIBILITY) {
580 $clause[] = 'visibility = "Public Pages"';
581 }
582 if ($visibility & self::ADMIN_VISIBILITY) {
583 $clause[] = 'visibility = "User and User Admin Only"';
584 }
585 if ($visibility & self::LISTINGS_VISIBILITY) {
586 $clause[] = 'visibility = "Public Pages and Listings"';
587 }
588 if (!empty($clause)) {
589 $where .= ' AND ( ' . implode(' OR ', $clause) . ' ) ';
590 }
591 }
592
593 $query = "SELECT * FROM civicrm_uf_field $where ORDER BY weight";
594 if ($orderBy) {
595 $query .= ", " . $orderBy;
596 return $query;
597 }
598 return $query;
599 }
600
601 /**
602 * Create a query to find all visible UFFields in a UFGroup.
603 *
604 * This is the PHP in-memory variant of createUFFieldQuery().
605 *
606 * @param CRM_Core_DAO_UFField|CRM_Core_DAO $field
607 * @param bool $searchable
608 * @param bool $showAll
609 * @param int $visibility
610 * @return bool
611 * TRUE if field is displayable
612 */
613 protected static function filterUFField($field, $searchable, $showAll, $visibility) {
614 if ($searchable && $field->is_searchable != 1) {
615 return FALSE;
616 }
617
618 if (!$showAll && $field->is_active != 1) {
619 return FALSE;
620 }
621
622 if ($visibility) {
623 $allowedVisibilities = array();
624 if ($visibility & self::PUBLIC_VISIBILITY) {
625 $allowedVisibilities[] = 'Public Pages';
626 }
627 if ($visibility & self::ADMIN_VISIBILITY) {
628 $allowedVisibilities[] = 'User and User Admin Only';
629 }
630 if ($visibility & self::LISTINGS_VISIBILITY) {
631 $allowedVisibilities[] = 'Public Pages and Listings';
632 }
633 // !empty($allowedVisibilities) seems silly to me, but it is equivalent to the pre-existing SQL
634 if (!empty($allowedVisibilities) && !in_array($field->visibility, $allowedVisibilities)) {
635 return FALSE;
636 }
637 }
638
639 return TRUE;
640 }
641
642 /**
643 * Get a list of filtered field metadata.
644 *
645 * @deprecated use getProfileFieldMetadata
646 *
647 * @param $showAll
648 * @param $profileType
649 * @param $contactActivityProfile
650 * @param bool $filterMode
651 * Filter mode means you are using importable fields for filtering rather than just getting metadata.
652 * With filter mode = FALSE BOTH activity fields and component fields are returned.
653 * I can't see why you would ever want to use this function in filter mode as the component fields are
654 * still unfiltered. However, I feel scared enough to leave it as it is. I have marked this function as
655 * deprecated and am recommending the wrapper 'getProfileFieldMetadata' in order to try to
656 * send this confusion to history.
657 *
658 * @return array
659 */
660 protected static function getImportableFields($showAll, $profileType, $contactActivityProfile, $filterMode = TRUE) {
661 if (!$showAll) {
662 $importableFields = CRM_Contact_BAO_Contact::importableFields('All', FALSE, FALSE, FALSE, TRUE, TRUE);
663 }
664 else {
665 $importableFields = CRM_Contact_BAO_Contact::importableFields('All', FALSE, TRUE, FALSE, TRUE, TRUE);
666 }
667
668 $activityFields = CRM_Activity_BAO_Activity::getProfileFields();
669 $componentFields = CRM_Core_Component::getQueryFields();
670 if ($filterMode == TRUE) {
671 if ($profileType == 'Activity' || $contactActivityProfile) {
672 $importableFields = array_merge($importableFields, $activityFields);
673 }
674 else {
675 $importableFields = array_merge($importableFields, $componentFields);
676 }
677 }
678 else {
679 $importableFields = array_merge($importableFields, $activityFields, $componentFields);
680 }
681
682 $importableFields['group']['title'] = ts('Group(s)');
683 $importableFields['group']['where'] = NULL;
684 $importableFields['tag']['title'] = ts('Tag(s)');
685 $importableFields['tag']['where'] = NULL;
686 return $importableFields;
687 }
688
689 /**
690 * Get the metadata for all potential profile fields.
691 *
692 * @param bool $isIncludeInactive
693 * Should disabled fields be included.
694 *
695 * @return array
696 * Field metadata for all fields that might potentially be in a profile.
697 */
698 protected static function getProfileFieldMetadata($isIncludeInactive) {
699 return self::getImportableFields($isIncludeInactive, NULL, NULL, NULL, TRUE);
700 }
701
702 /**
703 * Get the fields relating to locations.
704 *
705 * @return array
706 */
707 public static function getLocationFields() {
708 static $locationFields = array(
709 'street_address',
710 'supplemental_address_1',
711 'supplemental_address_2',
712 'city',
713 'postal_code',
714 'postal_code_suffix',
715 'geo_code_1',
716 'geo_code_2',
717 'state_province',
718 'country',
719 'county',
720 'phone',
721 'phone_and_ext',
722 'email',
723 'im',
724 'address_name',
725 'phone_ext',
726 );
727 return $locationFields;
728 }
729
730 /**
731 * @param $ctype
732 *
733 * @return mixed
734 */
735 protected static function getCustomFields($ctype) {
736 static $customFieldCache = array();
737 if (!isset($customFieldCache[$ctype])) {
738 $customFields = CRM_Core_BAO_CustomField::getFieldsForImport($ctype, FALSE, FALSE, FALSE, TRUE, TRUE);
739
740 // hack to add custom data for components
741 $components = array('Contribution', 'Participant', 'Membership', 'Activity', 'Case');
742 foreach ($components as $value) {
743 $customFields = array_merge($customFields, CRM_Core_BAO_CustomField::getFieldsForImport($value));
744 }
745 $addressCustomFields = CRM_Core_BAO_CustomField::getFieldsForImport('Address');
746 $customFields = array_merge($customFields, $addressCustomFields);
747 $customFieldCache[$ctype] = array($customFields, $addressCustomFields);
748 }
749 return $customFieldCache[$ctype];
750 }
751
752 /**
753 * Check the data validity.
754 *
755 * @param int $userID
756 * The user id that we are actually editing.
757 * @param string $name
758 * The machine-name of the group we are interested in.
759 * @param bool $register
760 * @param int $action
761 * The action of the form.
762 *
763 * @pram boolean $register is this the registrtion form
764 * @return bool
765 * true if form is valid
766 */
767 public static function isValid($userID, $name, $register = FALSE, $action = NULL) {
768 if ($register) {
769 $controller = new CRM_Core_Controller_Simple('CRM_Profile_Form_Dynamic',
770 ts('Dynamic Form Creator'),
771 $action
772 );
773 $controller->set('id', $userID);
774 $controller->set('register', 1);
775 $controller->process();
776 return $controller->validate();
777 }
778 else {
779 // make sure we have a valid group
780 $group = new CRM_Core_DAO_UFGroup();
781
782 $group->name = $name;
783
784 if ($group->find(TRUE) && $userID) {
785 $controller = new CRM_Core_Controller_Simple('CRM_Profile_Form_Dynamic', ts('Dynamic Form Creator'), $action);
786 $controller->set('gid', $group->id);
787 $controller->set('id', $userID);
788 $controller->set('register', 0);
789 $controller->process();
790 return $controller->validate();
791 }
792 return TRUE;
793 }
794 }
795
796 /**
797 * Get the html for the form that represents this particular group.
798 *
799 * @param int $userID
800 * The user id that we are actually editing.
801 * @param string $title
802 * The title of the group we are interested in.
803 * @param int $action
804 * The action of the form.
805 * @param bool $register
806 * Is this the registration form.
807 * @param bool $reset
808 * Should we reset the form?.
809 * @param int $profileID
810 * Do we have the profile ID?.
811 *
812 * @param bool $doNotProcess
813 * @param null $ctype
814 *
815 * @return string
816 * the html for the form on success, otherwise empty string
817 */
818 public static function getEditHTML(
819 $userID,
820 $title,
821 $action = NULL,
822 $register = FALSE,
823 $reset = FALSE,
824 $profileID = NULL,
825 $doNotProcess = FALSE,
826 $ctype = NULL
827 ) {
828
829 if ($register) {
830 $controller = new CRM_Core_Controller_Simple('CRM_Profile_Form_Dynamic',
831 ts('Dynamic Form Creator'),
832 $action
833 );
834 if ($reset || $doNotProcess) {
835 // hack to make sure we do not process this form
836 $oldQFDefault = CRM_Utils_Array::value('_qf_default',
837 $_POST
838 );
839 unset($_POST['_qf_default']);
840 unset($_REQUEST['_qf_default']);
841 if ($reset) {
842 $controller->reset();
843 }
844 }
845
846 $controller->set('id', $userID);
847 $controller->set('register', 1);
848 $controller->set('skipPermission', 1);
849 $controller->set('ctype', $ctype);
850 $controller->process();
851 if ($doNotProcess || !empty($_POST)) {
852 $controller->validate();
853 }
854 $controller->setEmbedded(TRUE);
855
856 //CRM-5839 - though we want to process form, get the control back.
857 $controller->setSkipRedirection(($doNotProcess) ? FALSE : TRUE);
858
859 $controller->run();
860
861 // we are done processing so restore the POST/REQUEST vars
862 if (($reset || $doNotProcess) && $oldQFDefault) {
863 $_POST['_qf_default'] = $_REQUEST['_qf_default'] = $oldQFDefault;
864 }
865
866 $template = CRM_Core_Smarty::singleton();
867
868 // Hide CRM error messages if they are displayed using drupal form_set_error.
869 if (!empty($_POST)) {
870 $template->assign('suppressForm', TRUE);
871 }
872
873 return trim($template->fetch('CRM/Profile/Form/Dynamic.tpl'));
874 }
875 else {
876 if (!$profileID) {
877 // make sure we have a valid group
878 $group = new CRM_Core_DAO_UFGroup();
879
880 $group->title = $title;
881
882 if ($group->find(TRUE)) {
883 $profileID = $group->id;
884 }
885 }
886
887 if ($profileID) {
888 // make sure profileID and ctype match if ctype exists
889 if ($ctype) {
890 $profileType = CRM_Core_BAO_UFField::getProfileType($profileID);
891 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
892 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
893 }
894
895 if (($profileType != 'Contact') && ($profileType != $ctype)) {
896 return NULL;
897 }
898 }
899
900 $controller = new CRM_Core_Controller_Simple('CRM_Profile_Form_Dynamic',
901 ts('Dynamic Form Creator'),
902 $action
903 );
904 if ($reset) {
905 $controller->reset();
906 }
907 $controller->set('gid', $profileID);
908 $controller->set('id', $userID);
909 $controller->set('register', 0);
910 $controller->set('skipPermission', 1);
911 if ($ctype) {
912 $controller->set('ctype', $ctype);
913 }
914 $controller->process();
915 $controller->setEmbedded(TRUE);
916
917 //CRM-5846 - give the control back to drupal.
918 $controller->setSkipRedirection(($doNotProcess) ? FALSE : TRUE);
919 $controller->run();
920
921 $template = CRM_Core_Smarty::singleton();
922
923 // Hide CRM error messages if they are displayed using drupal form_set_error.
924 if (!empty($_POST) && CRM_Core_Config::singleton()->userFramework == 'Drupal') {
925 if (arg(0) == 'user' || (arg(0) == 'admin' && arg(1) == 'people')) {
926 $template->assign('suppressForm', TRUE);
927 }
928 }
929
930 $templateFile = "CRM/Profile/Form/{$profileID}/Dynamic.tpl";
931 if (!$template->template_exists($templateFile)) {
932 $templateFile = 'CRM/Profile/Form/Dynamic.tpl';
933 }
934 return trim($template->fetch($templateFile));
935 }
936 else {
937 $userEmail = CRM_Contact_BAO_Contact_Location::getEmailDetails($userID);
938
939 // if post not empty then only proceed
940 if (!empty($_POST)) {
941 // get the new email
942 $config = CRM_Core_Config::singleton();
943 $email = CRM_Utils_Array::value('mail', $_POST);
944
945 if (CRM_Utils_Rule::email($email) && ($email != $userEmail[1])) {
946 CRM_Core_BAO_UFMatch::updateContactEmail($userID, $email);
947 }
948 }
949 }
950 }
951 return '';
952 }
953
954 /**
955 * Searches for a contact in the db with similar attributes.
956 *
957 * @param array $params
958 * The list of values to be used in the where clause.
959 * @param int $id
960 * The current contact id (hence excluded from matching).
961 * @param string $contactType
962 *
963 * @return int|null
964 * contact_id if found, null otherwise
965 */
966 public static function findContact(&$params, $id = NULL, $contactType = 'Individual') {
967 $ids = CRM_Contact_BAO_Contact::getDuplicateContacts($params, $contactType, 'Supervised', array($id), CRM_Utils_Array::value('check_permission', $params, TRUE));
968 if (!empty($ids)) {
969 return implode(',', $ids);
970 }
971 else {
972 return NULL;
973 }
974 }
975
976 /**
977 * Given a contact id and a field set, return the values from the db.
978 *
979 * @param int $cid
980 * @param array $fields
981 * The profile fields of interest.
982 * @param array $values
983 * The values for the above fields.
984 * @param bool $searchable
985 * Searchable or not.
986 * @param array $componentWhere
987 * Component condition.
988 * @param bool $absolute
989 * Return urls in absolute form (useful when sending an email).
990 * @param null $additionalWhereClause
991 *
992 * @return null|array
993 */
994 public static function getValues(
995 $cid, &$fields, &$values,
996 $searchable = TRUE, $componentWhere = NULL,
997 $absolute = FALSE, $additionalWhereClause = NULL
998 ) {
999 if (empty($cid) && empty($componentWhere)) {
1000 return NULL;
1001 }
1002
1003 // get the contact details (hier)
1004 $returnProperties = CRM_Contact_BAO_Contact::makeHierReturnProperties($fields);
1005 $params = $cid ? array(array('contact_id', '=', $cid, 0, 0)) : array();
1006
1007 // add conditions specified by components. eg partcipant_id etc
1008 if (!empty($componentWhere)) {
1009 $params = array_merge($params, $componentWhere);
1010 }
1011
1012 $query = new CRM_Contact_BAO_Query($params, $returnProperties, $fields);
1013
1014 $details = $query->searchQuery(0, 0, NULL, FALSE, FALSE,
1015 FALSE, FALSE, FALSE, $additionalWhereClause);
1016 if (!$details->fetch()) {
1017 return;
1018 }
1019 $query->convertToPseudoNames($details);
1020 $config = CRM_Core_Config::singleton();
1021
1022 $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
1023 $imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
1024 $websiteTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Website', 'website_type_id');
1025
1026 $multipleFields = array('url');
1027
1028 //start of code to set the default values
1029 foreach ($fields as $name => $field) {
1030 // fix for CRM-3962
1031 if ($name == 'id') {
1032 $name = 'contact_id';
1033 }
1034
1035 // skip fields that should not be displayed separately
1036 if (!empty($field['skipDisplay'])) {
1037 continue;
1038 }
1039
1040 // Create a unique, non-empty index for each field.
1041 $index = $field['title'];
1042 if ($index === '') {
1043 $index = ' ';
1044 }
1045 while (array_key_exists($index, $values)) {
1046 $index .= ' ';
1047 }
1048
1049 $params[$index] = $values[$index] = '';
1050 $customFieldName = NULL;
1051 // hack for CRM-665
1052 if (isset($details->$name) || $name == 'group' || $name == 'tag') {
1053 // to handle gender / suffix / prefix
1054 if (in_array(substr($name, 0, -3), array('gender', 'prefix', 'suffix'))) {
1055 $params[$index] = $details->$name;
1056 $values[$index] = $details->$name;
1057 }
1058 elseif (in_array($name, CRM_Contact_BAO_Contact::$_greetingTypes)) {
1059 $dname = $name . '_display';
1060 $values[$index] = $details->$dname;
1061 $name = $name . '_id';
1062 $params[$index] = $details->$name;
1063 }
1064 elseif (in_array($name, array(
1065 'state_province',
1066 'country',
1067 'county',
1068 ))) {
1069 $values[$index] = $details->$name;
1070 $idx = $name . '_id';
1071 $params[$index] = $details->$idx;
1072 }
1073 elseif ($name === 'preferred_language') {
1074 $params[$index] = $details->$name;
1075 $values[$index] = CRM_Core_PseudoConstant::getLabel('CRM_Contact_DAO_Contact', 'preferred_language', $details->$name);
1076 }
1077 elseif ($name == 'group') {
1078 $groups = CRM_Contact_BAO_GroupContact::getContactGroup($cid, 'Added', NULL, FALSE, TRUE);
1079 $title = $ids = array();
1080
1081 foreach ($groups as $g) {
1082 // CRM-8362: User and User Admin visibility groups should be included in display if user has
1083 // VIEW permission on that group
1084 $groupPerm = CRM_Contact_BAO_Group::checkPermission($g['group_id'], TRUE);
1085
1086 if ($g['visibility'] != 'User and User Admin Only' ||
1087 CRM_Utils_Array::key(CRM_Core_Permission::VIEW, $groupPerm)
1088 ) {
1089 $title[] = $g['title'];
1090 if ($g['visibility'] == 'Public Pages') {
1091 $ids[] = $g['group_id'];
1092 }
1093 }
1094 }
1095 $values[$index] = implode(', ', $title);
1096 $params[$index] = implode(',', $ids);
1097 }
1098 elseif ($name == 'tag') {
1099 $entityTags = CRM_Core_BAO_EntityTag::getTag($cid);
1100 $allTags = CRM_Core_PseudoConstant::get('CRM_Core_DAO_EntityTag', 'tag_id', array('onlyActive' => FALSE));
1101 $title = array();
1102 foreach ($entityTags as $tagId) {
1103 $title[] = $allTags[$tagId];
1104 }
1105 $values[$index] = implode(', ', $title);
1106 $params[$index] = implode(',', $entityTags);
1107 }
1108 elseif ($name == 'activity_status_id') {
1109 $activityStatus = CRM_Core_PseudoConstant::activityStatus();
1110 $values[$index] = $activityStatus[$details->$name];
1111 $params[$index] = $details->$name;
1112 }
1113 elseif ($name == 'activity_date_time') {
1114 $values[$index] = CRM_Utils_Date::customFormat($details->$name);
1115 $params[$index] = $details->$name;
1116 }
1117 elseif ($name == 'contact_sub_type') {
1118 $contactSubTypeNames = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details->$name);
1119 if (!empty($contactSubTypeNames)) {
1120 $contactSubTypeLabels = array();
1121 // get all contact subtypes
1122 $allContactSubTypes = CRM_Contact_BAO_ContactType::subTypeInfo();
1123 // build contact subtype labels array
1124 foreach ($contactSubTypeNames as $cstName) {
1125 if ($cstName) {
1126 $contactSubTypeLabels[] = $allContactSubTypes[$cstName]['label'];
1127 }
1128 }
1129 $values[$index] = implode(',', $contactSubTypeLabels);
1130 }
1131
1132 $params[$index] = $details->$name;
1133 }
1134 else {
1135 if (substr($name, 0, 7) === 'do_not_' || substr($name, 0, 3) === 'is_') {
1136 if ($details->$name) {
1137 $values[$index] = '[ x ]';
1138 }
1139 }
1140 else {
1141 if ($cfID = CRM_Core_BAO_CustomField::getKeyID($name)) {
1142 $htmlType = $field['html_type'];
1143
1144 // field_type is only set when we are retrieving profile values
1145 // when sending email, we call the same function to get custom field
1146 // values etc, i.e. emulating a profile
1147 $fieldType = CRM_Utils_Array::value('field_type', $field);
1148
1149 if ($htmlType == 'File') {
1150 $entityId = $cid;
1151 if (!$cid &&
1152 $fieldType == 'Activity' && !empty($componentWhere[0][2])
1153 ) {
1154 $entityId = $componentWhere[0][2];
1155 }
1156
1157 $fileURL = CRM_Core_BAO_CustomField::getFileURL($entityId,
1158 $cfID,
1159 NULL,
1160 $absolute,
1161 $additionalWhereClause
1162 );
1163 $params[$index] = $values[$index] = $fileURL['file_url'];
1164 }
1165 else {
1166 $customVal = NULL;
1167 if (isset($dao) && property_exists($dao, 'data_type') &&
1168 ($dao->data_type == 'Int' ||
1169 $dao->data_type == 'Boolean'
1170 )
1171 ) {
1172 $customVal = (int ) ($details->{$name});
1173 }
1174 elseif (isset($dao) && property_exists($dao, 'data_type')
1175 && $dao->data_type == 'Float'
1176 ) {
1177 $customVal = (float ) ($details->{$name});
1178 }
1179 elseif (!CRM_Utils_System::isNull(explode(CRM_Core_DAO::VALUE_SEPARATOR,
1180 $details->{$name}
1181 ))
1182 ) {
1183 $customVal = $details->{$name};
1184 }
1185
1186 //CRM-4582
1187 if (CRM_Utils_System::isNull($customVal)) {
1188 continue;
1189 }
1190
1191 $params[$index] = $customVal;
1192 $values[$index] = CRM_Core_BAO_CustomField::displayValue($customVal, $cfID);
1193 if ($field['data_type'] == 'ContactReference') {
1194 $params[$index] = $values[$index];
1195 }
1196 if (CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField',
1197 $cfID, 'is_search_range'
1198 )
1199 ) {
1200 $customFieldName = "{$name}_from";
1201 }
1202 }
1203 }
1204 elseif ($name == 'image_URL') {
1205 list($width, $height) = getimagesize(CRM_Utils_String::unstupifyUrl($details->$name));
1206 list($thumbWidth, $thumbHeight) = CRM_Contact_BAO_Contact::getThumbSize($width, $height);
1207
1208 $image_URL = '<img src="' . $details->$name . '" height= ' . $thumbHeight . ' width= ' . $thumbWidth . ' />';
1209 $values[$index] = "<a href='#' onclick='contactImagePopUp(\"{$details->$name}\", {$width}, {$height});'>{$image_URL}</a>";
1210 }
1211 elseif (in_array($name, array(
1212 'birth_date',
1213 'deceased_date',
1214 ))) {
1215 // @todo this set should be determined from metadata, not hard-coded.
1216 $values[$index] = CRM_Utils_Date::customFormat($details->$name);
1217 $params[$index] = CRM_Utils_Date::isoToMysql($details->$name);
1218 }
1219 else {
1220 $dao = '';
1221 if ($index == 'Campaign') {
1222 $dao = 'CRM_Campaign_DAO_Campaign';
1223 }
1224 elseif ($index == 'Contribution Page') {
1225 $dao = 'CRM_Contribute_DAO_ContributionPage';
1226 }
1227 if ($dao) {
1228 $value = CRM_Core_DAO::getFieldValue($dao, $details->$name, 'title');
1229 }
1230 else {
1231 $value = $details->$name;
1232 }
1233 $values[$index] = $value;
1234 }
1235 }
1236 }
1237 }
1238 elseif (strpos($name, '-') !== FALSE) {
1239 list($fieldName, $id, $type) = CRM_Utils_System::explode('-', $name, 3);
1240
1241 if (!in_array($fieldName, $multipleFields)) {
1242 if ($id == 'Primary') {
1243 // fix for CRM-1543
1244 // not sure why we'd every use Primary location type id
1245 // we need to fix the source if we are using it
1246 // $locationTypeName = CRM_Contact_BAO_Contact::getPrimaryLocationType( $cid );
1247 $locationTypeName = 1;
1248 }
1249 else {
1250 $locationTypeName = CRM_Utils_Array::value($id, $locationTypes);
1251 }
1252
1253 if (!$locationTypeName) {
1254 continue;
1255 }
1256
1257 $detailName = "{$locationTypeName}-{$fieldName}";
1258 $detailName = str_replace(' ', '_', $detailName);
1259
1260 if (in_array($fieldName, array(
1261 'phone',
1262 'im',
1263 'email',
1264 'openid',
1265 ))) {
1266 if ($type) {
1267 $detailName .= "-{$type}";
1268 }
1269 }
1270
1271 if (in_array($fieldName, array(
1272 'state_province',
1273 'country',
1274 'county',
1275 ))) {
1276 $values[$index] = $details->$detailName;
1277 $idx = $detailName . '_id';
1278 $params[$index] = $details->$idx;
1279 }
1280 elseif ($fieldName == 'im') {
1281 $providerId = $detailName . '-provider_id';
1282 if (isset($imProviders[$details->$providerId])) {
1283 $values[$index] = $details->$detailName . " (" . $imProviders[$details->$providerId] . ")";
1284 }
1285 else {
1286 $values[$index] = $details->$detailName;
1287 }
1288 $params[$index] = $details->$detailName;
1289 }
1290 elseif ($fieldName == 'phone') {
1291 $phoneExtField = str_replace('phone', 'phone_ext', $detailName);
1292 if (isset($details->$phoneExtField)) {
1293 $values[$index] = $details->$detailName . " (" . $details->$phoneExtField . ")";
1294 }
1295 else {
1296 $values[$index] = $details->$detailName;
1297 }
1298 $params[$index] = $details->$detailName;
1299 }
1300 else {
1301 $values[$index] = $params[$index] = $details->$detailName;
1302 }
1303 }
1304 else {
1305 $detailName = "website-{$id}-{$fieldName}";
1306 $url = CRM_Utils_System::fixURL($details->$detailName);
1307 if ($details->$detailName) {
1308 $websiteTypeId = "website-{$id}-website_type_id";
1309 $websiteType = $websiteTypes[$details->$websiteTypeId];
1310 $values[$index] = "<a href=\"$url\">{$details->$detailName} ( {$websiteType} )</a>";
1311 }
1312 else {
1313 $values[$index] = '';
1314 }
1315 }
1316 }
1317
1318 if ((CRM_Utils_Array::value('visibility', $field) == 'Public Pages and Listings') &&
1319 CRM_Core_Permission::check('profile listings and forms')
1320 ) {
1321
1322 if (CRM_Utils_System::isNull($params[$index])) {
1323 $params[$index] = $values[$index];
1324 }
1325 if (!isset($params[$index])) {
1326 continue;
1327 }
1328 if (!$customFieldName) {
1329 $fieldName = $field['name'];
1330 }
1331 else {
1332 $fieldName = $customFieldName;
1333 }
1334
1335 $url = NULL;
1336 if (CRM_Core_BAO_CustomField::getKeyID($field['name'])) {
1337 $htmlType = $field['html_type'];
1338 if ($htmlType == 'Link') {
1339 $url = $params[$index];
1340 }
1341 elseif (in_array($htmlType, array(
1342 'CheckBox',
1343 'Multi-Select',
1344 'AdvMulti-Select',
1345 'Multi-Select State/Province',
1346 'Multi-Select Country',
1347 ))) {
1348 $valSeperator = CRM_Core_DAO::VALUE_SEPARATOR;
1349 $selectedOptions = explode($valSeperator, $params[$index]);
1350
1351 foreach ($selectedOptions as $key => $multiOption) {
1352 if ($multiOption) {
1353 $url[] = CRM_Utils_System::url('civicrm/profile',
1354 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1355 urlencode($fieldName) .
1356 '=' .
1357 urlencode($multiOption)
1358 );
1359 }
1360 }
1361 }
1362 else {
1363 $url = CRM_Utils_System::url('civicrm/profile',
1364 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1365 urlencode($fieldName) .
1366 '=' .
1367 urlencode($params[$index])
1368 );
1369 }
1370 }
1371 else {
1372 $url = CRM_Utils_System::url('civicrm/profile',
1373 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1374 urlencode($fieldName) .
1375 '=' .
1376 urlencode($params[$index])
1377 );
1378 }
1379
1380 if ($url &&
1381 !empty($values[$index]) &&
1382 $searchable
1383 ) {
1384
1385 if (is_array($url) && !empty($url)) {
1386 $links = array();
1387 $eachMultiValue = explode(', ', $values[$index]);
1388 foreach ($eachMultiValue as $key => $valueLabel) {
1389 $links[] = '<a href="' . $url[$key] . '">' . $valueLabel . '</a>';
1390 }
1391 $values[$index] = implode(', ', $links);
1392 }
1393 else {
1394 $values[$index] = '<a href="' . $url . '">' . $values[$index] . '</a>';
1395 }
1396 }
1397 }
1398 }
1399 }
1400
1401 /**
1402 * Check if profile Group used by any module.
1403 *
1404 * @param int $id
1405 * Profile Id.
1406 *
1407 * @return bool
1408 *
1409 */
1410 public static function usedByModule($id) {
1411 //check whether this group is used by any module(check uf join records)
1412 $sql = "SELECT id
1413 FROM civicrm_uf_join
1414 WHERE civicrm_uf_join.uf_group_id=$id";
1415
1416 $dao = new CRM_Core_DAO();
1417 $dao->query($sql);
1418 if ($dao->fetch()) {
1419 return TRUE;
1420 }
1421 else {
1422 return FALSE;
1423 }
1424 }
1425
1426 /**
1427 * Delete the profile Group.
1428 *
1429 * @param int $id
1430 * Profile Id.
1431 *
1432 * @return bool
1433 *
1434 */
1435 public static function del($id) {
1436 //check whether this group contains any profile fields
1437 $profileField = new CRM_Core_DAO_UFField();
1438 $profileField->uf_group_id = $id;
1439 $profileField->find();
1440 while ($profileField->fetch()) {
1441 CRM_Core_BAO_UFField::del($profileField->id);
1442 }
1443
1444 //delete records from uf join table
1445 $ufJoin = new CRM_Core_DAO_UFJoin();
1446 $ufJoin->uf_group_id = $id;
1447 $ufJoin->delete();
1448
1449 //delete profile group
1450 $group = new CRM_Core_DAO_UFGroup();
1451 $group->id = $id;
1452 $group->delete();
1453 return 1;
1454 }
1455
1456 /**
1457 * Add the UF Group.
1458 *
1459 * @param array $params
1460 * Reference array contains the values submitted by the form.
1461 * @param array $ids
1462 * Reference array contains the id.
1463 *
1464 *
1465 * @return object
1466 */
1467 public static function add(&$params, $ids = array()) {
1468 $fields = array(
1469 'is_active',
1470 'add_captcha',
1471 'is_map',
1472 'is_update_dupe',
1473 'is_edit_link',
1474 'is_uf_link',
1475 'is_cms_user',
1476 );
1477 foreach ($fields as $field) {
1478 $params[$field] = CRM_Utils_Array::value($field, $params, FALSE);
1479 }
1480
1481 $params['limit_listings_group_id'] = CRM_Utils_Array::value('group', $params);
1482 $params['add_to_group_id'] = CRM_Utils_Array::value('add_contact_to_group', $params);
1483
1484 //CRM-15427
1485 if (!empty($params['group_type']) && is_array($params['group_type'])) {
1486 $params['group_type'] = implode(',', $params['group_type']);
1487 }
1488 $ufGroup = new CRM_Core_DAO_UFGroup();
1489 $ufGroup->copyValues($params);
1490
1491 $ufGroupID = CRM_Utils_Array::value('ufgroup', $ids, CRM_Utils_Array::value('id', $params));
1492 if (!$ufGroupID && empty($params['name'])) {
1493 $ufGroup->name = CRM_Utils_String::munge($ufGroup->title, '_', 56);
1494 }
1495 $ufGroup->id = $ufGroupID;
1496
1497 $ufGroup->save();
1498
1499 if (!$ufGroupID && empty($params['name'])) {
1500 $ufGroup->name = $ufGroup->name . "_{$ufGroup->id}";
1501 $ufGroup->save();
1502 }
1503
1504 return $ufGroup;
1505 }
1506
1507 /**
1508 * Make uf join entries for an uf group.
1509 *
1510 * @param array $params
1511 * (reference) an assoc array of name/value pairs.
1512 * @param int $ufGroupId
1513 * Ufgroup id.
1514 */
1515 public static function createUFJoin(&$params, $ufGroupId) {
1516 $groupTypes = CRM_Utils_Array::value('uf_group_type', $params);
1517
1518 // get ufjoin records for uf group
1519 $ufGroupRecord = CRM_Core_BAO_UFGroup::getUFJoinRecord($ufGroupId);
1520
1521 // get the list of all ufgroup types
1522 $allUFGroupType = CRM_Core_SelectValues::ufGroupTypes();
1523
1524 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
1525 if (!is_array($groupTypes)) {
1526 $groupTypes = array();
1527 }
1528
1529 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
1530 if (!is_array($ufGroupRecord)) {
1531 $ufGroupRecord = array();
1532 }
1533
1534 // check which values has to be inserted/deleted for contact
1535 $menuRebuild = FALSE;
1536 foreach ($allUFGroupType as $key => $value) {
1537 $joinParams = array();
1538 $joinParams['uf_group_id'] = $ufGroupId;
1539 $joinParams['module'] = $key;
1540 if ($key == 'User Account') {
1541 $menuRebuild = TRUE;
1542 }
1543 if (array_key_exists($key, $groupTypes) && !in_array($key, $ufGroupRecord)) {
1544 // insert a new record
1545 CRM_Core_BAO_UFGroup::addUFJoin($joinParams);
1546 }
1547 elseif (!array_key_exists($key, $groupTypes) && in_array($key, $ufGroupRecord)) {
1548 // delete a record for existing ufgroup
1549 CRM_Core_BAO_UFGroup::delUFJoin($joinParams);
1550 }
1551 }
1552
1553 //update the weight
1554 $query = "
1555 UPDATE civicrm_uf_join
1556 SET weight = %1
1557 WHERE uf_group_id = %2
1558 AND ( entity_id IS NULL OR entity_id <= 0 )
1559 ";
1560 $p = array(
1561 1 => array($params['weight'], 'Integer'),
1562 2 => array($ufGroupId, 'Integer'),
1563 );
1564 CRM_Core_DAO::executeQuery($query, $p);
1565
1566 // do a menu rebuild if we are on drupal, so it gets all the new menu entries
1567 // for user account
1568 $config = CRM_Core_Config::singleton();
1569 if ($menuRebuild &&
1570 $config->userSystem->is_drupal
1571 ) {
1572 menu_rebuild();
1573 }
1574 }
1575
1576 /**
1577 * Get the UF Join records for an ufgroup id.
1578 *
1579 * @param int $ufGroupId
1580 * Uf group id.
1581 * @param int $displayName
1582 * If set return display name in array.
1583 * @param int $status
1584 * If set return module other than default modules (User Account/User registration/Profile).
1585 *
1586 * @return array
1587 *
1588 */
1589 public static function getUFJoinRecord($ufGroupId = NULL, $displayName = NULL, $status = NULL) {
1590 if ($displayName) {
1591 $UFGroupType = array();
1592 $UFGroupType = CRM_Core_SelectValues::ufGroupTypes();
1593 }
1594
1595 $ufJoin = array();
1596 $dao = new CRM_Core_DAO_UFJoin();
1597
1598 if ($ufGroupId) {
1599 $dao->uf_group_id = $ufGroupId;
1600 }
1601
1602 $dao->find();
1603 $ufJoin = array();
1604
1605 while ($dao->fetch()) {
1606 if (!$displayName) {
1607 $ufJoin[$dao->id] = $dao->module;
1608 }
1609 else {
1610 if (isset($UFGroupType[$dao->module])) {
1611 // skip the default modules
1612 if (!$status) {
1613 $ufJoin[$dao->id] = $UFGroupType[$dao->module];
1614 }
1615 // added for CRM-1475
1616 }
1617 elseif (!CRM_Utils_Array::key($dao->module, $ufJoin)) {
1618 $ufJoin[$dao->id] = $dao->module;
1619 }
1620 }
1621 }
1622 return $ufJoin;
1623 }
1624
1625 /**
1626 * Function takes an associative array and creates a ufjoin record for ufgroup.
1627 *
1628 * @param array $params
1629 * (reference) an assoc array of name/value pairs.
1630 *
1631 * @return CRM_Core_BAO_UFJoin
1632 */
1633 public static function addUFJoin(&$params) {
1634 $ufJoin = new CRM_Core_DAO_UFJoin();
1635 $ufJoin->copyValues($params);
1636 $ufJoin->save();
1637 return $ufJoin;
1638 }
1639
1640 /**
1641 * Delete the uf join record for an uf group.
1642 *
1643 * @param array $params
1644 * (reference) an assoc array of name/value pairs.
1645 */
1646 public static function delUFJoin(&$params) {
1647 $ufJoin = new CRM_Core_DAO_UFJoin();
1648 $ufJoin->copyValues($params);
1649 $ufJoin->delete();
1650 }
1651
1652 /**
1653 * Get the weight for ufjoin record.
1654 *
1655 * @param int $ufGroupId
1656 * If $ufGroupId get update weight or add weight.
1657 *
1658 * @return int
1659 * weight of the UFGroup
1660 */
1661 public static function getWeight($ufGroupId = NULL) {
1662 //calculate the weight
1663 $p = array();
1664 if (!$ufGroupId) {
1665 $queryString = "SELECT ( MAX(civicrm_uf_join.weight)+1) as new_weight
1666 FROM civicrm_uf_join
1667 WHERE module = 'User Registration' OR module = 'User Account' OR module = 'Profile'";
1668 }
1669 else {
1670 $queryString = "SELECT MAX(civicrm_uf_join.weight) as new_weight
1671 FROM civicrm_uf_join
1672 WHERE civicrm_uf_join.uf_group_id = %1
1673 AND ( entity_id IS NULL OR entity_id <= 0 )";
1674 $p[1] = array($ufGroupId, 'Integer');
1675 }
1676
1677 $dao = CRM_Core_DAO::executeQuery($queryString, $p);
1678 $dao->fetch();
1679 return ($dao->new_weight) ? $dao->new_weight : 1;
1680 }
1681
1682 /**
1683 * Get the uf group for a module.
1684 *
1685 * @param string $moduleName
1686 * Module name.
1687 * @param int $count
1688 * No to increment the weight.
1689 * @param bool $skipPermission
1690 * @param int $op
1691 * Which operation (view, edit, create, etc) to check permission for.
1692 * @param array|NULL $returnFields list of UFGroup fields to return; NULL for default
1693 *
1694 * @return array
1695 * array of ufgroups for a module
1696 */
1697 public static function getModuleUFGroup($moduleName = NULL, $count = 0, $skipPermission = TRUE, $op = CRM_Core_Permission::VIEW, $returnFields = NULL) {
1698 $selectFields = array('id', 'title', 'created_id', 'is_active', 'is_reserved', 'group_type');
1699
1700 if (!CRM_Core_Config::isUpgradeMode()) {
1701 // CRM-13555, since description field was added later (4.4), and to avoid any problems with upgrade
1702 $selectFields[] = 'description';
1703 }
1704
1705 if (!empty($returnFields)) {
1706 $selectFields = array_merge($returnFields, array_diff($selectFields, $returnFields));
1707 }
1708
1709 $queryString = 'SELECT civicrm_uf_group.' . implode(', civicrm_uf_group.', $selectFields) . '
1710 FROM civicrm_uf_group
1711 LEFT JOIN civicrm_uf_join ON (civicrm_uf_group.id = uf_group_id)';
1712 $p = array();
1713 if ($moduleName) {
1714 $queryString .= ' AND civicrm_uf_group.is_active = 1
1715 WHERE civicrm_uf_join.module = %2';
1716 $p[2] = array($moduleName, 'String');
1717 }
1718
1719 // add permissioning for profiles only if not registration
1720 if (!$skipPermission) {
1721 $permissionClause = CRM_Core_Permission::ufGroupClause($op, 'civicrm_uf_group.');
1722 if (strpos($queryString, 'WHERE') !== FALSE) {
1723 $queryString .= " AND $permissionClause ";
1724 }
1725 else {
1726 $queryString .= " $permissionClause ";
1727 }
1728 }
1729
1730 $queryString .= ' ORDER BY civicrm_uf_join.weight, civicrm_uf_group.title';
1731 $dao = CRM_Core_DAO::executeQuery($queryString, $p);
1732
1733 $ufGroups = array();
1734 while ($dao->fetch()) {
1735 //skip mix profiles in user Registration / User Account
1736 if (($moduleName == 'User Registration' || $moduleName == 'User Account') &&
1737 CRM_Core_BAO_UFField::checkProfileType($dao->id)
1738 ) {
1739 continue;
1740 }
1741 foreach ($selectFields as $key => $field) {
1742 if ($field == 'id') {
1743 continue;
1744 }
1745 $ufGroups[$dao->id][$field] = $dao->$field;
1746 }
1747 }
1748
1749 // Allow other modules to alter/override the UFGroups.
1750 CRM_Utils_Hook::buildUFGroupsForModule($moduleName, $ufGroups);
1751
1752 return $ufGroups;
1753 }
1754
1755 /**
1756 * Filter ufgroups based on logged in user contact type.
1757 *
1758 * @param int $ufGroupId
1759 * Uf group id (profile id).
1760 * @param int $contactID
1761 *
1762 * @return bool
1763 * true or false
1764 */
1765 public static function filterUFGroups($ufGroupId, $contactID = NULL) {
1766 if (!$contactID) {
1767 $session = CRM_Core_Session::singleton();
1768 $contactID = $session->get('userID');
1769 }
1770
1771 if ($contactID) {
1772 //get the contact type
1773 $contactType = CRM_Contact_BAO_Contact::getContactType($contactID);
1774
1775 //match if exixting contact type is same as profile contact type
1776 $profileType = CRM_Core_BAO_UFField::getProfileType($ufGroupId);
1777
1778 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
1779 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
1780 }
1781
1782 //allow special mix profiles for Contribution and Participant
1783 $specialProfiles = array('Contribution', 'Participant', 'Membership');
1784
1785 if (in_array($profileType, $specialProfiles)) {
1786 return TRUE;
1787 }
1788
1789 if (($contactType == $profileType) || $profileType == 'Contact') {
1790 return TRUE;
1791 }
1792 }
1793
1794 return FALSE;
1795 }
1796
1797 /**
1798 * Add profile field to a form.
1799 *
1800 * @param CRM_Core_Form $form
1801 * @param array $field
1802 * Properties.
1803 * @param int $mode
1804 * Profile mode.
1805 * @param int $contactId
1806 * @param bool $online
1807 * @param string $usedFor
1808 * For building up prefixed fieldname for special cases (e.g. onBehalf, Honor).
1809 * @param int $rowNumber
1810 * @param string $prefix
1811 *
1812 * @return null
1813 */
1814 public static function buildProfile(
1815 &$form,
1816 &$field,
1817 $mode,
1818 $contactId = NULL,
1819 $online = FALSE,
1820 $usedFor = NULL,
1821 $rowNumber = NULL,
1822 $prefix = ''
1823 ) {
1824 $defaultValues = array();
1825 $fieldName = $field['name'];
1826 $title = $field['title'];
1827 $attributes = $field['attributes'];
1828 $rule = $field['rule'];
1829 $view = $field['is_view'];
1830 $required = ($mode == CRM_Profile_Form::MODE_SEARCH) ? FALSE : $field['is_required'];
1831 $search = ($mode == CRM_Profile_Form::MODE_SEARCH) ? TRUE : FALSE;
1832 $isShared = CRM_Utils_Array::value('is_shared', $field, 0);
1833
1834 // do not display view fields in drupal registration form
1835 // CRM-4632
1836 if ($view && $mode == CRM_Profile_Form::MODE_REGISTER) {
1837 return NULL;
1838 }
1839
1840 if ($usedFor == 'onbehalf') {
1841 $name = "onbehalf[$fieldName]";
1842 }
1843 elseif ($usedFor == 'honor') {
1844 $name = "honor[$fieldName]";
1845 }
1846 elseif ($contactId && !$online) {
1847 $name = "field[$contactId][$fieldName]";
1848 }
1849 elseif ($rowNumber) {
1850 $name = "field[$rowNumber][$fieldName]";
1851 }
1852 elseif (!empty($prefix)) {
1853 $name = $prefix . "[$fieldName]";
1854 }
1855 else {
1856 $name = $fieldName;
1857 }
1858
1859 $selectAttributes = array('class' => 'crm-select2', 'placeholder' => TRUE);
1860
1861 if ($fieldName == 'image_URL' && $mode == CRM_Profile_Form::MODE_EDIT) {
1862 $deleteExtra = json_encode(ts('Are you sure you want to delete contact image.'));
1863 $deleteURL = array(
1864 CRM_Core_Action::DELETE => array(
1865 'name' => ts('Delete Contact Image'),
1866 'url' => 'civicrm/contact/image',
1867 'qs' => 'reset=1&id=%%id%%&gid=%%gid%%&action=delete',
1868 'extra' => 'onclick = "' . htmlspecialchars("if (confirm($deleteExtra)) this.href+='&confirmed=1'; else return false;") . '"',
1869 ),
1870 );
1871 $deleteURL = CRM_Core_Action::formLink($deleteURL,
1872 CRM_Core_Action::DELETE,
1873 array(
1874 'id' => $form->get('id'),
1875 'gid' => $form->get('gid'),
1876 ),
1877 ts('more'),
1878 FALSE,
1879 'contact.profileimage.delete',
1880 'Contact',
1881 $form->get('id')
1882 );
1883 $form->assign('deleteURL', $deleteURL);
1884 }
1885 $addressOptions = CRM_Core_BAO_Setting::valueOptions(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
1886 'address_options', TRUE, NULL, TRUE
1887 );
1888
1889 if (substr($fieldName, 0, 14) === 'state_province') {
1890 $form->addChainSelect($name, array('label' => $title, 'required' => $required));
1891 $config = CRM_Core_Config::singleton();
1892 if (!in_array($mode, array(
1893 CRM_Profile_Form::MODE_EDIT,
1894 CRM_Profile_Form::MODE_SEARCH,
1895 )) &&
1896 $config->defaultContactStateProvince
1897 ) {
1898 $defaultValues[$name] = $config->defaultContactStateProvince;
1899 $form->setDefaults($defaultValues);
1900 }
1901 }
1902 elseif (substr($fieldName, 0, 7) === 'country') {
1903 $form->add('select', $name, $title, array('' => ts('- select -')) + CRM_Core_PseudoConstant::country(), $required, $selectAttributes);
1904 $config = CRM_Core_Config::singleton();
1905 if (!in_array($mode, array(
1906 CRM_Profile_Form::MODE_EDIT,
1907 CRM_Profile_Form::MODE_SEARCH,
1908 )) &&
1909 $config->defaultContactCountry
1910 ) {
1911 $defaultValues[$name] = $config->defaultContactCountry;
1912 $form->setDefaults($defaultValues);
1913 }
1914 }
1915 elseif (substr($fieldName, 0, 6) === 'county') {
1916 if ($addressOptions['county']) {
1917 $form->addChainSelect($name, array('label' => $title, 'required' => $required));
1918 }
1919 }
1920 elseif (substr($fieldName, 0, 9) === 'image_URL') {
1921 $form->add('file', $name, $title, $attributes, $required);
1922 $form->addUploadElement($name);
1923 }
1924 elseif (substr($fieldName, 0, 2) === 'im') {
1925 $form->add('text', $name, $title, $attributes, $required);
1926 if (!$contactId) {
1927 if ($usedFor) {
1928 if (substr($name, -1) == ']') {
1929 $providerName = substr($name, 0, -1) . '-provider_id]';
1930 }
1931 $form->add('select', $providerName, NULL,
1932 array(
1933 '' => ts('- select -'),
1934 ) + CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id'), $required
1935 );
1936 }
1937 else {
1938 $form->add('select', $name . '-provider_id', $title,
1939 array(
1940 '' => ts('- select -'),
1941 ) + CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id'), $required
1942 );
1943 }
1944
1945 if ($view && $mode != CRM_Profile_Form::MODE_SEARCH) {
1946 $form->freeze($name . '-provider_id');
1947 }
1948 }
1949 }
1950 elseif (CRM_Utils_Array::value('name', $field) == 'membership_type') {
1951 list($orgInfo, $types) = CRM_Member_BAO_MembershipType::getMembershipTypeInfo();
1952 $sel = &$form->addElement('hierselect', $name, $title);
1953 $select = array('' => ts('- select -'));
1954 if (count($orgInfo) == 1 && $field['is_required']) {
1955 // we only have one org - so we should default to it. Not sure about defaulting to first type
1956 // as it could be missed - so adding a select
1957 // however, possibly that is more similar to the membership form
1958 if (count($types[1]) > 1) {
1959 $types[1] = $select + $types[1];
1960 }
1961 }
1962 else {
1963 $orgInfo = $select + $orgInfo;
1964 }
1965 $sel->setOptions(array($orgInfo, $types));
1966 }
1967 elseif (CRM_Utils_Array::value('name', $field) == 'membership_status') {
1968 $form->add('select', $name, $title,
1969 array(
1970 '' => ts('- select -'),
1971 ) + CRM_Member_PseudoConstant::membershipStatus(NULL, NULL, 'label'), $required
1972 );
1973 }
1974 elseif (in_array($fieldName, array('gender_id', 'communication_style_id'))) {
1975 $options = array();
1976 $pseudoValues = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', $fieldName);
1977 foreach ($pseudoValues as $key => $var) {
1978 $options[$key] = $form->createElement('radio', NULL, ts($title), $var, $key);
1979 }
1980 $group = $form->addGroup($options, $name, $title);
1981 if ($required) {
1982 $form->addRule($name, ts('%1 is a required field.', array(1 => $title)), 'required');
1983 }
1984 else {
1985 $group->setAttribute('allowClear', TRUE);
1986 }
1987 }
1988 elseif ($fieldName === 'prefix_id' || $fieldName === 'suffix_id') {
1989 $form->addSelect($name, array(
1990 'label' => $title,
1991 'entity' => 'contact',
1992 'field' => $fieldName,
1993 'class' => 'six',
1994 'placeholder' => '',
1995 ), $required);
1996 }
1997 elseif ($fieldName === 'contact_sub_type') {
1998 $gId = $form->get('gid') ? $form->get('gid') : CRM_Utils_Array::value('group_id', $field);
1999 if ($usedFor == 'onbehalf') {
2000 $profileType = 'Organization';
2001 }
2002 elseif ($usedFor == 'honor') {
2003 $profileType = CRM_Core_BAO_UFField::getProfileType($form->_params['honoree_profile_id']);
2004 }
2005 else {
2006 $profileType = $gId ? CRM_Core_BAO_UFField::getProfileType($gId) : NULL;
2007 if ($profileType == 'Contact') {
2008 $profileType = 'Individual';
2009 }
2010 }
2011
2012 $setSubtype = FALSE;
2013 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
2014 $setSubtype = $profileType;
2015 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
2016 }
2017
2018 $subtypes = $profileType ? CRM_Contact_BAO_ContactType::subTypePairs($profileType) : array();
2019
2020 if ($setSubtype) {
2021 $subtypeList = array();
2022 $subtypeList[$setSubtype] = $subtypes[$setSubtype];
2023 }
2024 else {
2025 $subtypeList = $subtypes;
2026 }
2027
2028 $form->add('select', $name, $title, $subtypeList, $required, array('class' => 'crm-select2', 'multiple' => TRUE));
2029 }
2030 elseif (in_array($fieldName, CRM_Contact_BAO_Contact::$_greetingTypes)) {
2031 //add email greeting, postal greeting, addressee, CRM-4575
2032 $gId = $form->get('gid') ? $form->get('gid') : CRM_Utils_Array::value('group_id', $field);
2033 $profileType = CRM_Core_BAO_UFField::getProfileType($gId, TRUE, FALSE, TRUE);
2034
2035 if (empty($profileType) || in_array($profileType, array(
2036 'Contact',
2037 'Contribution',
2038 'Participant',
2039 'Membership',
2040 ))
2041 ) {
2042 $profileType = 'Individual';
2043 }
2044 if (CRM_Contact_BAO_ContactType::isaSubType($profileType)) {
2045 $profileType = CRM_Contact_BAO_ContactType::getBasicType($profileType);
2046 }
2047 $greeting = array(
2048 'contact_type' => $profileType,
2049 'greeting_type' => $fieldName,
2050 );
2051 $form->add('select', $name, $title,
2052 array(
2053 '' => ts('- select -'),
2054 ) + CRM_Core_PseudoConstant::greeting($greeting), $required
2055 );
2056 // add custom greeting element
2057 $form->add('text', $fieldName . '_custom', ts('Custom %1', array(1 => ucwords(str_replace('_', ' ', $fieldName)))),
2058 NULL, FALSE
2059 );
2060 }
2061 elseif ($fieldName === 'preferred_communication_method') {
2062 $communicationFields = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'preferred_communication_method');
2063 foreach ($communicationFields as $key => $var) {
2064 if ($key == '') {
2065 continue;
2066 }
2067 $communicationOptions[] = $form->createElement('checkbox', $key, NULL, $var);
2068 }
2069 $form->addGroup($communicationOptions, $name, $title, '<br/>');
2070 }
2071 elseif ($fieldName === 'preferred_mail_format') {
2072 $form->add('select', $name, $title, CRM_Core_SelectValues::pmf());
2073 }
2074 elseif ($fieldName === 'preferred_language') {
2075 $form->add('select', $name, $title, array('' => ts('- select -')) + CRM_Contact_BAO_Contact::buildOptions('preferred_language'));
2076 }
2077 elseif ($fieldName == 'external_identifier') {
2078 $form->add('text', $name, $title, $attributes, $required);
2079 $contID = $contactId;
2080 if (!$contID) {
2081 $contID = $form->get('id');
2082 }
2083 $form->addRule($name,
2084 ts('External ID already exists in Database.'),
2085 'objectExists',
2086 array('CRM_Contact_DAO_Contact', $contID, 'external_identifier')
2087 );
2088 }
2089 elseif ($fieldName === 'group') {
2090 CRM_Contact_Form_Edit_TagsAndGroups::buildQuickForm($form, $contactId,
2091 CRM_Contact_Form_Edit_TagsAndGroups::GROUP,
2092 TRUE, $required,
2093 $title, NULL, $name
2094 );
2095 }
2096 elseif ($fieldName === 'tag') {
2097 CRM_Contact_Form_Edit_TagsAndGroups::buildQuickForm($form, $contactId,
2098 CRM_Contact_Form_Edit_TagsAndGroups::TAG,
2099 FALSE, $required,
2100 NULL, $title, $name
2101 );
2102 }
2103 elseif (substr($fieldName, 0, 4) === 'url-') {
2104 $form->add('text', $name, $title, CRM_Core_DAO::getAttribute('CRM_Core_DAO_Website', 'url'), $required);
2105 $form->addRule($name, ts('Enter a valid web address beginning with \'http://\' or \'https://\'.'), 'url');
2106 }
2107 // Note should be rendered as textarea
2108 elseif (substr($fieldName, -4) == 'note') {
2109 $form->add('textarea', $name, $title, $attributes, $required);
2110 }
2111 elseif (substr($fieldName, 0, 6) === 'custom') {
2112 $customFieldID = CRM_Core_BAO_CustomField::getKeyID($fieldName);
2113 if ($customFieldID) {
2114 CRM_Core_BAO_CustomField::addQuickFormElement($form, $name, $customFieldID, $required, $search, $title);
2115 }
2116 }
2117 elseif (substr($fieldName, 0, 14) === 'address_custom') {
2118 list($fName, $locTypeId) = CRM_Utils_System::explode('-', $fieldName, 2);
2119 $customFieldID = CRM_Core_BAO_CustomField::getKeyID(substr($fName, 8));
2120 if ($customFieldID) {
2121 CRM_Core_BAO_CustomField::addQuickFormElement($form, $name, $customFieldID, $required, $search, $title);
2122 }
2123 }
2124 elseif ($fieldName == 'send_receipt') {
2125 $form->addElement('checkbox', $name, $title);
2126 }
2127 elseif ($fieldName == 'soft_credit') {
2128 $form->addEntityRef("soft_credit_contact_id[$rowNumber]", ts('Soft Credit To'), array('create' => TRUE));
2129 $form->addMoney("soft_credit_amount[{$rowNumber}]", ts('Amount'), FALSE, NULL, FALSE);
2130 }
2131 elseif ($fieldName == 'product_name') {
2132 list($products, $options) = CRM_Contribute_BAO_Premium::getPremiumProductInfo();
2133 $sel = &$form->addElement('hierselect', $name, $title);
2134 $products = array(
2135 '0' => ts('- select -'),
2136 ) + $products;
2137 $sel->setOptions(array($products, $options));
2138 }
2139 elseif ($fieldName == 'payment_instrument') {
2140 $form->add('select', $name, $title,
2141 array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::paymentInstrument(), $required);
2142 }
2143 elseif ($fieldName == 'financial_type') {
2144 $form->add('select', $name, $title,
2145 array(
2146 '' => ts('- select -'),
2147 ) + CRM_Contribute_PseudoConstant::financialType(), $required
2148 );
2149 }
2150 elseif ($fieldName == 'contribution_status_id') {
2151 $contributionStatuses = CRM_Contribute_PseudoConstant::contributionStatus();
2152 $statusName = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
2153 foreach (array(
2154 'In Progress',
2155 'Overdue',
2156 'Refunded',
2157 ) as $suppress) {
2158 unset($contributionStatuses[CRM_Utils_Array::key($suppress, $statusName)]);
2159 }
2160
2161 $form->add('select', $name, $title,
2162 array(
2163 '' => ts('- select -'),
2164 ) + $contributionStatuses, $required
2165 );
2166 }
2167 elseif ($fieldName == 'soft_credit_type') {
2168 $name = "soft_credit_type[$rowNumber]";
2169 $form->add('select', $name, $title,
2170 array(
2171 '' => ts('- select -'),
2172 ) + CRM_Core_OptionGroup::values("soft_credit_type")
2173 );
2174 //CRM-15350: choose SCT field default value as 'Gift' for membership use
2175 //else (for contribution), use configured SCT default value
2176 $SCTDefaultValue = CRM_Core_OptionGroup::getDefaultValue("soft_credit_type");
2177 if ($field['field_type'] == 'Membership') {
2178 $SCTDefaultValue = CRM_Core_OptionGroup::getValue('soft_credit_type', 'Gift', 'name');
2179 }
2180 $form->addElement('hidden', 'sct_default_id', $SCTDefaultValue, array('id' => 'sct_default_id'));
2181 }
2182 elseif ($fieldName == 'contribution_soft_credit_pcp_id') {
2183 CRM_Contribute_Form_SoftCredit::addPCPFields($form, "[$rowNumber]");
2184 }
2185 elseif ($fieldName == 'currency') {
2186 $form->addCurrency($name, $title, $required);
2187 }
2188 elseif ($fieldName == 'contribution_page_id') {
2189 $form->add('select', $name, $title,
2190 array(
2191 '' => ts('- select -'),
2192 ) + CRM_Contribute_PseudoConstant::contributionPage(), $required, 'class="big"'
2193 );
2194 }
2195 elseif ($fieldName == 'activity_status_id') {
2196 $form->add('select', $name, $title,
2197 array(
2198 '' => ts('- select -'),
2199 ) + CRM_Core_PseudoConstant::activityStatus(), $required
2200 );
2201 }
2202 elseif ($fieldName == 'activity_engagement_level') {
2203 $form->add('select', $name, $title,
2204 array(
2205 '' => ts('- select -'),
2206 ) + CRM_Campaign_PseudoConstant::engagementLevel(), $required
2207 );
2208 }
2209 elseif ($fieldName == 'participant_status') {
2210 $cond = NULL;
2211 if ($online == TRUE) {
2212 $cond = 'visibility_id = 1';
2213 }
2214 $form->add('select', $name, $title,
2215 array(
2216 '' => ts('- select -'),
2217 ) + CRM_Event_PseudoConstant::participantStatus(NULL, $cond, 'label'), $required
2218 );
2219 }
2220 elseif ($fieldName == 'participant_role') {
2221 if (!empty($field['is_multiple'])) {
2222 $form->addCheckBox($name, $title, CRM_Event_PseudoConstant::participantRole(), NULL, NULL, NULL, NULL, '&nbsp', TRUE);
2223 }
2224 else {
2225 $form->add('select', $name, $title,
2226 array(
2227 '' => ts('- select -'),
2228 ) + CRM_Event_PseudoConstant::participantRole(), $required
2229 );
2230 }
2231 }
2232 elseif ($fieldName == 'world_region') {
2233 $form->add('select', $name, $title, CRM_Core_PseudoConstant::worldRegion(), $required, $selectAttributes);
2234 }
2235 elseif ($fieldName == 'signature_html') {
2236 $form->add('wysiwyg', $name, $title, CRM_Core_DAO::getAttribute('CRM_Core_DAO_Email', $fieldName));
2237 }
2238 elseif ($fieldName == 'signature_text') {
2239 $form->add('textarea', $name, $title, CRM_Core_DAO::getAttribute('CRM_Core_DAO_Email', $fieldName));
2240 }
2241 elseif (substr($fieldName, -11) == 'campaign_id') {
2242 if (CRM_Campaign_BAO_Campaign::isCampaignEnable()) {
2243 $campaigns = CRM_Campaign_BAO_Campaign::getCampaigns(CRM_Utils_Array::value($contactId,
2244 $form->_componentCampaigns
2245 ));
2246 $form->add('select', $name, $title,
2247 array(
2248 '' => ts('- select -'),
2249 ) + $campaigns, $required, 'class="crm-select2 big"'
2250 );
2251 }
2252 }
2253 elseif ($fieldName == 'activity_details') {
2254 $form->add('wysiwyg', $fieldName, $title, array('rows' => 4, 'cols' => 60), $required);
2255 }
2256 elseif ($fieldName == 'activity_duration') {
2257 $form->add('text', $name, $title, $attributes, $required);
2258 $form->addRule($name, ts('Please enter the duration as number of minutes (integers only).'), 'positiveInteger');
2259 }
2260 else {
2261 if (substr($fieldName, 0, 3) === 'is_' or substr($fieldName, 0, 7) === 'do_not_') {
2262 $form->add('advcheckbox', $name, $title, $attributes, $required);
2263 }
2264 elseif (CRM_Utils_Array::value('html_type', $field) === 'Select Date') {
2265 $extra = isset($field['datepicker']) ? $field['datepicker']['extra'] : CRM_Utils_Date::getDatePickerExtra($field);
2266 $attributes = isset($field['datepicker']) ? $field['datepicker']['attributes'] : CRM_Utils_Date::getDatePickerAttributes($field);
2267 $form->add('datepicker', $name, $title, $attributes, $required, $extra);
2268 }
2269 else {
2270 $form->add('text', $name, $title, $attributes, $required);
2271 }
2272 }
2273
2274 static $hiddenSubtype = FALSE;
2275 if (!$hiddenSubtype && CRM_Contact_BAO_ContactType::isaSubType($field['field_type'])) {
2276 // In registration mode params are submitted via POST and we don't have any clue
2277 // about profile-id or the profile-type (which could be a subtype)
2278 // To generalize the behavior and simplify the process,
2279 // lets always add the hidden
2280 //subtype value if there is any, and we won't have to
2281 // compute it while processing.
2282 if ($usedFor) {
2283 $form->addElement('hidden', $usedFor . '[contact_sub_type]', $field['field_type']);
2284 }
2285 else {
2286 $form->addElement('hidden', 'contact_sub_type_hidden', $field['field_type']);
2287 }
2288 $hiddenSubtype = TRUE;
2289 }
2290
2291 if (($view && $mode != CRM_Profile_Form::MODE_SEARCH) || $isShared) {
2292 $form->freeze($name);
2293 }
2294
2295 //add the rules
2296 if (in_array($fieldName, array(
2297 'non_deductible_amount',
2298 'total_amount',
2299 'fee_amount',
2300 'net_amount',
2301 ))) {
2302 $form->addRule($name, ts('Please enter a valid amount.'), 'money');
2303 }
2304 if ($rule) {
2305 if (!($rule == 'email' && $mode == CRM_Profile_Form::MODE_SEARCH)) {
2306 $form->addRule($name, ts('Please enter a valid %1', array(1 => $title)), $rule);
2307 }
2308 }
2309 }
2310
2311 /**
2312 * Set profile defaults.
2313 *
2314 * @param int $contactId
2315 * Contact id.
2316 * @param array $fields
2317 * Associative array of fields.
2318 * @param array $defaults
2319 * Defaults array.
2320 * @param bool $singleProfile
2321 * True for single profile else false(Update multiple items).
2322 * @param int $componentId
2323 * Id for specific components like contribute, event etc.
2324 * @param null $component
2325 */
2326 public static function setProfileDefaults(
2327 $contactId, &$fields, &$defaults,
2328 $singleProfile = TRUE, $componentId = NULL, $component = NULL
2329 ) {
2330 if (!$componentId) {
2331 //get the contact details
2332 list($contactDetails, $options) = CRM_Contact_BAO_Contact::getHierContactDetails($contactId, $fields);
2333 $details = CRM_Utils_Array::value($contactId, $contactDetails);
2334 $multipleFields = array('website' => 'url');
2335
2336 //start of code to set the default values
2337 foreach ($fields as $name => $field) {
2338 // skip pseudo fields
2339 if (substr($name, 0, 9) == 'phone_ext') {
2340 continue;
2341 }
2342
2343 //set the field name depending upon the profile mode(single/multiple)
2344 if ($singleProfile) {
2345 $fldName = $name;
2346 }
2347 else {
2348 $fldName = "field[$contactId][$name]";
2349 }
2350
2351 if ($name == 'group') {
2352 CRM_Contact_Form_Edit_TagsAndGroups::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups::GROUP, $fldName);
2353 }
2354 if ($name == 'tag') {
2355 CRM_Contact_Form_Edit_TagsAndGroups::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups::TAG, $fldName);
2356 }
2357
2358 if (!empty($details[$name]) || isset($details[$name])) {
2359 //to handle custom data (checkbox) to be written
2360 // to handle birth/deceased date, greeting_type and few other fields
2361 if (in_array($name, CRM_Contact_BAO_Contact::$_greetingTypes)) {
2362 $defaults[$fldName] = $details[$name . '_id'];
2363 $defaults[$name . '_custom'] = $details[$name . '_custom'];
2364 }
2365 elseif ($name == 'preferred_communication_method') {
2366 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details[$name]);
2367 foreach ($v as $item) {
2368 if ($item) {
2369 $defaults[$fldName . "[$item]"] = 1;
2370 }
2371 }
2372 }
2373 elseif ($name == 'contact_sub_type') {
2374 $defaults[$fldName] = explode(CRM_Core_DAO::VALUE_SEPARATOR, trim($details[$name], CRM_Core_DAO::VALUE_SEPARATOR));
2375 }
2376 elseif ($name == 'world_region') {
2377 $defaults[$fldName] = $details['worldregion_id'];
2378 }
2379 elseif ($customFieldId = CRM_Core_BAO_CustomField::getKeyID($name)) {
2380 // @todo retrieving the custom fields here seems obsolete - $field holds more data for the fields.
2381 $customFields = CRM_Core_BAO_CustomField::getFields(CRM_Utils_Array::value('contact_type', $details));
2382
2383 // hack to add custom data for components
2384 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
2385 foreach ($components as $value) {
2386 $customFields = CRM_Utils_Array::crmArrayMerge($customFields,
2387 CRM_Core_BAO_CustomField::getFieldsForImport($value)
2388 );
2389 }
2390
2391 switch ($customFields[$customFieldId]['html_type']) {
2392 case 'Multi-Select State/Province':
2393 case 'Multi-Select Country':
2394 case 'AdvMulti-Select':
2395 case 'Multi-Select':
2396 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details[$name]);
2397 foreach ($v as $item) {
2398 if ($item) {
2399 $defaults[$fldName][$item] = $item;
2400 }
2401 }
2402 break;
2403
2404 case 'CheckBox':
2405 $v = explode(CRM_Core_DAO::VALUE_SEPARATOR, $details[$name]);
2406 foreach ($v as $item) {
2407 if ($item) {
2408 $defaults[$fldName][$item] = 1;
2409 // seems like we need this for QF style checkboxes in profile where its multiindexed
2410 // CRM-2969
2411 $defaults["{$fldName}[{$item}]"] = 1;
2412 }
2413 }
2414 break;
2415
2416 default:
2417 $defaults[$fldName] = $details[$name];
2418 break;
2419 }
2420 }
2421 else {
2422 $defaults[$fldName] = $details[$name];
2423 }
2424 }
2425 else {
2426 $blocks = array('email', 'phone', 'im', 'openid');
2427 list($fieldName, $locTypeId, $phoneTypeId) = CRM_Utils_System::explode('-', $name, 3);
2428 if (!in_array($fieldName, $multipleFields)) {
2429 if (is_array($details)) {
2430 foreach ($details as $key => $value) {
2431 // when we fixed CRM-5319 - get primary loc
2432 // type as per loc field and removed below code.
2433 $primaryLocationType = FALSE;
2434 if ($locTypeId == 'Primary') {
2435 if (is_array($value) && array_key_exists($fieldName, $value)) {
2436 $primaryLocationType = TRUE;
2437 if (in_array($fieldName, $blocks)) {
2438 $locTypeId = CRM_Contact_BAO_Contact::getPrimaryLocationType($contactId, FALSE, $fieldName);
2439 }
2440 else {
2441 $locTypeId = CRM_Contact_BAO_Contact::getPrimaryLocationType($contactId, FALSE, 'address');
2442 }
2443 }
2444 }
2445
2446 // fixed for CRM-665
2447 if (is_numeric($locTypeId)) {
2448 if ($primaryLocationType || $locTypeId == CRM_Utils_Array::value('location_type_id', $value)) {
2449 if (!empty($value[$fieldName])) {
2450 //to handle stateprovince and country
2451 if ($fieldName == 'state_province') {
2452 $defaults[$fldName] = $value['state_province_id'];
2453 }
2454 elseif ($fieldName == 'county') {
2455 $defaults[$fldName] = $value['county_id'];
2456 }
2457 elseif ($fieldName == 'country') {
2458 if (!isset($value['country_id']) || !$value['country_id']) {
2459 $config = CRM_Core_Config::singleton();
2460 if ($config->defaultContactCountry) {
2461 $defaults[$fldName] = $config->defaultContactCountry;
2462 }
2463 }
2464 else {
2465 $defaults[$fldName] = $value['country_id'];
2466 }
2467 }
2468 elseif ($fieldName == 'phone') {
2469 if ($phoneTypeId) {
2470 if (isset($value['phone'][$phoneTypeId])) {
2471 $defaults[$fldName] = $value['phone'][$phoneTypeId];
2472 }
2473 if (isset($value['phone_ext'][$phoneTypeId])) {
2474 $defaults[str_replace('phone', 'phone_ext', $fldName)] = $value['phone_ext'][$phoneTypeId];
2475 }
2476 }
2477 else {
2478 $phoneDefault = CRM_Utils_Array::value('phone', $value);
2479 // CRM-9216
2480 if (!is_array($phoneDefault)) {
2481 $defaults[$fldName] = $phoneDefault;
2482 }
2483 }
2484 }
2485 elseif ($fieldName == 'email') {
2486 //adding the first email (currently we don't support multiple emails of same location type)
2487 $defaults[$fldName] = $value['email'];
2488 }
2489 elseif ($fieldName == 'im') {
2490 //adding the first im (currently we don't support multiple ims of same location type)
2491 $defaults[$fldName] = $value['im'];
2492 $defaults[$fldName . '-provider_id'] = $value['im_provider_id'];
2493 }
2494 else {
2495 $defaults[$fldName] = $value[$fieldName];
2496 }
2497 }
2498 elseif (substr($fieldName, 0, 14) === 'address_custom' &&
2499 CRM_Utils_Array::value(substr($fieldName, 8), $value)
2500 ) {
2501 $defaults[$fldName] = $value[substr($fieldName, 8)];
2502 }
2503 }
2504 }
2505 }
2506 }
2507 }
2508 else {
2509 if (is_array($details)) {
2510 if ($fieldName === 'url'
2511 && !empty($details['website'])
2512 && !empty($details['website'][$locTypeId])
2513 ) {
2514 $defaults[$fldName] = CRM_Utils_Array::value('url', $details['website'][$locTypeId]);
2515 }
2516 }
2517 }
2518 }
2519 }
2520 }
2521
2522 //Handling Contribution Part of the batch profile
2523 if (CRM_Core_Permission::access('CiviContribute') && $component == 'Contribute') {
2524 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2525 }
2526
2527 //Handling Event Participation Part of the batch profile
2528 if (CRM_Core_Permission::access('CiviEvent') && $component == 'Event') {
2529 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2530 }
2531
2532 //Handling membership Part of the batch profile
2533 if (CRM_Core_Permission::access('CiviMember') && $component == 'Membership') {
2534 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2535 }
2536
2537 //Handling Activity Part of the batch profile
2538 if ($component == 'Activity') {
2539 self::setComponentDefaults($fields, $componentId, $component, $defaults);
2540 }
2541 }
2542
2543 /**
2544 * Get profiles by type eg: pure Individual etc
2545 *
2546 * @param array $types
2547 * Associative array of types eg: types('Individual').
2548 * @param bool $onlyPure
2549 * True if only pure profiles are required.
2550 *
2551 * @return array
2552 * associative array of profiles
2553 */
2554 public static function getProfiles($types, $onlyPure = FALSE) {
2555 $profiles = array();
2556 $ufGroups = CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id');
2557
2558 CRM_Utils_Hook::aclGroup(CRM_Core_Permission::ADMIN, NULL, 'civicrm_uf_group', $ufGroups, $ufGroups);
2559
2560 // Exclude Batch Data Entry profiles - CRM-10901
2561 $batchProfiles = CRM_Core_BAO_UFGroup::getBatchProfiles();
2562
2563 foreach ($ufGroups as $id => $title) {
2564 $ptype = CRM_Core_BAO_UFField::getProfileType($id, FALSE, $onlyPure);
2565 if (in_array($ptype, $types) && !array_key_exists($id, $batchProfiles)) {
2566 $profiles[$id] = $title;
2567 }
2568 }
2569 return $profiles;
2570 }
2571
2572 /**
2573 * Check whether a profile is valid combination of
2574 * required and/or optional profile types
2575 *
2576 * @param array $required
2577 * Array of types those are required.
2578 * @param array $optional
2579 * Array of types those are optional.
2580 *
2581 * @return array
2582 * associative array of profiles
2583 */
2584 public static function getValidProfiles($required, $optional = NULL) {
2585 if (!is_array($required) || empty($required)) {
2586 return NULL;
2587 }
2588
2589 $profiles = array();
2590 $ufGroups = CRM_Core_PseudoConstant::get('CRM_Core_DAO_UFField', 'uf_group_id');
2591
2592 CRM_Utils_Hook::aclGroup(CRM_Core_Permission::ADMIN, NULL, 'civicrm_uf_group', $ufGroups, $ufGroups);
2593
2594 foreach ($ufGroups as $id => $title) {
2595 $type = CRM_Core_BAO_UFField::checkValidProfileType($id, $required, $optional);
2596 if ($type) {
2597 $profiles[$id] = $title;
2598 }
2599 }
2600
2601 return $profiles;
2602 }
2603
2604 /**
2605 * Check whether a profile is valid combination of
2606 * required profile fields
2607 *
2608 * @param array $ufId
2609 * Integer id of the profile.
2610 * @param array $required
2611 * Array of fields those are required in the profile.
2612 *
2613 * @return array
2614 * associative array of profiles
2615 */
2616 public static function checkValidProfile($ufId, $required = NULL) {
2617 $validProfile = FALSE;
2618 if (!$ufId) {
2619 return $validProfile;
2620 }
2621
2622 if (!CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $ufId, 'is_active')) {
2623 return $validProfile;
2624 }
2625
2626 $profileFields = self::getFields($ufId, FALSE, CRM_Core_Action::VIEW, NULL,
2627 NULL, FALSE, NULL, FALSE, NULL,
2628 CRM_Core_Permission::CREATE, NULL
2629 );
2630
2631 $validProfile = array();
2632 if (!empty($profileFields)) {
2633 $fields = array_keys($profileFields);
2634 foreach ($fields as $val) {
2635 foreach ($required as $key => $field) {
2636 if (strpos($val, $field) === 0) {
2637 unset($required[$key]);
2638 }
2639 }
2640 }
2641
2642 $validProfile = (empty($required)) ? TRUE : FALSE;
2643 }
2644
2645 return $validProfile;
2646 }
2647
2648 /**
2649 * Get default value for Register.
2650 *
2651 * @param array $fields
2652 * @param array $defaults
2653 *
2654 * @return array
2655 */
2656 public static function setRegisterDefaults(&$fields, &$defaults) {
2657 $config = CRM_Core_Config::singleton();
2658 foreach ($fields as $name => $field) {
2659 if (substr($name, 0, 8) == 'country-') {
2660 if (!empty($config->defaultContactCountry)) {
2661 $defaults[$name] = $config->defaultContactCountry;
2662 }
2663 }
2664 elseif (substr($name, 0, 15) == 'state_province-') {
2665 if (!empty($config->defaultContactStateProvince)) {
2666 $defaults[$name] = $config->defaultContactStateProvince;
2667 }
2668 }
2669 }
2670 return $defaults;
2671 }
2672
2673 /**
2674 * make a copy of a profile, including
2675 * all the fields in the profile
2676 *
2677 * @param int $id
2678 * The profile id to copy.
2679 *
2680 * @return \CRM_Core_DAO
2681 */
2682 public static function copy($id) {
2683 $maxId = CRM_Core_DAO::singleValueQuery("SELECT max(id) FROM civicrm_uf_group");
2684
2685 $title = ts('[Copy id %1]', array(1 => $maxId + 1));
2686 $fieldsFix = array(
2687 'suffix' => array(
2688 'title' => ' ' . $title,
2689 'name' => '__Copy_id_' . ($maxId + 1) . '_',
2690 ),
2691 );
2692
2693 $copy = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFGroup',
2694 array('id' => $id),
2695 NULL,
2696 $fieldsFix
2697 );
2698
2699 if ($pos = strrpos($copy->name, "_{$id}")) {
2700 $copy->name = substr_replace($copy->name, '', $pos);
2701 }
2702 $copy->name = CRM_Utils_String::munge($copy->name, '_', 56) . "_{$copy->id}";
2703 $copy->save();
2704
2705 $copyUFJoin = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFJoin',
2706 array('uf_group_id' => $id),
2707 array('uf_group_id' => $copy->id),
2708 NULL,
2709 'entity_table'
2710 );
2711
2712 $copyUFField = &CRM_Core_DAO::copyGeneric('CRM_Core_BAO_UFField',
2713 array('uf_group_id' => $id),
2714 array('uf_group_id' => $copy->id)
2715 );
2716
2717 $maxWeight = CRM_Utils_Weight::getMax('CRM_Core_DAO_UFJoin', NULL, 'weight');
2718
2719 //update the weight
2720 $query = "
2721 UPDATE civicrm_uf_join
2722 SET weight = %1
2723 WHERE uf_group_id = %2
2724 AND ( entity_id IS NULL OR entity_id <= 0 )
2725 ";
2726 $p = array(
2727 1 => array($maxWeight + 1, 'Integer'),
2728 2 => array($copy->id, 'Integer'),
2729 );
2730 CRM_Core_DAO::executeQuery($query, $p);
2731 if ($copy->is_reserved) {
2732 $query = "UPDATE civicrm_uf_group SET is_reserved = 0 WHERE id = %1";
2733 $params = array(1 => array($copy->id, 'Integer'));
2734 CRM_Core_DAO::executeQuery($query, $params);
2735 }
2736 CRM_Utils_Hook::copy('UFGroup', $copy);
2737
2738 return $copy;
2739 }
2740
2741 /**
2742 * Process that send notification e-mails
2743 *
2744 * @param int $contactID
2745 * Contact id.
2746 * @param array $values
2747 * Associative array of name/value pair.
2748 */
2749 public static function commonSendMail($contactID, &$values) {
2750 if (!$contactID || !$values) {
2751 return;
2752
2753 }
2754 $template = CRM_Core_Smarty::singleton();
2755
2756 $displayName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
2757 $contactID,
2758 'display_name'
2759 );
2760
2761 self::profileDisplay($values['id'], $values['values'], $template);
2762 $emailList = explode(',', $values['email']);
2763
2764 $contactLink = CRM_Utils_System::url('civicrm/contact/view',
2765 "reset=1&cid=$contactID",
2766 TRUE, NULL, FALSE, FALSE, TRUE
2767 );
2768
2769 //get the default domain email address.
2770 list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail();
2771
2772 if (!$domainEmailAddress || $domainEmailAddress == 'info@EXAMPLE.ORG') {
2773 $fixUrl = CRM_Utils_System::url('civicrm/admin/domain', 'action=update&reset=1');
2774 CRM_Core_Error::fatal(ts('The site administrator needs to enter a valid \'FROM Email Address\' in <a href="%1">Administer CiviCRM &raquo; Communications &raquo; FROM Email Addresses</a>. The email address used may need to be a valid mail account with your email service provider.', array(1 => $fixUrl)));
2775 }
2776
2777 foreach ($emailList as $emailTo) {
2778 // FIXME: take the below out of the foreach loop
2779 CRM_Core_BAO_MessageTemplate::sendTemplate(
2780 array(
2781 'groupName' => 'msg_tpl_workflow_uf',
2782 'valueName' => 'uf_notify',
2783 'contactId' => $contactID,
2784 'tplParams' => array(
2785 'displayName' => $displayName,
2786 'currentDate' => date('r'),
2787 'contactLink' => $contactLink,
2788 ),
2789 'from' => "$domainEmailName <$domainEmailAddress>",
2790 'toEmail' => $emailTo,
2791 )
2792 );
2793 }
2794 }
2795
2796 /**
2797 * Given a contact id and a group id, returns the field values from the db
2798 * for this group and notify email only if group's notify field is
2799 * set and field values are not empty
2800 *
2801 * @param int $gid
2802 * Group id.
2803 * @param int $cid
2804 * Contact id.
2805 * @param array $params
2806 * @param bool $skipCheck
2807 *
2808 * @return array
2809 */
2810 public function checkFieldsEmptyValues($gid, $cid, $params, $skipCheck = FALSE) {
2811 if ($gid) {
2812 if (CRM_Core_BAO_UFGroup::filterUFGroups($gid, $cid) || $skipCheck) {
2813 $values = array();
2814 $fields = CRM_Core_BAO_UFGroup::getFields($gid, FALSE, CRM_Core_Action::VIEW);
2815 CRM_Core_BAO_UFGroup::getValues($cid, $fields, $values, FALSE, $params, TRUE);
2816
2817 $email = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'notify');
2818
2819 if (!empty($values) &&
2820 !empty($email)
2821 ) {
2822 $val = array(
2823 'id' => $gid,
2824 'values' => $values,
2825 'email' => $email,
2826 );
2827 return $val;
2828 }
2829 }
2830 }
2831 return NULL;
2832 }
2833
2834 /**
2835 * Assign uf fields to template.
2836 *
2837 * @param int $gid
2838 * Group id.
2839 * @param array $values
2840 * @param CRM_Core_Smarty $template
2841 */
2842 static public function profileDisplay($gid, $values, $template) {
2843 $groupTitle = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'title');
2844 $template->assign('grouptitle', $groupTitle);
2845 if (count($values)) {
2846 $template->assign('values', $values);
2847 }
2848 }
2849
2850 /**
2851 * Format fields for dupe Contact Matching.
2852 *
2853 * @param array $params
2854 *
2855 * @param int $contactId
2856 *
2857 * @return array
2858 * associated formatted array
2859 */
2860 public static function formatFields($params, $contactId = NULL) {
2861 if ($contactId) {
2862 // get the primary location type id and email
2863 list($name, $primaryEmail, $primaryLocationType) = CRM_Contact_BAO_Contact_Location::getEmailDetails($contactId);
2864 }
2865 else {
2866 $defaultLocationType = CRM_Core_BAO_LocationType::getDefault();
2867 $primaryLocationType = $defaultLocationType->id;
2868 }
2869
2870 $data = array();
2871 $locationType = array();
2872 $count = 1;
2873 $primaryLocation = 0;
2874 foreach ($params as $key => $value) {
2875 list($fieldName, $locTypeId, $phoneTypeId) = explode('-', $key);
2876
2877 if ($locTypeId == 'Primary') {
2878 $locTypeId = $primaryLocationType;
2879 }
2880
2881 if (is_numeric($locTypeId)) {
2882 if (!in_array($locTypeId, $locationType)) {
2883 $locationType[$count] = $locTypeId;
2884 $count++;
2885 }
2886 $loc = CRM_Utils_Array::key($locTypeId, $locationType);
2887
2888 $data['location'][$loc]['location_type_id'] = $locTypeId;
2889
2890 // if we are getting in a new primary email, dont overwrite the new one
2891 if ($locTypeId == $primaryLocationType) {
2892 if (!empty($params['email-' . $primaryLocationType])) {
2893 $data['location'][$loc]['email'][$loc]['email'] = $fields['email-' . $primaryLocationType];
2894 }
2895 elseif (isset($primaryEmail)) {
2896 $data['location'][$loc]['email'][$loc]['email'] = $primaryEmail;
2897 }
2898 $primaryLocation++;
2899 }
2900
2901 if ($loc == 1) {
2902 $data['location'][$loc]['is_primary'] = 1;
2903 }
2904 if ($fieldName == 'phone') {
2905 if ($phoneTypeId) {
2906 $data['location'][$loc]['phone'][$loc]['phone_type_id'] = $phoneTypeId;
2907 }
2908 else {
2909 $data['location'][$loc]['phone'][$loc]['phone_type_id'] = '';
2910 }
2911 $data['location'][$loc]['phone'][$loc]['phone'] = $value;
2912 }
2913 elseif ($fieldName == 'email') {
2914 $data['location'][$loc]['email'][$loc]['email'] = $value;
2915 }
2916 elseif ($fieldName == 'im') {
2917 $data['location'][$loc]['im'][$loc]['name'] = $value;
2918 }
2919 else {
2920 if ($fieldName === 'state_province') {
2921 $data['location'][$loc]['address']['state_province_id'] = $value;
2922 }
2923 elseif ($fieldName === 'country') {
2924 $data['location'][$loc]['address']['country_id'] = $value;
2925 }
2926 else {
2927 $data['location'][$loc]['address'][$fieldName] = $value;
2928 }
2929 }
2930 }
2931 else {
2932 // TODO: prefix, suffix and gender translation may no longer be necessary - check inputs
2933 if ($key === 'individual_suffix') {
2934 $data['suffix_id'] = $value;
2935 }
2936 elseif ($key === 'individual_prefix') {
2937 $data['prefix_id'] = $value;
2938 }
2939 elseif ($key === 'gender') {
2940 $data['gender_id'] = $value;
2941 }
2942 elseif (substr($key, 0, 6) === 'custom') {
2943 if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
2944 //fix checkbox
2945 if ($customFields[$customFieldID]['html_type'] == 'CheckBox') {
2946 $value = implode(CRM_Core_DAO::VALUE_SEPARATOR, array_keys($value));
2947 }
2948 // fix the date field
2949 if ($customFields[$customFieldID]['data_type'] == 'Date') {
2950 $date = CRM_Utils_Date::format($value);
2951 if (!$date) {
2952 $date = '';
2953 }
2954 $value = $date;
2955 }
2956
2957 $data['custom'][$customFieldID] = array(
2958 'id' => $id,
2959 'value' => $value,
2960 'extends' => $customFields[$customFieldID]['extends'],
2961 'type' => $customFields[$customFieldID]['data_type'],
2962 'custom_field_id' => $customFieldID,
2963 );
2964 }
2965 }
2966 elseif ($key == 'edit') {
2967 continue;
2968 }
2969 else {
2970 $data[$key] = $value;
2971 }
2972 }
2973 }
2974
2975 if (!$primaryLocation) {
2976 $loc++;
2977 $data['location'][$loc]['email'][$loc]['email'] = $primaryEmail;
2978 }
2979
2980 return $data;
2981 }
2982
2983 /**
2984 * Calculate the profile type 'group_type' as per profile fields.
2985 *
2986 * @param int $gId
2987 * Profile id.
2988 * @param bool $includeTypeValues
2989 * @param int $ignoreFieldId
2990 * Ignore particular profile field.
2991 *
2992 * @return array
2993 * list of calculated group type
2994 */
2995 public static function calculateGroupType($gId, $includeTypeValues = FALSE, $ignoreFieldId = NULL) {
2996 //get the profile fields.
2997 $ufFields = self::getFields($gId, FALSE, NULL, NULL, NULL, TRUE, NULL, TRUE);
2998 return self::_calculateGroupType($ufFields, $includeTypeValues, $ignoreFieldId);
2999 }
3000
3001 /**
3002 * Calculate the profile type 'group_type' as per profile fields.
3003 *
3004 * @param $ufFields
3005 * @param bool $includeTypeValues
3006 * @param int $ignoreFieldId
3007 * Ignore perticular profile field.
3008 *
3009 * @return array
3010 * list of calculated group type
3011 */
3012 public static function _calculateGroupType($ufFields, $includeTypeValues = FALSE, $ignoreFieldId = NULL) {
3013 $groupType = $groupTypeValues = $customFieldIds = array();
3014 if (!empty($ufFields)) {
3015 foreach ($ufFields as $fieldName => $fieldValue) {
3016 //ignore field from group type when provided.
3017 //in case of update profile field.
3018 if ($ignoreFieldId && ($ignoreFieldId == $fieldValue['field_id'])) {
3019 continue;
3020 }
3021 if (!in_array($fieldValue['field_type'], $groupType)) {
3022 $groupType[$fieldValue['field_type']] = $fieldValue['field_type'];
3023 }
3024
3025 if ($includeTypeValues && ($fldId = CRM_Core_BAO_CustomField::getKeyID($fieldName))) {
3026 $customFieldIds[$fldId] = $fldId;
3027 }
3028 }
3029 }
3030
3031 if (!empty($customFieldIds)) {
3032 $query = 'SELECT DISTINCT(cg.id), cg.extends, cg.extends_entity_column_id, cg.extends_entity_column_value FROM civicrm_custom_group cg LEFT JOIN civicrm_custom_field cf ON cf.custom_group_id = cg.id WHERE cg.extends_entity_column_value IS NOT NULL AND cf.id IN (' . implode(',', $customFieldIds) . ')';
3033
3034 $customGroups = CRM_Core_DAO::executeQuery($query);
3035 while ($customGroups->fetch()) {
3036 if (!$customGroups->extends_entity_column_value) {
3037 continue;
3038 }
3039
3040 $groupTypeName = "{$customGroups->extends}Type";
3041 if ($customGroups->extends == 'Participant' && $customGroups->extends_entity_column_id) {
3042 $groupTypeName = CRM_Core_OptionGroup::getValue('custom_data_type', $customGroups->extends_entity_column_id, 'value', 'String', 'name');
3043 }
3044
3045 foreach (explode(CRM_Core_DAO::VALUE_SEPARATOR, $customGroups->extends_entity_column_value) as $val) {
3046 if ($val) {
3047 $groupTypeValues[$groupTypeName][$val] = $val;
3048 }
3049 }
3050 }
3051
3052 if (!empty($groupTypeValues)) {
3053 $groupType = array_merge($groupType, $groupTypeValues);
3054 }
3055 }
3056
3057 return $groupType;
3058 }
3059
3060 /**
3061 * Update the profile type 'group_type' as per profile fields including group types and group subtype values.
3062 * Build and store string like: group_type1,group_type2[VALUE_SEPERATOR]group_type1Type:1:2:3,group_type2Type:1:2
3063 *
3064 * FIELDS GROUP_TYPE
3065 * BirthDate + Email Individual,Contact
3066 * BirthDate + Subject Individual,Activity
3067 * BirthDate + Subject + SurveyOnlyField Individual,Activity\0ActivityType:28
3068 * BirthDate + Subject + SurveyOnlyField + PhoneOnlyField (Not allowed)
3069 * BirthDate + SurveyOnlyField Individual,Activity\0ActivityType:28
3070 * BirthDate + Subject + SurveyOrPhoneField Individual,Activity\0ActivityType:2:28
3071 * BirthDate + SurveyOrPhoneField Individual,Activity\0ActivityType:2:28
3072 * BirthDate + SurveyOrPhoneField + SurveyOnlyField Individual,Activity\0ActivityType:2:28
3073 * BirthDate + StudentField + Subject + SurveyOnlyField Individual,Activity,Student\0ActivityType:28
3074 *
3075 * @param int $gId
3076 * @param array $groupTypes
3077 * With key having group type names.
3078 *
3079 * @return bool
3080 */
3081 public static function updateGroupTypes($gId, $groupTypes = array()) {
3082 if (!is_array($groupTypes) || !$gId) {
3083 return FALSE;
3084 }
3085
3086 // If empty group types set group_type as 'null'
3087 if (empty($groupTypes)) {
3088 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFGroup', $gId, 'group_type', 'null');
3089 }
3090
3091 $componentGroupTypes = array('Contribution', 'Participant', 'Membership', 'Activity', 'Case');
3092 $validGroupTypes = array_merge(array(
3093 'Contact',
3094 'Individual',
3095 'Organization',
3096 'Household',
3097 ), $componentGroupTypes, CRM_Contact_BAO_ContactType::subTypes());
3098
3099 $gTypes = $gTypeValues = array();
3100
3101 $participantExtends = array('ParticipantRole', 'ParticipantEventName', 'ParticipantEventType');
3102 // Get valid group type and group subtypes
3103 foreach ($groupTypes as $groupType => $value) {
3104 if (in_array($groupType, $validGroupTypes) && !in_array($groupType, $gTypes)) {
3105 $gTypes[] = $groupType;
3106 }
3107
3108 $subTypesOf = NULL;
3109
3110 if (in_array($groupType, $participantExtends)) {
3111 $subTypesOf = $groupType;
3112 }
3113 elseif (strpos($groupType, 'Type') > 0) {
3114 $subTypesOf = substr($groupType, 0, strpos($groupType, 'Type'));
3115 }
3116 else {
3117 continue;
3118 }
3119
3120 if (!empty($value) &&
3121 (in_array($subTypesOf, $componentGroupTypes) ||
3122 in_array($subTypesOf, $participantExtends)
3123 )
3124 ) {
3125 $gTypeValues[$subTypesOf] = $groupType . ":" . implode(':', $value);
3126 }
3127 }
3128
3129 if (empty($gTypes)) {
3130 return FALSE;
3131 }
3132
3133 // Build String to store group types and group subtypes
3134 $groupTypeString = implode(',', $gTypes);
3135 if (!empty($gTypeValues)) {
3136 $groupTypeString .= CRM_Core_DAO::VALUE_SEPARATOR . implode(',', $gTypeValues);
3137 }
3138
3139 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFGroup', $gId, 'group_type', $groupTypeString);
3140 }
3141
3142 /**
3143 * Create a "group_type" string.
3144 *
3145 * @param array $coreTypes
3146 * E.g. array('Individual','Contact','Student').
3147 * @param array $subTypes
3148 * E.g. array('ActivityType' => array(7, 11)).
3149 * @param string $delim
3150 *
3151 * @return string
3152 * @throws CRM_Core_Exception
3153 */
3154 public static function encodeGroupType($coreTypes, $subTypes, $delim = CRM_Core_DAO::VALUE_SEPARATOR) {
3155 $groupTypeExpr = '';
3156 if ($coreTypes) {
3157 $groupTypeExpr .= implode(',', $coreTypes);
3158 }
3159 if ($subTypes) {
3160 //CRM-15427 Allow Multiple subtype filtering
3161 //if (count($subTypes) > 1) {
3162 //throw new CRM_Core_Exception("Multiple subtype filtering is not currently supported by widget.");
3163 //}
3164 foreach ($subTypes as $subType => $subTypeIds) {
3165 $groupTypeExpr .= $delim . $subType . ':' . implode(':', $subTypeIds);
3166 }
3167 }
3168 return $groupTypeExpr;
3169 }
3170
3171 /**
3172 * setDefault componet specific profile fields.
3173 *
3174 * @param array $fields
3175 * Profile fields.
3176 * @param int $componentId
3177 * ComponetID.
3178 * @param string $component
3179 * Component name.
3180 * @param array $defaults
3181 * An array of default values.
3182 *
3183 * @param bool $isStandalone
3184 */
3185 public static function setComponentDefaults(&$fields, $componentId, $component, &$defaults, $isStandalone = FALSE) {
3186 if (!$componentId ||
3187 !in_array($component, array('Contribute', 'Membership', 'Event', 'Activity'))
3188 ) {
3189 return;
3190 }
3191
3192 $componentBAO = $componentSubType = NULL;
3193 switch ($component) {
3194 case 'Membership':
3195 $componentBAO = 'CRM_Member_BAO_Membership';
3196 $componentBAOName = 'Membership';
3197 $componentSubType = array('membership_type_id');
3198 break;
3199
3200 case 'Contribute':
3201 $componentBAO = 'CRM_Contribute_BAO_Contribution';
3202 $componentBAOName = 'Contribution';
3203 $componentSubType = array('financial_type_id');
3204 break;
3205
3206 case 'Event':
3207 $componentBAO = 'CRM_Event_BAO_Participant';
3208 $componentBAOName = 'Participant';
3209 $componentSubType = array('role_id', 'event_id', 'event_type_id');
3210 break;
3211
3212 case 'Activity':
3213 $componentBAO = 'CRM_Activity_BAO_Activity';
3214 $componentBAOName = 'Activity';
3215 $componentSubType = array('activity_type_id');
3216 break;
3217 }
3218
3219 $values = array();
3220 $params = array('id' => $componentId);
3221
3222 //get the component values.
3223 CRM_Core_DAO::commonRetrieve($componentBAO, $params, $values);
3224 if ($componentBAOName == 'Participant') {
3225 $values += array('event_type_id' => CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $values['event_id'], 'event_type_id'));
3226 }
3227
3228 $formattedGroupTree = array();
3229
3230 foreach ($fields as $name => $field) {
3231 $fldName = $isStandalone ? $name : "field[$componentId][$name]";
3232 if (array_key_exists($name, $values)) {
3233 $defaults[$fldName] = $values[$name];
3234 }
3235 elseif ($name == 'participant_note') {
3236 $noteDetails = CRM_Core_BAO_Note::getNote($componentId, 'civicrm_participant');
3237 $defaults[$fldName] = array_pop($noteDetails);
3238 }
3239 elseif (in_array($name, array(
3240 'financial_type',
3241 'payment_instrument',
3242 'participant_status',
3243 'participant_role',
3244 ))) {
3245 $defaults[$fldName] = $values["{$name}_id"];
3246 }
3247 elseif ($name == 'membership_type') {
3248 // since membership_type field is a hierselect -
3249 $defaults[$fldName][0]
3250 = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $values['membership_type_id'], 'member_of_contact_id', 'id');
3251 $defaults[$fldName][1] = $values['membership_type_id'];
3252 }
3253 elseif ($name == 'membership_status') {
3254 $defaults[$fldName] = $values['status_id'];
3255 }
3256 elseif (CRM_Core_BAO_CustomField::getKeyID($name, TRUE) !== array(NULL, NULL)) {
3257 if (empty($formattedGroupTree)) {
3258 //get the groupTree as per subTypes.
3259 $groupTree = array();
3260 foreach ($componentSubType as $subType) {
3261 $subTree = CRM_Core_BAO_CustomGroup::getTree($componentBAOName, CRM_Core_DAO::$_nullObject,
3262 $componentId, 0, $values[$subType]
3263 );
3264 $groupTree = CRM_Utils_Array::crmArrayMerge($groupTree, $subTree);
3265 }
3266 $formattedGroupTree = CRM_Core_BAO_CustomGroup::formatGroupTree($groupTree, 1);
3267 CRM_Core_BAO_CustomGroup::setDefaults($formattedGroupTree, $defaults);
3268 }
3269
3270 //FIX ME: We need to loop defaults, but once we move to custom_1_x convention this code can be simplified.
3271 foreach ($defaults as $customKey => $customValue) {
3272 if ($customFieldDetails = CRM_Core_BAO_CustomField::getKeyID($customKey, TRUE)) {
3273 if ($name == 'custom_' . $customFieldDetails[0]) {
3274
3275 //hack to set default for checkbox
3276 //basically this is for weired field name like field[33][custom_19]
3277 //we are converting this field name to array structure and assign value.
3278 $skipValue = FALSE;
3279
3280 foreach ($formattedGroupTree as $tree) {
3281 if (!empty($tree['fields'][$customFieldDetails[0]])) {
3282 if ('CheckBox' == CRM_Utils_Array::value('html_type', $tree['fields'][$customFieldDetails[0]])) {
3283 $skipValue = TRUE;
3284 $defaults['field'][$componentId][$name] = $customValue;
3285 break;
3286 }
3287 elseif (CRM_Utils_Array::value('data_type', $tree['fields'][$customFieldDetails[0]]) == 'Date') {
3288 $skipValue = TRUE;
3289
3290 // CRM-6681, $default contains formatted date, time values.
3291 $defaults[$fldName] = $customValue;
3292 if (!empty($defaults[$customKey . '_time'])) {
3293 $defaults['field'][$componentId][$name . '_time'] = $defaults[$customKey . '_time'];
3294 }
3295 }
3296 }
3297 }
3298
3299 if (!$skipValue || $isStandalone) {
3300 $defaults[$fldName] = $customValue;
3301 }
3302 unset($defaults[$customKey]);
3303 break;
3304 }
3305 }
3306 }
3307 }
3308 elseif (isset($values[$fldName])) {
3309 $defaults[$fldName] = $values[$fldName];
3310 }
3311 }
3312 }
3313
3314 /**
3315 * @param array|string $profiles - name of profile(s) to create links for
3316 * @param array $appendProfiles
3317 * Name of profile(s) to append to each link.
3318 *
3319 * @return array
3320 */
3321 public static function getCreateLinks($profiles = '', $appendProfiles = array()) {
3322 // Default to contact profiles
3323 if (!$profiles) {
3324 $profiles = array('new_individual', 'new_organization', 'new_household');
3325 }
3326 $profiles = (array) $profiles;
3327 $toGet = array_merge($profiles, (array) $appendProfiles);
3328 $retrieved = civicrm_api3('uf_group', 'get', array(
3329 'name' => array('IN' => $toGet),
3330 'is_active' => 1,
3331 ));
3332 $links = $append = array();
3333 if (!empty($retrieved['values'])) {
3334 foreach ($retrieved['values'] as $id => $profile) {
3335 if (in_array($profile['name'], $profiles)) {
3336 $links[] = array(
3337 'label' => $profile['title'],
3338 'url' => CRM_Utils_System::url('civicrm/profile/create', "reset=1&context=dialog&gid=$id",
3339 NULL, NULL, FALSE, FALSE, TRUE),
3340 'type' => ucfirst(str_replace('new_', '', $profile['name'])),
3341 );
3342 }
3343 else {
3344 $append[] = $id;
3345 }
3346 }
3347 foreach ($append as $id) {
3348 foreach ($links as &$link) {
3349 $link['url'] .= ",$id";
3350 }
3351 }
3352 }
3353 return $links;
3354 }
3355
3356 /**
3357 * Retrieve groups of profiles.
3358 *
3359 * @param int $profileID
3360 * Id of the profile.
3361 *
3362 * @return array
3363 * returns array
3364 */
3365 public static function profileGroups($profileID) {
3366 $groupTypes = array();
3367 $profileTypes = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $profileID, 'group_type');
3368 if ($profileTypes) {
3369 $groupTypeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $profileTypes);
3370 $groupTypes = explode(',', $groupTypeParts[0]);
3371 }
3372 return $groupTypes;
3373 }
3374
3375 /**
3376 * Alter contact params by filtering existing subscribed groups and returns
3377 * unsubscribed groups array for subscription.
3378 *
3379 * @param array $params
3380 * Contact params.
3381 * @param int $contactId
3382 * User contact id.
3383 *
3384 * @return array
3385 * This contains array of groups for subscription
3386 */
3387 public static function getDoubleOptInGroupIds(&$params, $contactId = NULL) {
3388 $config = CRM_Core_Config::singleton();
3389 $subscribeGroupIds = array();
3390
3391 // process further only if profileDoubleOptIn enabled and if groups exist
3392 if (!array_key_exists('group', $params) ||
3393 !self::isProfileDoubleOptin() ||
3394 CRM_Utils_System::isNull($params['group'])
3395 ) {
3396 return $subscribeGroupIds;
3397 }
3398
3399 //check if contact email exist.
3400 $hasEmails = FALSE;
3401 foreach ($params as $name => $value) {
3402 if (strpos($name, 'email-') !== FALSE) {
3403 $hasEmails = TRUE;
3404 break;
3405 }
3406 }
3407
3408 //Proceed furthur only if email present
3409 if (!$hasEmails) {
3410 return $subscribeGroupIds;
3411 }
3412
3413 //do check for already subscriptions.
3414 $contactGroups = array();
3415 if ($contactId) {
3416 $query = "
3417 SELECT group_id
3418 FROM civicrm_group_contact
3419 WHERE status = 'Added'
3420 AND contact_id = %1";
3421
3422 $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($contactId, 'Integer')));
3423 while ($dao->fetch()) {
3424 $contactGroups[$dao->group_id] = $dao->group_id;
3425 }
3426 }
3427
3428 //since we don't have names, compare w/ label.
3429 $mailingListGroupType = array_search('Mailing List', CRM_Core_OptionGroup::values('group_type'));
3430
3431 //actual processing start.
3432 foreach ($params['group'] as $groupId => $isSelected) {
3433 //unset group those are not selected.
3434 if (!$isSelected) {
3435 unset($params['group'][$groupId]);
3436 continue;
3437 }
3438
3439 $groupTypes = explode(CRM_Core_DAO::VALUE_SEPARATOR,
3440 CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $groupId, 'group_type', 'id')
3441 );
3442 //get only mailing type group and unset it from params
3443 if (in_array($mailingListGroupType, $groupTypes) && !in_array($groupId, $contactGroups)) {
3444 $subscribeGroupIds[$groupId] = $groupId;
3445 unset($params['group'][$groupId]);
3446 }
3447 }
3448
3449 return $subscribeGroupIds;
3450 }
3451
3452 /**
3453 * Check if we are rendering mixed profiles.
3454 *
3455 * @param array $profileIds
3456 * Associated array of profile ids.
3457 *
3458 * @return bool
3459 * true if profile is mixed
3460 */
3461 public static function checkForMixProfiles($profileIds) {
3462 $mixProfile = FALSE;
3463
3464 $contactTypes = array('Individual', 'Household', 'Organization');
3465 $subTypes = CRM_Contact_BAO_ContactType::subTypes();
3466
3467 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
3468
3469 $typeCount = array('ctype' => array(), 'subtype' => array());
3470 foreach ($profileIds as $gid) {
3471 $profileType = CRM_Core_BAO_UFField::getProfileType($gid);
3472 // ignore profile of type Contact
3473 if ($profileType == 'Contact') {
3474 continue;
3475 }
3476 if (in_array($profileType, $contactTypes)) {
3477 if (!isset($typeCount['ctype'][$profileType])) {
3478 $typeCount['ctype'][$profileType] = 1;
3479 }
3480
3481 // check if we are rendering profile of different contact types
3482 if (count($typeCount['ctype']) == 2) {
3483 $mixProfile = TRUE;
3484 break;
3485 }
3486 }
3487 elseif (in_array($profileType, $components)) {
3488 $mixProfile = TRUE;
3489 break;
3490 }
3491 else {
3492 if (!isset($typeCount['subtype'][$profileType])) {
3493 $typeCount['subtype'][$profileType] = 1;
3494 }
3495 // check if we are rendering profile of different contact sub types
3496 if (count($typeCount['subtype']) == 2) {
3497 $mixProfile = TRUE;
3498 break;
3499 }
3500 }
3501 }
3502 return $mixProfile;
3503 }
3504
3505 /**
3506 * Determine of we show overlay profile or not.
3507 *
3508 * @return bool
3509 * true if profile should be shown else false
3510 */
3511 public static function showOverlayProfile() {
3512 $showOverlay = TRUE;
3513
3514 // get the id of overlay profile
3515 $overlayProfileId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', 'summary_overlay', 'id', 'name');
3516 $query = "SELECT count(id) FROM civicrm_uf_field WHERE uf_group_id = {$overlayProfileId} AND visibility IN ('Public Pages', 'Public Pages and Listings') ";
3517
3518 $count = CRM_Core_DAO::singleValueQuery($query);
3519
3520 //check if there are no public fields and use is anonymous
3521 $session = CRM_Core_Session::singleton();
3522 if (!$count && !$session->get('userID')) {
3523 $showOverlay = FALSE;
3524 }
3525
3526 return $showOverlay;
3527 }
3528
3529 /**
3530 * Get group type values of the profile.
3531 *
3532 * @param int $profileId
3533 * @param string $groupType
3534 *
3535 * @return array
3536 * group type values
3537 */
3538 public static function groupTypeValues($profileId, $groupType = NULL) {
3539 $groupTypeValue = array();
3540 $groupTypes = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $profileId, 'group_type');
3541
3542 $groupTypeParts = explode(CRM_Core_DAO::VALUE_SEPARATOR, $groupTypes);
3543 if (empty($groupTypeParts[1])) {
3544 return $groupTypeValue;
3545 }
3546 $participantExtends = array('ParticipantRole', 'ParticipantEventName', 'ParticipantEventType');
3547
3548 foreach (explode(',', $groupTypeParts[1]) as $groupTypeValues) {
3549 $values = array();
3550 $valueParts = explode(':', $groupTypeValues);
3551 if ($groupType &&
3552 ($valueParts[0] != "{$groupType}Type" ||
3553 ($groupType == 'Participant' &&
3554 !in_array($valueParts[0], $participantExtends)
3555 )
3556 )
3557 ) {
3558 continue;
3559 }
3560 foreach ($valueParts as $val) {
3561 if (CRM_Utils_Rule::integer($val)) {
3562 $values[$val] = $val;
3563 }
3564 }
3565 if (!empty($values)) {
3566 $typeName = substr($valueParts[0], 0, -4);
3567 if (in_array($valueParts[0], $participantExtends)) {
3568 $typeName = $valueParts[0];
3569 }
3570 $groupTypeValue[$typeName] = $values;
3571 }
3572 }
3573
3574 return $groupTypeValue;
3575 }
3576
3577 /**
3578 * @return bool|object
3579 */
3580 public static function isProfileDoubleOptin() {
3581 // check for double optin
3582 $config = CRM_Core_Config::singleton();
3583 if (in_array('CiviMail', $config->enableComponents)) {
3584 return Civi::settings()->get('profile_double_optin');
3585 }
3586 return FALSE;
3587 }
3588
3589 /**
3590 * @return bool|object
3591 */
3592 public static function isProfileAddToGroupDoubleOptin() {
3593 // check for add to group double optin
3594 $config = CRM_Core_Config::singleton();
3595 if (in_array('CiviMail', $config->enableComponents)) {
3596 return Civi::settings()->get('profile_add_to_group_double_optin');
3597 }
3598 return FALSE;
3599 }
3600
3601 /**
3602 * Get profiles used for batch entry.
3603 *
3604 * @return array
3605 * profileIds profile ids
3606 */
3607 public static function getBatchProfiles() {
3608 $query = "SELECT id
3609 FROM civicrm_uf_group
3610 WHERE name IN ('contribution_batch_entry', 'membership_batch_entry')";
3611 $dao = CRM_Core_DAO::executeQuery($query);
3612 $profileIds = array();
3613 while ($dao->fetch()) {
3614 $profileIds[$dao->id] = $dao->id;
3615 }
3616 return $profileIds;
3617 }
3618
3619 /**
3620 * @todo what do I do?
3621 * @param $source
3622 * @param $destination
3623 * @param bool $returnMultiSummaryFields
3624 *
3625 * @return array|null
3626 */
3627 public static function shiftMultiRecordFields(&$source, &$destination, $returnMultiSummaryFields = FALSE) {
3628 $multiSummaryFields = $returnMultiSummaryFields ? array() : NULL;
3629 foreach ($source as $field => $properties) {
3630 if (!CRM_Core_BAO_CustomField::getKeyID($field)) {
3631 continue;
3632 }
3633 if (CRM_Core_BAO_CustomField::isMultiRecordField($field)) {
3634 $destination[$field] = $properties;
3635 if ($returnMultiSummaryFields) {
3636 if ($properties['is_multi_summary']) {
3637 $multiSummaryFields[$field] = $properties;
3638 }
3639 }
3640 unset($source[$field]);
3641 }
3642 }
3643 return $multiSummaryFields;
3644 }
3645
3646 /**
3647 * This is function is used to format pseudo fields.
3648 *
3649 * @param array $fields
3650 * Associated array of profile fields.
3651 *
3652 */
3653 public static function reformatProfileFields(&$fields) {
3654 //reformat fields array
3655 foreach ($fields as $name => $field) {
3656 //reformat phone and extension field
3657 if (substr($field['name'], 0, 13) == 'phone_and_ext') {
3658 $fieldSuffix = str_replace('phone_and_ext-', '', $field['name']);
3659
3660 // retain existing element properties and just update and replace key
3661 CRM_Utils_Array::crmReplaceKey($fields, $name, "phone-{$fieldSuffix}");
3662 $fields["phone-{$fieldSuffix}"]['name'] = "phone-{$fieldSuffix}";
3663 $fields["phone-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone';
3664
3665 // add additional phone extension field
3666 $fields["phone_ext-{$fieldSuffix}"] = $field;
3667 $fields["phone_ext-{$fieldSuffix}"]['title'] = $field['title'] . ' - ' . ts('Ext.');
3668 $fields["phone_ext-{$fieldSuffix}"]['name'] = "phone_ext-{$fieldSuffix}";
3669 $fields["phone_ext-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone_ext';
3670 $fields["phone_ext-{$fieldSuffix}"]['skipDisplay'] = 1;
3671 //ignore required for extension field
3672 $fields["phone_ext-{$fieldSuffix}"]['is_required'] = 0;
3673 }
3674 }
3675 }
3676
3677 }