3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2019
37 class CRM_Core_BAO_UFGroup
extends CRM_Core_DAO_UFGroup
{
38 const PUBLIC_VISIBILITY
= 1,
40 LISTINGS_VISIBILITY
= 4;
43 * Cache the match clause used in this transaction.
47 static $_matchFields = NULL;
50 * Fetch object based on array of properties.
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.
58 * CRM_Core_DAO_UFGroup object
60 public static function retrieve(&$params, &$defaults) {
61 return CRM_Core_DAO
::commonRetrieve('CRM_Core_DAO_UFGroup', $params, $defaults);
65 * Retrieve the first non-generic contact type
73 public static function getContactType($id) {
75 $validTypes = array_filter(array_keys(CRM_Core_SelectValues
::contactType()));
76 $validSubTypes = CRM_Contact_BAO_ContactType
::subTypeInfo();
78 $typesParts = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $id, 'group_type'));
79 $types = explode(',', $typesParts[0]);
82 foreach ($types as $type) {
83 if (in_array($type, $validTypes)) {
86 elseif (array_key_exists($type, $validSubTypes)) {
87 $cType = CRM_Utils_Array
::value('parent', $validSubTypes[$type]);
107 public static function getTitle($id) {
108 return CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $id, 'title');
112 * Update the is_active flag in the db.
115 * Id of the database record.
116 * @param bool $is_active
117 * Value we want to set the is_active field.
120 * true if we found and updated the object, else false
122 public static function setIsActive($id, $is_active) {
123 return CRM_Core_DAO
::setFieldValue('CRM_Core_DAO_UFGroup', $id, 'is_active', $is_active);
127 * Get all the registration fields.
130 * What action are we doing.
137 * the fields that are needed for registration
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');
144 $ufGroups = CRM_Core_BAO_UFGroup
::getModuleUFGroup('Profile');
147 if (!is_array($ufGroups)) {
153 foreach ($ufGroups as $id => $title) {
155 $fieldType = CRM_Core_BAO_UFField
::getProfileType($id);
156 if (($fieldType != 'Contact') &&
157 ($fieldType != $ctype) &&
158 !CRM_Contact_BAO_ContactType
::isExtendsContactType($fieldType, $ctype)
162 if (CRM_Contact_BAO_ContactType
::isaSubType($fieldType)) {
163 $profileSubType = $fieldType;
167 $subset = self
::getFields($id, TRUE, $action,
168 NULL, NULL, FALSE, NULL, TRUE, $ctype
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;
183 * Get all the listing fields.
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
194 * @param null $restrict
195 * @param bool $skipPermission
196 * @param int $permissionType
198 * the fields that are listings related
200 public static function getListingFields(
203 $considerSelector = FALSE,
207 $skipPermission = FALSE,
208 $permissionType = CRM_Core_Permission
::SEARCH
211 $subset = self
::getFields($ufGroupIds, FALSE, $action,
212 $visibility, $searchable,
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]);
229 $ufGroups = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_UFField', 'uf_group_id');
232 foreach ($ufGroups as $id => $title) {
233 $subset = self
::getFields($id, FALSE, $action,
234 $visibility, $searchable,
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]);
248 $fields = array_merge($fields, $subset);
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
260 * The id of the UF group or ids of ufgroup.
261 * @param bool|int $register are we interested in registration fields
263 * What action are we doing.
264 * @param int $visibility
265 * Visibility of fields we are interested in.
267 * @param bool $showAll
268 * @param string $restrict
269 * Should we restrict based on a specified profile type.
270 * @param bool $skipPermission
272 * @param int $permissionType
273 * @param string $orderBy
274 * @param null $orderProfiles
276 * @param bool $eventProfile
279 * The fields that belong to this ufgroup(s)
282 public static function getFields(
290 $skipPermission = FALSE,
292 $permissionType = CRM_Core_Permission
::CREATE
,
293 $orderBy = 'field_name',
294 $orderProfiles = NULL,
295 $eventProfile = FALSE
297 if (!is_array($id)) {
298 $id = CRM_Utils_Type
::escape($id, 'Positive');
299 $profileIds = array($id);
305 $gids = implode(',', $profileIds);
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 )
313 $params = array(1 => array($restrict, 'String'));
316 $query = "SELECT g.* from civicrm_uf_group g WHERE g.id IN ( {$gids} ) ";
320 $query .= " AND g.is_active = 1";
323 $checkPermission = array(
325 'administer CiviCRM',
326 'manage event profiles',
329 if ($eventProfile && CRM_Core_Permission
::check($checkPermission)) {
330 $skipPermission = TRUE;
333 // add permissioning for profiles only if not registration
334 if (!$skipPermission) {
335 $permissionClause = CRM_Core_Permission
::ufGroupClause($permissionType, 'g.');
336 $query .= " AND $permissionClause ";
339 if ($orderProfiles AND count($profileIds) > 1) {
340 $query .= " ORDER BY FIELD( g.id, {$gids} )";
342 $group = CRM_Core_DAO
::executeQuery($query, $params);
346 while ($group->fetch()) {
348 $query = self
::createUFFieldQuery($group->id
, $searchable, $showAll, $visibility, $orderBy);
349 $field = CRM_Core_DAO
::executeQuery($query);
351 $importableFields = self
::getProfileFieldMetadata($showAll);
352 list($customFields, $addressCustomFields) = self
::getCustomFields($ctype);
354 while ($field->fetch()) {
355 list($name, $formattedField) = self
::formatUFField($group, $field, $customFields, $addressCustomFields, $importableFields, $permissionType);
356 if ($formattedField !== NULL) {
357 $fields[$name] = $formattedField;
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))
369 self
::reformatProfileFields($fields);
376 * Format a list of UFFields for use with buildProfile. This is the in-memory analog
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
388 * @param int $permissionType
391 * @see self::getFields
393 public static function formatUFFields(
400 $permissionType = CRM_Core_Permission
::CREATE
402 // $group = new CRM_Core_DAO_UFGroup();
403 // $group->copyValues($groupArr); // no... converts string('') to string('null')
404 $group = (object) $groupArr;
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);
415 $formattedFields = array();
416 foreach ($fieldArrs as $fieldArr) {
417 $field = (object) $fieldArr;
418 if (!self
::filterUFField($field, $searchable, $showAll, $visibility)) {
422 list($name, $formattedField) = self
::formatUFField($group, $field, $customFields, $addressCustomFields, $importableFields, $permissionType);
423 if ($formattedField !== NULL) {
424 $formattedFields[$name] = $formattedField;
427 return $formattedFields;
431 * Prepare a field for rendering with CRM_Core_BAO_UFGroup::buildProfile.
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.
442 protected static function formatUFField(
446 $addressCustomFields,
448 $permissionType = CRM_Core_Permission
::CREATE
450 $name = $field->field_name
;
451 $title = $field->label
;
453 $addressCustom = FALSE;
454 if (in_array($permissionType, array(
455 CRM_Core_Permission
::CREATE
,
456 CRM_Core_Permission
::EDIT
,
458 in_array($field->field_name
, array_keys($addressCustomFields))
460 $addressCustom = TRUE;
461 $name = "address_{$name}";
463 if ($field->field_name
== 'url') {
464 $name .= "-{$field->website_type_id}";
466 elseif (!empty($field->location_type_id
)) {
467 $name .= "-{$field->location_type_id}";
470 $locationFields = self
::getLocationFields();
471 if (in_array($field->field_name
, $locationFields) ||
$addressCustom) {
476 if (isset($field->phone_type_id
)) {
477 $name .= "-{$field->phone_type_id}";
479 $fieldMetaData = CRM_Utils_Array
::value($name, $importableFields, (isset($importableFields[$field->field_name
]) ?
$importableFields[$field->field_name
] : array()));
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(
485 'groupTitle' => $group->title
,
486 'groupName' => $group->name
,
487 'groupDisplayTitle' => (!empty($group->frontend_title
)) ?
$group->frontend_title
: $group->title
,
488 'groupHelpPre' => empty($group->help_pre
) ?
'' : $group->help_pre
,
489 'groupHelpPost' => empty($group->help_post
) ?
'' : $group->help_post
,
491 'where' => CRM_Utils_Array
::value('where', CRM_Utils_Array
::value($field->field_name
, $importableFields)),
492 'attributes' => CRM_Core_DAO
::makeAttribute(CRM_Utils_Array
::value($field->field_name
, $importableFields)),
493 'is_required' => $field->is_required
,
494 'is_view' => $field->is_view
,
495 'help_pre' => $field->help_pre
,
496 'help_post' => $field->help_post
,
497 'visibility' => $field->visibility
,
498 'in_selector' => $field->in_selector
,
499 'rule' => CRM_Utils_Array
::value('rule', CRM_Utils_Array
::value($field->field_name
, $importableFields)),
500 'location_type_id' => isset($field->location_type_id
) ?
$field->location_type_id
: NULL,
501 'website_type_id' => isset($field->website_type_id
) ?
$field->website_type_id
: NULL,
502 'phone_type_id' => isset($field->phone_type_id
) ?
$field->phone_type_id
: NULL,
503 'group_id' => $group->id
,
504 'add_to_group_id' => isset($group->add_to_group_id
) ?
$group->add_to_group_id
: NULL,
505 'add_captcha' => isset($group->add_captcha
) ?
$group->add_captcha
: NULL,
506 'field_type' => $field->field_type
,
507 'field_id' => $field->id
,
508 'pseudoconstant' => CRM_Utils_Array
::value(
510 CRM_Utils_Array
::value($field->field_name
, $importableFields)
512 // obsolete this when we remove the name / dbName discrepancy with gender/suffix/prefix
513 'dbName' => CRM_Utils_Array
::value(
515 CRM_Utils_Array
::value($field->field_name
, $importableFields)
518 'data_type' => CRM_Utils_Type
::getDataTypeFromFieldMetadata($fieldMetaData),
519 'bao' => CRM_Utils_Array
::value('bao', $fieldMetaData),
522 $formattedField = CRM_Utils_Date
::addDateMetadataToField($fieldMetaData, $formattedField);
524 //adding custom field property
525 if (substr($field->field_name
, 0, 6) == 'custom' ||
526 substr($field->field_name
, 0, 14) === 'address_custom'
528 // if field is not present in customFields, that means the user
529 // DOES NOT HAVE permission to access that field
530 if (array_key_exists($field->field_name
, $customFields)) {
531 $formattedField['is_search_range'] = $customFields[$field->field_name
]['is_search_range'];
533 $formattedField['options_per_line'] = $customFields[$field->field_name
]['options_per_line'];
534 $formattedField['html_type'] = $customFields[$field->field_name
]['html_type'];
536 if (CRM_Utils_Array
::value('html_type', $formattedField) == 'Select Date') {
537 $formattedField['date_format'] = $customFields[$field->field_name
]['date_format'];
538 $formattedField['time_format'] = $customFields[$field->field_name
]['time_format'];
539 $formattedField['is_datetime_field'] = TRUE;
540 $formattedField['smarty_view_format'] = CRM_Utils_Date
::getDateFieldViewFormat($formattedField['date_format']);
543 $formattedField['is_multi_summary'] = $field->is_multi_summary
;
544 return array($name, $formattedField);
547 $formattedField = NULL;
548 return array($name, $formattedField);
551 return array($name, $formattedField);
555 * Create a query to find all visible UFFields in a UFGroup.
557 * This is the SQL-variant of checkUFFieldDisplayable().
559 * @param int $groupId
560 * @param bool $searchable
561 * @param bool $showAll
562 * @param int $visibility
563 * @param string $orderBy
564 * Comma-delimited list of SQL columns.
567 protected static function createUFFieldQuery($groupId, $searchable, $showAll, $visibility, $orderBy) {
568 $where = " WHERE uf_group_id = {$groupId}";
571 $where .= " AND is_searchable = 1";
575 $where .= " AND is_active = 1";
580 if ($visibility & self
::PUBLIC_VISIBILITY
) {
581 $clause[] = 'visibility = "Public Pages"';
583 if ($visibility & self
::ADMIN_VISIBILITY
) {
584 $clause[] = 'visibility = "User and User Admin Only"';
586 if ($visibility & self
::LISTINGS_VISIBILITY
) {
587 $clause[] = 'visibility = "Public Pages and Listings"';
589 if (!empty($clause)) {
590 $where .= ' AND ( ' . implode(' OR ', $clause) . ' ) ';
594 $query = "SELECT * FROM civicrm_uf_field $where ORDER BY weight";
596 $query .= ", " . $orderBy;
603 * Create a query to find all visible UFFields in a UFGroup.
605 * This is the PHP in-memory variant of createUFFieldQuery().
607 * @param CRM_Core_DAO_UFField|CRM_Core_DAO $field
608 * @param bool $searchable
609 * @param bool $showAll
610 * @param int $visibility
612 * TRUE if field is displayable
614 protected static function filterUFField($field, $searchable, $showAll, $visibility) {
615 if ($searchable && $field->is_searchable
!= 1) {
619 if (!$showAll && $field->is_active
!= 1) {
624 $allowedVisibilities = array();
625 if ($visibility & self
::PUBLIC_VISIBILITY
) {
626 $allowedVisibilities[] = 'Public Pages';
628 if ($visibility & self
::ADMIN_VISIBILITY
) {
629 $allowedVisibilities[] = 'User and User Admin Only';
631 if ($visibility & self
::LISTINGS_VISIBILITY
) {
632 $allowedVisibilities[] = 'Public Pages and Listings';
634 // !empty($allowedVisibilities) seems silly to me, but it is equivalent to the pre-existing SQL
635 if (!empty($allowedVisibilities) && !in_array($field->visibility
, $allowedVisibilities)) {
644 * Get a list of filtered field metadata.
646 * @deprecated use getProfileFieldMetadata
649 * @param $profileType
650 * @param $contactActivityProfile
651 * @param bool $filterMode
652 * Filter mode means you are using importable fields for filtering rather than just getting metadata.
653 * With filter mode = FALSE BOTH activity fields and component fields are returned.
654 * I can't see why you would ever want to use this function in filter mode as the component fields are
655 * still unfiltered. However, I feel scared enough to leave it as it is. I have marked this function as
656 * deprecated and am recommending the wrapper 'getProfileFieldMetadata' in order to try to
657 * send this confusion to history.
661 protected static function getImportableFields($showAll, $profileType, $contactActivityProfile, $filterMode = TRUE) {
663 $importableFields = CRM_Contact_BAO_Contact
::importableFields('All', FALSE, FALSE, FALSE, TRUE, TRUE);
666 $importableFields = CRM_Contact_BAO_Contact
::importableFields('All', FALSE, TRUE, FALSE, TRUE, TRUE);
669 $activityFields = CRM_Activity_BAO_Activity
::getProfileFields();
670 $componentFields = CRM_Core_Component
::getQueryFields();
671 if ($filterMode == TRUE) {
672 if ($profileType == 'Activity' ||
$contactActivityProfile) {
673 $importableFields = array_merge($importableFields, $activityFields);
676 $importableFields = array_merge($importableFields, $componentFields);
680 $importableFields = array_merge($importableFields, $activityFields, $componentFields);
683 $importableFields['group']['title'] = ts('Group(s)');
684 $importableFields['group']['where'] = NULL;
685 $importableFields['tag']['title'] = ts('Tag(s)');
686 $importableFields['tag']['where'] = NULL;
687 return $importableFields;
691 * Get the metadata for all potential profile fields.
693 * @param bool $isIncludeInactive
694 * Should disabled fields be included.
697 * Field metadata for all fields that might potentially be in a profile.
699 protected static function getProfileFieldMetadata($isIncludeInactive) {
700 return self
::getImportableFields($isIncludeInactive, NULL, NULL, NULL, TRUE);
704 * Get the fields relating to locations.
708 public static function getLocationFields() {
709 static $locationFields = array(
711 'supplemental_address_1',
712 'supplemental_address_2',
713 'supplemental_address_3',
716 'postal_code_suffix',
729 return $locationFields;
737 protected static function getCustomFields($ctype) {
738 static $customFieldCache = array();
739 if (!isset($customFieldCache[$ctype])) {
740 $customFields = CRM_Core_BAO_CustomField
::getFieldsForImport($ctype, FALSE, FALSE, FALSE, TRUE, TRUE);
742 // hack to add custom data for components
743 $components = array('Contribution', 'Participant', 'Membership', 'Activity', 'Case');
744 foreach ($components as $value) {
745 $customFields = array_merge($customFields, CRM_Core_BAO_CustomField
::getFieldsForImport($value));
747 $addressCustomFields = CRM_Core_BAO_CustomField
::getFieldsForImport('Address');
748 $customFields = array_merge($customFields, $addressCustomFields);
749 $customFieldCache[$ctype] = array($customFields, $addressCustomFields);
751 return $customFieldCache[$ctype];
755 * Check the data validity.
758 * The user id that we are actually editing.
759 * @param string $name
760 * The machine-name of the group we are interested in.
761 * @param bool $register
763 * The action of the form.
765 * @pram boolean $register is this the registrtion form
767 * true if form is valid
769 public static function isValid($userID, $name, $register = FALSE, $action = NULL) {
771 $controller = new CRM_Core_Controller_Simple('CRM_Profile_Form_Dynamic',
772 ts('Dynamic Form Creator'),
775 $controller->set('id', $userID);
776 $controller->set('register', 1);
777 $controller->process();
778 return $controller->validate();
781 // make sure we have a valid group
782 $group = new CRM_Core_DAO_UFGroup();
784 $group->name
= $name;
786 if ($group->find(TRUE) && $userID) {
787 $controller = new CRM_Core_Controller_Simple('CRM_Profile_Form_Dynamic', ts('Dynamic Form Creator'), $action);
788 $controller->set('gid', $group->id
);
789 $controller->set('id', $userID);
790 $controller->set('register', 0);
791 $controller->process();
792 return $controller->validate();
799 * Get the html for the form that represents this particular group.
802 * The user id that we are actually editing.
803 * @param string $title
804 * The title of the group we are interested in.
806 * The action of the form.
807 * @param bool $register
808 * Is this the registration form.
810 * Should we reset the form?.
811 * @param int $profileID
812 * Do we have the profile ID?.
814 * @param bool $doNotProcess
818 * the html for the form on success, otherwise empty string
820 public static function getEditHTML(
827 $doNotProcess = FALSE,
832 $controller = new CRM_Core_Controller_Simple('CRM_Profile_Form_Dynamic',
833 ts('Dynamic Form Creator'),
836 if ($reset ||
$doNotProcess) {
837 // hack to make sure we do not process this form
838 $oldQFDefault = CRM_Utils_Array
::value('_qf_default',
841 unset($_POST['_qf_default']);
842 unset($_REQUEST['_qf_default']);
844 $controller->reset();
848 $controller->set('id', $userID);
849 $controller->set('register', 1);
850 $controller->set('skipPermission', 1);
851 $controller->set('ctype', $ctype);
852 $controller->process();
853 if ($doNotProcess ||
!empty($_POST)) {
854 $controller->validate();
856 $controller->setEmbedded(TRUE);
858 //CRM-5839 - though we want to process form, get the control back.
859 $controller->setSkipRedirection(($doNotProcess) ?
FALSE : TRUE);
863 // we are done processing so restore the POST/REQUEST vars
864 if (($reset ||
$doNotProcess) && $oldQFDefault) {
865 $_POST['_qf_default'] = $_REQUEST['_qf_default'] = $oldQFDefault;
868 $template = CRM_Core_Smarty
::singleton();
870 // Hide CRM error messages if they are displayed using drupal form_set_error.
871 if (!empty($_POST)) {
872 $template->assign('suppressForm', TRUE);
875 return trim($template->fetch('CRM/Profile/Form/Dynamic.tpl'));
879 // make sure we have a valid group
880 $group = new CRM_Core_DAO_UFGroup();
882 $group->title
= $title;
884 if ($group->find(TRUE)) {
885 $profileID = $group->id
;
890 // make sure profileID and ctype match if ctype exists
892 $profileType = CRM_Core_BAO_UFField
::getProfileType($profileID);
893 if (CRM_Contact_BAO_ContactType
::isaSubType($profileType)) {
894 $profileType = CRM_Contact_BAO_ContactType
::getBasicType($profileType);
897 if (($profileType != 'Contact') && ($profileType != $ctype)) {
902 $controller = new CRM_Core_Controller_Simple('CRM_Profile_Form_Dynamic',
903 ts('Dynamic Form Creator'),
907 $controller->reset();
909 $controller->set('gid', $profileID);
910 $controller->set('id', $userID);
911 $controller->set('register', 0);
912 $controller->set('skipPermission', 1);
914 $controller->set('ctype', $ctype);
916 $controller->process();
917 $controller->setEmbedded(TRUE);
919 //CRM-5846 - give the control back to drupal.
920 $controller->setSkipRedirection(($doNotProcess) ?
FALSE : TRUE);
923 $template = CRM_Core_Smarty
::singleton();
925 // Hide CRM error messages if they are displayed using drupal form_set_error.
926 if (!empty($_POST) && CRM_Core_Config
::singleton()->userFramework
== 'Drupal') {
927 if (arg(0) == 'user' ||
(arg(0) == 'admin' && arg(1) == 'people')) {
928 $template->assign('suppressForm', TRUE);
932 $templateFile = "CRM/Profile/Form/{$profileID}/Dynamic.tpl";
933 if (!$template->template_exists($templateFile)) {
934 $templateFile = 'CRM/Profile/Form/Dynamic.tpl';
936 return trim($template->fetch($templateFile));
939 $userEmail = CRM_Contact_BAO_Contact_Location
::getEmailDetails($userID);
941 // if post not empty then only proceed
942 if (!empty($_POST)) {
944 $config = CRM_Core_Config
::singleton();
945 $email = CRM_Utils_Array
::value('mail', $_POST);
947 if (CRM_Utils_Rule
::email($email) && ($email != $userEmail[1])) {
948 CRM_Core_BAO_UFMatch
::updateContactEmail($userID, $email);
957 * Given a contact id and a field set, return the values from the db.
960 * @param array $fields
961 * The profile fields of interest.
962 * @param array $values
963 * The values for the above fields.
964 * @param bool $searchable
966 * @param array $componentWhere
967 * Component condition.
968 * @param bool $absolute
969 * Return urls in absolute form (useful when sending an email).
970 * @param null $additionalWhereClause
974 public static function getValues(
975 $cid, &$fields, &$values,
976 $searchable = TRUE, $componentWhere = NULL,
977 $absolute = FALSE, $additionalWhereClause = NULL
979 if (empty($cid) && empty($componentWhere)) {
983 // get the contact details (hier)
984 $returnProperties = CRM_Contact_BAO_Contact
::makeHierReturnProperties($fields);
985 $params = $cid ?
array(array('contact_id', '=', $cid, 0, 0)) : array();
987 // add conditions specified by components. eg partcipant_id etc
988 if (!empty($componentWhere)) {
989 $params = array_merge($params, $componentWhere);
992 $query = new CRM_Contact_BAO_Query($params, $returnProperties, $fields);
994 $details = $query->searchQuery(0, 0, NULL, FALSE, FALSE,
995 FALSE, FALSE, FALSE, $additionalWhereClause);
996 while ($details->fetch()) {
1001 $query->convertToPseudoNames($details);
1002 $config = CRM_Core_Config
::singleton();
1004 $locationTypes = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Address', 'location_type_id');
1005 $imProviders = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_IM', 'provider_id');
1006 $websiteTypes = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Website', 'website_type_id');
1008 $multipleFields = array('url');
1010 //start of code to set the default values
1011 foreach ($fields as $name => $field) {
1013 if ($name == 'id') {
1014 $name = 'contact_id';
1017 // skip fields that should not be displayed separately
1018 if (!empty($field['skipDisplay'])) {
1022 // Create a unique, non-empty index for each field.
1023 $index = $field['title'];
1024 if ($index === '') {
1027 while (array_key_exists($index, $values)) {
1031 $params[$index] = $values[$index] = '';
1032 $customFieldName = NULL;
1034 if (isset($details->$name) ||
$name == 'group' ||
$name == 'tag') {
1035 // to handle gender / suffix / prefix
1036 if (in_array(substr($name, 0, -3), array('gender', 'prefix', 'suffix'))) {
1037 $params[$index] = $details->$name;
1038 $values[$index] = $details->$name;
1040 elseif (in_array($name, CRM_Contact_BAO_Contact
::$_greetingTypes)) {
1041 $dname = $name . '_display';
1042 $values[$index] = $details->$dname;
1043 $name = $name . '_id';
1044 $params[$index] = $details->$name;
1046 elseif (in_array($name, array(
1051 $values[$index] = $details->$name;
1052 $idx = $name . '_id';
1053 $params[$index] = $details->$idx;
1055 elseif ($name === 'preferred_language') {
1056 $params[$index] = $details->$name;
1057 $values[$index] = CRM_Core_PseudoConstant
::getLabel('CRM_Contact_DAO_Contact', 'preferred_language', $details->$name);
1059 elseif ($name == 'group') {
1060 $groups = CRM_Contact_BAO_GroupContact
::getContactGroup($cid, 'Added', NULL, FALSE, TRUE);
1061 $title = $ids = array();
1063 foreach ($groups as $g) {
1064 // CRM-8362: User and User Admin visibility groups should be included in display if user has
1065 // VIEW permission on that group
1066 $groupPerm = CRM_Contact_BAO_Group
::checkPermission($g['group_id'], TRUE);
1068 if ($g['visibility'] != 'User and User Admin Only' ||
1069 CRM_Utils_Array
::key(CRM_Core_Permission
::VIEW
, $groupPerm)
1071 $title[] = $g['title'];
1072 if ($g['visibility'] == 'Public Pages') {
1073 $ids[] = $g['group_id'];
1077 $values[$index] = implode(', ', $title);
1078 $params[$index] = implode(',', $ids);
1080 elseif ($name == 'tag') {
1081 $entityTags = CRM_Core_BAO_EntityTag
::getTag($cid);
1082 $allTags = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_EntityTag', 'tag_id', array('onlyActive' => FALSE));
1084 foreach ($entityTags as $tagId) {
1085 $title[] = $allTags[$tagId];
1087 $values[$index] = implode(', ', $title);
1088 $params[$index] = implode(',', $entityTags);
1090 elseif ($name == 'activity_status_id') {
1091 $activityStatus = CRM_Core_PseudoConstant
::activityStatus();
1092 $values[$index] = $activityStatus[$details->$name];
1093 $params[$index] = $details->$name;
1095 elseif ($name == 'activity_date_time') {
1096 $values[$index] = CRM_Utils_Date
::customFormat($details->$name);
1097 $params[$index] = $details->$name;
1099 elseif ($name == 'contact_sub_type') {
1100 $contactSubTypeNames = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $details->$name);
1101 if (!empty($contactSubTypeNames)) {
1102 $contactSubTypeLabels = array();
1103 // get all contact subtypes
1104 $allContactSubTypes = CRM_Contact_BAO_ContactType
::subTypeInfo();
1105 // build contact subtype labels array
1106 foreach ($contactSubTypeNames as $cstName) {
1108 $contactSubTypeLabels[] = $allContactSubTypes[$cstName]['label'];
1111 $values[$index] = implode(',', $contactSubTypeLabels);
1114 $params[$index] = $details->$name;
1117 if (substr($name, 0, 7) === 'do_not_' ||
substr($name, 0, 3) === 'is_') {
1118 if ($details->$name) {
1119 $values[$index] = '[ x ]';
1123 if ($cfID = CRM_Core_BAO_CustomField
::getKeyID($name)) {
1124 $htmlType = $field['html_type'];
1126 // field_type is only set when we are retrieving profile values
1127 // when sending email, we call the same function to get custom field
1128 // values etc, i.e. emulating a profile
1129 $fieldType = CRM_Utils_Array
::value('field_type', $field);
1131 if ($htmlType == 'File') {
1134 $fieldType == 'Activity' && !empty($componentWhere[0][2])
1136 $entityId = $componentWhere[0][2];
1139 $fileURL = CRM_Core_BAO_CustomField
::getFileURL($entityId,
1143 $additionalWhereClause
1145 $params[$index] = $values[$index] = $fileURL['file_url'];
1149 if (isset($dao) && property_exists($dao, 'data_type') &&
1150 ($dao->data_type
== 'Int' ||
1151 $dao->data_type
== 'Boolean'
1154 $customVal = (int ) ($details->{$name});
1156 elseif (isset($dao) && property_exists($dao, 'data_type')
1157 && $dao->data_type
== 'Float'
1159 $customVal = (float ) ($details->{$name});
1161 elseif (!CRM_Utils_System
::isNull(explode(CRM_Core_DAO
::VALUE_SEPARATOR
,
1165 $customVal = $details->{$name};
1169 if (CRM_Utils_System
::isNull($customVal)) {
1173 $params[$index] = $customVal;
1174 $values[$index] = CRM_Core_BAO_CustomField
::displayValue($customVal, $cfID);
1175 if ($field['data_type'] == 'ContactReference') {
1176 $params[$index] = $values[$index];
1178 if (CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomField',
1179 $cfID, 'is_search_range'
1182 $customFieldName = "{$name}_from";
1186 elseif ($name == 'image_URL') {
1187 list($width, $height) = getimagesize(CRM_Utils_String
::unstupifyUrl($details->$name));
1188 list($thumbWidth, $thumbHeight) = CRM_Contact_BAO_Contact
::getThumbSize($width, $height);
1190 $image_URL = '<img src="' . $details->$name . '" height= ' . $thumbHeight . ' width= ' . $thumbWidth . ' />';
1191 $values[$index] = "<a href='#' onclick='contactImagePopUp(\"{$details->$name}\", {$width}, {$height});'>{$image_URL}</a>";
1193 elseif (in_array($name, array(
1197 // @todo this set should be determined from metadata, not hard-coded.
1198 $values[$index] = CRM_Utils_Date
::customFormat($details->$name);
1199 $params[$index] = CRM_Utils_Date
::isoToMysql($details->$name);
1203 if ($index == 'Campaign') {
1204 $dao = 'CRM_Campaign_DAO_Campaign';
1206 elseif ($index == 'Contribution Page') {
1207 $dao = 'CRM_Contribute_DAO_ContributionPage';
1210 $value = CRM_Core_DAO
::getFieldValue($dao, $details->$name, 'title');
1213 $value = $details->$name;
1215 $values[$index] = $value;
1220 elseif (strpos($name, '-') !== FALSE) {
1221 list($fieldName, $id, $type) = CRM_Utils_System
::explode('-', $name, 3);
1223 if (!in_array($fieldName, $multipleFields)) {
1224 if ($id == 'Primary') {
1226 // not sure why we'd every use Primary location type id
1227 // we need to fix the source if we are using it
1228 // $locationTypeName = CRM_Contact_BAO_Contact::getPrimaryLocationType( $cid );
1229 $locationTypeName = 1;
1232 $locationTypeName = CRM_Utils_Array
::value($id, $locationTypes);
1235 if (!$locationTypeName) {
1239 $detailName = "{$locationTypeName}-{$fieldName}";
1240 $detailName = str_replace(' ', '_', $detailName);
1242 if (in_array($fieldName, array(
1249 $detailName .= "-{$type}";
1253 if (in_array($fieldName, array(
1258 $values[$index] = $details->$detailName;
1259 $idx = $detailName . '_id';
1260 $params[$index] = $details->$idx;
1262 elseif ($fieldName == 'im') {
1263 $providerId = $detailName . '-provider_id';
1264 if (isset($imProviders[$details->$providerId])) {
1265 $values[$index] = $details->$detailName . " (" . $imProviders[$details->$providerId] . ")";
1268 $values[$index] = $details->$detailName;
1270 $params[$index] = $details->$detailName;
1272 elseif ($fieldName == 'phone') {
1273 $phoneExtField = str_replace('phone', 'phone_ext', $detailName);
1274 if (isset($details->$phoneExtField)) {
1275 $values[$index] = $details->$detailName . " (" . $details->$phoneExtField . ")";
1278 $values[$index] = $details->$detailName;
1280 $params[$index] = $details->$detailName;
1283 $values[$index] = $params[$index] = $details->$detailName;
1287 $detailName = "website-{$id}-{$fieldName}";
1288 $url = CRM_Utils_System
::fixURL($details->$detailName);
1289 if ($details->$detailName) {
1290 $websiteTypeId = "website-{$id}-website_type_id";
1291 $websiteType = $websiteTypes[$details->$websiteTypeId];
1292 $values[$index] = "<a href=\"$url\">{$details->$detailName} ( {$websiteType} )</a>";
1295 $values[$index] = '';
1300 if ((CRM_Utils_Array
::value('visibility', $field) == 'Public Pages and Listings') &&
1301 CRM_Core_Permission
::check('profile listings and forms')
1304 if (CRM_Utils_System
::isNull($params[$index])) {
1305 $params[$index] = $values[$index];
1307 if (!isset($params[$index])) {
1310 if (!$customFieldName) {
1311 $fieldName = $field['name'];
1314 $fieldName = $customFieldName;
1318 if (CRM_Core_BAO_CustomField
::getKeyID($field['name'])) {
1319 $htmlType = $field['html_type'];
1320 if ($htmlType == 'Link') {
1321 $url = $params[$index];
1323 elseif (in_array($htmlType, array(
1326 'Multi-Select State/Province',
1327 'Multi-Select Country',
1329 $valSeperator = CRM_Core_DAO
::VALUE_SEPARATOR
;
1330 $selectedOptions = explode($valSeperator, $params[$index]);
1332 foreach ($selectedOptions as $key => $multiOption) {
1334 $url[] = CRM_Utils_System
::url('civicrm/profile',
1335 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1336 urlencode($fieldName) .
1338 urlencode($multiOption)
1344 $url = CRM_Utils_System
::url('civicrm/profile',
1345 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1346 urlencode($fieldName) .
1348 urlencode($params[$index])
1353 $url = CRM_Utils_System
::url('civicrm/profile',
1354 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1355 urlencode($fieldName) .
1357 urlencode($params[$index])
1362 !empty($values[$index]) &&
1366 if (is_array($url) && !empty($url)) {
1368 $eachMultiValue = explode(', ', $values[$index]);
1369 foreach ($eachMultiValue as $key => $valueLabel) {
1370 $links[] = '<a href="' . $url[$key] . '">' . $valueLabel . '</a>';
1372 $values[$index] = implode(', ', $links);
1375 $values[$index] = '<a href="' . $url . '">' . $values[$index] . '</a>';
1383 * Check if profile Group used by any module.
1391 public static function usedByModule($id) {
1392 //check whether this group is used by any module(check uf join records)
1394 FROM civicrm_uf_join
1395 WHERE civicrm_uf_join.uf_group_id=$id";
1397 $dao = new CRM_Core_DAO();
1399 if ($dao->fetch()) {
1408 * Delete the profile Group.
1416 public static function del($id) {
1417 //check whether this group contains any profile fields
1418 $profileField = new CRM_Core_DAO_UFField();
1419 $profileField->uf_group_id
= $id;
1420 $profileField->find();
1421 while ($profileField->fetch()) {
1422 CRM_Core_BAO_UFField
::del($profileField->id
);
1425 //delete records from uf join table
1426 $ufJoin = new CRM_Core_DAO_UFJoin();
1427 $ufJoin->uf_group_id
= $id;
1430 //delete profile group
1431 $group = new CRM_Core_DAO_UFGroup();
1440 * @param array $params
1441 * Reference array contains the values submitted by the form.
1443 * Reference array contains the id.
1448 public static function add(&$params, $ids = array()) {
1458 foreach ($fields as $field) {
1459 $params[$field] = CRM_Utils_Array
::value($field, $params, FALSE);
1462 $params['limit_listings_group_id'] = CRM_Utils_Array
::value('group', $params);
1463 $params['add_to_group_id'] = CRM_Utils_Array
::value('add_contact_to_group', $params);
1466 if (!empty($params['group_type']) && is_array($params['group_type'])) {
1467 $params['group_type'] = implode(',', $params['group_type']);
1469 $ufGroup = new CRM_Core_DAO_UFGroup();
1470 $ufGroup->copyValues($params);
1472 $ufGroupID = CRM_Utils_Array
::value('ufgroup', $ids, CRM_Utils_Array
::value('id', $params));
1473 if (!$ufGroupID && empty($params['name'])) {
1474 $ufGroup->name
= CRM_Utils_String
::munge($ufGroup->title
, '_', 56);
1476 $ufGroup->id
= $ufGroupID;
1480 if (!$ufGroupID && empty($params['name'])) {
1481 $ufGroup->name
= $ufGroup->name
. "_{$ufGroup->id}";
1489 * Make uf join entries for an uf group.
1491 * @param array $params
1492 * (reference) an assoc array of name/value pairs.
1493 * @param int $ufGroupId
1496 public static function createUFJoin(&$params, $ufGroupId) {
1497 $groupTypes = CRM_Utils_Array
::value('uf_group_type', $params);
1499 // get ufjoin records for uf group
1500 $ufGroupRecord = CRM_Core_BAO_UFGroup
::getUFJoinRecord($ufGroupId);
1502 // get the list of all ufgroup types
1503 $allUFGroupType = CRM_Core_SelectValues
::ufGroupTypes();
1505 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
1506 if (!is_array($groupTypes)) {
1507 $groupTypes = array();
1510 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
1511 if (!is_array($ufGroupRecord)) {
1512 $ufGroupRecord = array();
1515 // check which values has to be inserted/deleted for contact
1516 $menuRebuild = FALSE;
1517 foreach ($allUFGroupType as $key => $value) {
1518 $joinParams = array();
1519 $joinParams['uf_group_id'] = $ufGroupId;
1520 $joinParams['module'] = $key;
1521 if ($key == 'User Account') {
1522 $menuRebuild = TRUE;
1524 if (array_key_exists($key, $groupTypes) && !in_array($key, $ufGroupRecord)) {
1525 // insert a new record
1526 CRM_Core_BAO_UFGroup
::addUFJoin($joinParams);
1528 elseif (!array_key_exists($key, $groupTypes) && in_array($key, $ufGroupRecord)) {
1529 // delete a record for existing ufgroup
1530 CRM_Core_BAO_UFGroup
::delUFJoin($joinParams);
1536 UPDATE civicrm_uf_join
1538 WHERE uf_group_id = %2
1539 AND ( entity_id IS NULL OR entity_id <= 0 )
1542 1 => array($params['weight'], 'Integer'),
1543 2 => array($ufGroupId, 'Integer'),
1545 CRM_Core_DAO
::executeQuery($query, $p);
1547 // Do a menu rebuild, so it gets all the new menu entries for user account
1549 $config = CRM_Core_Config
::singleton();
1550 $config->userSystem
->updateCategories();
1555 * Get the UF Join records for an ufgroup id.
1557 * @param int $ufGroupId
1559 * @param int $displayName
1560 * If set return display name in array.
1561 * @param int $status
1562 * If set return module other than default modules (User Account/User registration/Profile).
1567 public static function getUFJoinRecord($ufGroupId = NULL, $displayName = NULL, $status = NULL) {
1569 $UFGroupType = array();
1570 $UFGroupType = CRM_Core_SelectValues
::ufGroupTypes();
1574 $dao = new CRM_Core_DAO_UFJoin();
1577 $dao->uf_group_id
= $ufGroupId;
1583 while ($dao->fetch()) {
1584 if (!$displayName) {
1585 $ufJoin[$dao->id
] = $dao->module
;
1588 if (isset($UFGroupType[$dao->module
])) {
1589 // skip the default modules
1591 $ufJoin[$dao->id
] = $UFGroupType[$dao->module
];
1593 // added for CRM-1475
1595 elseif (!CRM_Utils_Array
::key($dao->module
, $ufJoin)) {
1596 $ufJoin[$dao->id
] = $dao->module
;
1604 * Function takes an associative array and creates a ufjoin record for ufgroup.
1606 * @param array $params
1607 * (reference) an assoc array of name/value pairs.
1609 * @return CRM_Core_BAO_UFJoin
1611 public static function addUFJoin(&$params) {
1612 $ufJoin = new CRM_Core_DAO_UFJoin();
1613 $ufJoin->copyValues($params);
1619 * Delete the uf join record for an uf group.
1621 * @param array $params
1622 * (reference) an assoc array of name/value pairs.
1624 public static function delUFJoin(&$params) {
1625 $ufJoin = new CRM_Core_DAO_UFJoin();
1626 $ufJoin->copyValues($params);
1631 * Get the weight for ufjoin record.
1633 * @param int $ufGroupId
1634 * If $ufGroupId get update weight or add weight.
1637 * weight of the UFGroup
1639 public static function getWeight($ufGroupId = NULL) {
1640 //calculate the weight
1643 $queryString = "SELECT ( MAX(civicrm_uf_join.weight)+1) as new_weight
1644 FROM civicrm_uf_join
1645 WHERE module = 'User Registration' OR module = 'User Account' OR module = 'Profile'";
1648 $queryString = "SELECT MAX(civicrm_uf_join.weight) as new_weight
1649 FROM civicrm_uf_join
1650 WHERE civicrm_uf_join.uf_group_id = %1
1651 AND ( entity_id IS NULL OR entity_id <= 0 )";
1652 $p[1] = array($ufGroupId, 'Integer');
1655 $dao = CRM_Core_DAO
::executeQuery($queryString, $p);
1657 return ($dao->new_weight
) ?
$dao->new_weight
: 1;
1661 * Get the uf group for a module.
1663 * @param string $moduleName
1666 * No to increment the weight.
1667 * @param bool $skipPermission
1669 * Which operation (view, edit, create, etc) to check permission for.
1670 * @param array|NULL $returnFields list of UFGroup fields to return; NULL for default
1673 * array of ufgroups for a module
1675 public static function getModuleUFGroup($moduleName = NULL, $count = 0, $skipPermission = TRUE, $op = CRM_Core_Permission
::VIEW
, $returnFields = NULL) {
1676 $selectFields = array('id', 'title', 'created_id', 'is_active', 'is_reserved', 'group_type');
1678 if (CRM_Core_BAO_SchemaHandler
::checkIfFieldExists('civicrm_uf_group', 'description')) {
1679 // CRM-13555, since description field was added later (4.4), and to avoid any problems with upgrade
1680 $selectFields[] = 'description';
1683 if (CRM_Core_BAO_SchemaHandler
::checkIfFieldExists('civicrm_uf_group', 'frontend_title')) {
1684 $selectFields[] = 'frontend_title';
1687 if (!empty($returnFields)) {
1688 $selectFields = array_merge($returnFields, array_diff($selectFields, $returnFields));
1691 $queryString = 'SELECT civicrm_uf_group.' . implode(', civicrm_uf_group.', $selectFields) . '
1692 FROM civicrm_uf_group
1693 LEFT JOIN civicrm_uf_join ON (civicrm_uf_group.id = uf_group_id)';
1696 $queryString .= ' AND civicrm_uf_group.is_active = 1
1697 WHERE civicrm_uf_join.module = %2';
1698 $p[2] = array($moduleName, 'String');
1701 // add permissioning for profiles only if not registration
1702 if (!$skipPermission) {
1703 $permissionClause = CRM_Core_Permission
::ufGroupClause($op, 'civicrm_uf_group.');
1704 if (strpos($queryString, 'WHERE') !== FALSE) {
1705 $queryString .= " AND $permissionClause ";
1708 $queryString .= " $permissionClause ";
1712 $queryString .= ' ORDER BY civicrm_uf_join.weight, civicrm_uf_group.title';
1713 $dao = CRM_Core_DAO
::executeQuery($queryString, $p);
1715 $ufGroups = array();
1716 while ($dao->fetch()) {
1717 //skip mix profiles in user Registration / User Account
1718 if (($moduleName == 'User Registration' ||
$moduleName == 'User Account') &&
1719 CRM_Core_BAO_UFField
::checkProfileType($dao->id
)
1723 foreach ($selectFields as $key => $field) {
1724 if ($field == 'id') {
1727 $ufGroups[$dao->id
][$field] = $dao->$field;
1731 // Allow other modules to alter/override the UFGroups.
1732 CRM_Utils_Hook
::buildUFGroupsForModule($moduleName, $ufGroups);
1738 * Filter ufgroups based on logged in user contact type.
1740 * @param int $ufGroupId
1741 * Uf group id (profile id).
1742 * @param int $contactID
1747 public static function filterUFGroups($ufGroupId, $contactID = NULL) {
1749 $session = CRM_Core_Session
::singleton();
1750 $contactID = $session->get('userID');
1754 //get the contact type
1755 $contactType = CRM_Contact_BAO_Contact
::getContactType($contactID);
1757 //match if exixting contact type is same as profile contact type
1758 $profileType = CRM_Core_BAO_UFField
::getProfileType($ufGroupId);
1760 if (CRM_Contact_BAO_ContactType
::isaSubType($profileType)) {
1761 $profileType = CRM_Contact_BAO_ContactType
::getBasicType($profileType);
1763 //in some cases getBasicType() returns a cached array instead of string. Example: array ('sponsor' => 'organization')
1764 if (is_array($profileType)) {
1765 $profileType = array_shift($profileType);
1769 //allow special mix profiles for Contribution and Participant
1770 $specialProfiles = array('Contribution', 'Participant', 'Membership');
1772 if (in_array($profileType, $specialProfiles)) {
1776 if (($contactType == $profileType) ||
$profileType == 'Contact') {
1785 * Add profile field to a form.
1787 * @param CRM_Core_Form $form
1788 * @param array $field
1792 * @param int $contactId
1793 * @param bool $online
1794 * @param string $usedFor
1795 * For building up prefixed fieldname for special cases (e.g. onBehalf, Honor).
1796 * @param int $rowNumber
1797 * @param string $prefix
1801 public static function buildProfile(
1811 $defaultValues = array();
1812 $fieldName = $field['name'];
1813 $title = $field['title'];
1814 $attributes = $field['attributes'];
1815 $rule = $field['rule'];
1816 $view = $field['is_view'];
1817 $required = ($mode == CRM_Profile_Form
::MODE_SEARCH
) ?
FALSE : $field['is_required'];
1818 $search = ($mode == CRM_Profile_Form
::MODE_SEARCH
) ?
TRUE : FALSE;
1819 $isShared = CRM_Utils_Array
::value('is_shared', $field, 0);
1821 // do not display view fields in drupal registration form
1823 if ($view && $mode == CRM_Profile_Form
::MODE_REGISTER
) {
1827 if ($usedFor == 'onbehalf') {
1828 $name = "onbehalf[$fieldName]";
1830 elseif ($usedFor == 'honor') {
1831 $name = "honor[$fieldName]";
1833 elseif ($contactId && !$online) {
1834 $name = "field[$contactId][$fieldName]";
1836 elseif ($rowNumber) {
1837 $name = "field[$rowNumber][$fieldName]";
1839 elseif (!empty($prefix)) {
1840 $name = $prefix . "[$fieldName]";
1846 $selectAttributes = array('class' => 'crm-select2', 'placeholder' => TRUE);
1848 if ($fieldName == 'image_URL' && $mode == CRM_Profile_Form
::MODE_EDIT
) {
1849 $deleteExtra = json_encode(ts('Are you sure you want to delete contact image.'));
1851 CRM_Core_Action
::DELETE
=> array(
1852 'name' => ts('Delete Contact Image'),
1853 'url' => 'civicrm/contact/image',
1854 'qs' => 'reset=1&id=%%id%%&gid=%%gid%%&action=delete',
1855 'extra' => 'onclick = "' . htmlspecialchars("if (confirm($deleteExtra)) this.href+='&confirmed=1'; else return false;") . '"',
1858 $deleteURL = CRM_Core_Action
::formLink($deleteURL,
1859 CRM_Core_Action
::DELETE
,
1861 'id' => $form->get('id'),
1862 'gid' => $form->get('gid'),
1866 'contact.profileimage.delete',
1870 $form->assign('deleteURL', $deleteURL);
1872 $addressOptions = CRM_Core_BAO_Setting
::valueOptions(CRM_Core_BAO_Setting
::SYSTEM_PREFERENCES_NAME
,
1873 'address_options', TRUE, NULL, TRUE
1876 if (substr($fieldName, 0, 14) === 'state_province') {
1877 $form->addChainSelect($name, array('label' => $title, 'required' => $required));
1878 $config = CRM_Core_Config
::singleton();
1879 if (!in_array($mode, array(
1880 CRM_Profile_Form
::MODE_EDIT
,
1881 CRM_Profile_Form
::MODE_SEARCH
,
1883 $config->defaultContactStateProvince
1885 $defaultValues[$name] = $config->defaultContactStateProvince
;
1886 $form->setDefaults($defaultValues);
1889 elseif (substr($fieldName, 0, 7) === 'country') {
1890 $form->add('select', $name, $title, array('' => ts('- select -')) + CRM_Core_PseudoConstant
::country(), $required, $selectAttributes);
1891 $config = CRM_Core_Config
::singleton();
1892 if (!in_array($mode, array(
1893 CRM_Profile_Form
::MODE_EDIT
,
1894 CRM_Profile_Form
::MODE_SEARCH
,
1896 $config->defaultContactCountry
1898 $defaultValues[$name] = $config->defaultContactCountry
;
1899 $form->setDefaults($defaultValues);
1902 elseif (substr($fieldName, 0, 6) === 'county') {
1903 if ($addressOptions['county']) {
1904 $form->addChainSelect($name, array('label' => $title, 'required' => $required));
1907 elseif (substr($fieldName, 0, 9) === 'image_URL') {
1908 $form->add('file', $name, $title, $attributes, $required);
1909 $form->addUploadElement($name);
1911 elseif (substr($fieldName, 0, 2) === 'im') {
1912 $form->add('text', $name, $title, $attributes, $required);
1915 if (substr($name, -1) == ']') {
1916 $providerName = substr($name, 0, -1) . '-provider_id]';
1918 $form->add('select', $providerName, NULL,
1920 '' => ts('- select -'),
1921 ) + CRM_Core_PseudoConstant
::get('CRM_Core_DAO_IM', 'provider_id'), $required
1925 $form->add('select', $name . '-provider_id', $title,
1927 '' => ts('- select -'),
1928 ) + CRM_Core_PseudoConstant
::get('CRM_Core_DAO_IM', 'provider_id'), $required
1932 if ($view && $mode != CRM_Profile_Form
::MODE_SEARCH
) {
1933 $form->freeze($name . '-provider_id');
1937 elseif (CRM_Utils_Array
::value('name', $field) == 'membership_type') {
1938 list($orgInfo, $types) = CRM_Member_BAO_MembershipType
::getMembershipTypeInfo();
1939 $sel = &$form->addElement('hierselect', $name, $title);
1940 $select = array('' => ts('- select -'));
1941 if (count($orgInfo) == 1 && $field['is_required']) {
1942 // we only have one org - so we should default to it. Not sure about defaulting to first type
1943 // as it could be missed - so adding a select
1944 // however, possibly that is more similar to the membership form
1945 if (count($types[1]) > 1) {
1946 $types[1] = $select +
$types[1];
1950 $orgInfo = $select +
$orgInfo;
1952 $sel->setOptions(array($orgInfo, $types));
1954 elseif (CRM_Utils_Array
::value('name', $field) == 'membership_status') {
1955 $form->add('select', $name, $title,
1957 '' => ts('- select -'),
1958 ) + CRM_Member_PseudoConstant
::membershipStatus(NULL, NULL, 'label'), $required
1961 elseif (in_array($fieldName, array('gender_id', 'communication_style_id'))) {
1963 $pseudoValues = CRM_Core_PseudoConstant
::get('CRM_Contact_DAO_Contact', $fieldName);
1964 foreach ($pseudoValues as $key => $var) {
1965 $options[$key] = $form->createElement('radio', NULL, ts($title), $var, $key);
1967 $group = $form->addGroup($options, $name, $title);
1969 $form->addRule($name, ts('%1 is a required field.', array(1 => $title)), 'required');
1972 $group->setAttribute('allowClear', TRUE);
1975 elseif ($fieldName === 'prefix_id' ||
$fieldName === 'suffix_id') {
1976 $form->addSelect($name, array(
1978 'entity' => 'contact',
1979 'field' => $fieldName,
1981 'placeholder' => '',
1984 elseif ($fieldName === 'contact_sub_type') {
1985 $gId = $form->get('gid') ?
$form->get('gid') : CRM_Utils_Array
::value('group_id', $field);
1986 if ($usedFor == 'onbehalf') {
1987 $profileType = 'Organization';
1989 elseif ($usedFor == 'honor') {
1990 $profileType = CRM_Core_BAO_UFField
::getProfileType($form->_params
['honoree_profile_id']);
1993 $profileType = $gId ? CRM_Core_BAO_UFField
::getProfileType($gId) : NULL;
1994 if ($profileType == 'Contact') {
1995 $profileType = 'Individual';
1999 $setSubtype = FALSE;
2000 if (CRM_Contact_BAO_ContactType
::isaSubType($profileType)) {
2001 $setSubtype = $profileType;
2002 $profileType = CRM_Contact_BAO_ContactType
::getBasicType($profileType);
2005 $subtypes = $profileType ? CRM_Contact_BAO_ContactType
::subTypePairs($profileType) : array();
2008 $subtypeList = array();
2009 $subtypeList[$setSubtype] = $subtypes[$setSubtype];
2012 $subtypeList = $subtypes;
2015 $form->add('select', $name, $title, $subtypeList, $required, array('class' => 'crm-select2', 'multiple' => TRUE));
2017 elseif (in_array($fieldName, CRM_Contact_BAO_Contact
::$_greetingTypes)) {
2018 //add email greeting, postal greeting, addressee, CRM-4575
2019 $gId = $form->get('gid') ?
$form->get('gid') : CRM_Utils_Array
::value('group_id', $field);
2020 $profileType = CRM_Core_BAO_UFField
::getProfileType($gId, TRUE, FALSE, TRUE);
2022 if (empty($profileType) ||
in_array($profileType, array(
2029 $profileType = 'Individual';
2031 if (CRM_Contact_BAO_ContactType
::isaSubType($profileType)) {
2032 $profileType = CRM_Contact_BAO_ContactType
::getBasicType($profileType);
2035 'contact_type' => $profileType,
2036 'greeting_type' => $fieldName,
2038 $form->add('select', $name, $title,
2040 '' => ts('- select -'),
2041 ) + CRM_Core_PseudoConstant
::greeting($greeting), $required
2043 // add custom greeting element
2044 $form->add('text', $fieldName . '_custom', ts('Custom %1', array(1 => ucwords(str_replace('_', ' ', $fieldName)))),
2048 elseif ($fieldName === 'preferred_communication_method') {
2049 $communicationFields = CRM_Core_PseudoConstant
::get('CRM_Contact_DAO_Contact', 'preferred_communication_method');
2050 foreach ($communicationFields as $key => $var) {
2054 $communicationOptions[] = $form->createElement('checkbox', $key, NULL, $var);
2056 $form->addGroup($communicationOptions, $name, $title, '<br/>');
2058 elseif ($fieldName === 'preferred_mail_format') {
2059 $form->add('select', $name, $title, CRM_Core_SelectValues
::pmf());
2061 elseif ($fieldName === 'preferred_language') {
2062 $form->add('select', $name, $title, array('' => ts('- select -')) + CRM_Contact_BAO_Contact
::buildOptions('preferred_language'));
2064 elseif ($fieldName == 'external_identifier') {
2065 $form->add('text', $name, $title, $attributes, $required);
2066 $contID = $contactId;
2068 $contID = $form->get('id');
2070 $form->addRule($name,
2071 ts('External ID already exists in Database.'),
2073 array('CRM_Contact_DAO_Contact', $contID, 'external_identifier')
2076 elseif ($fieldName === 'group') {
2077 CRM_Contact_Form_Edit_TagsAndGroups
::buildQuickForm($form, $contactId,
2078 CRM_Contact_Form_Edit_TagsAndGroups
::GROUP
,
2083 elseif ($fieldName === 'tag') {
2084 CRM_Contact_Form_Edit_TagsAndGroups
::buildQuickForm($form, $contactId,
2085 CRM_Contact_Form_Edit_TagsAndGroups
::TAG
,
2090 elseif (substr($fieldName, 0, 4) === 'url-') {
2091 $form->add('text', $name, $title, CRM_Core_DAO
::getAttribute('CRM_Core_DAO_Website', 'url'), $required);
2092 $form->addRule($name, ts('Enter a valid web address beginning with \'http://\' or \'https://\'.'), 'url');
2094 // Note should be rendered as textarea
2095 elseif (substr($fieldName, -4) == 'note') {
2096 $form->add('textarea', $name, $title, $attributes, $required);
2098 elseif (substr($fieldName, 0, 6) === 'custom') {
2099 $customFieldID = CRM_Core_BAO_CustomField
::getKeyID($fieldName);
2100 if ($customFieldID) {
2101 CRM_Core_BAO_CustomField
::addQuickFormElement($form, $name, $customFieldID, $required, $search, $title);
2104 elseif (substr($fieldName, 0, 14) === 'address_custom') {
2105 list($fName, $locTypeId) = CRM_Utils_System
::explode('-', $fieldName, 2);
2106 $customFieldID = CRM_Core_BAO_CustomField
::getKeyID(substr($fName, 8));
2107 if ($customFieldID) {
2108 CRM_Core_BAO_CustomField
::addQuickFormElement($form, $name, $customFieldID, $required, $search, $title);
2111 elseif ($fieldName == 'send_receipt') {
2112 $form->addElement('checkbox', $name, $title);
2114 elseif ($fieldName == 'soft_credit') {
2115 $form->addEntityRef("soft_credit_contact_id[$rowNumber]", ts('Soft Credit To'), array('create' => TRUE));
2116 $form->addMoney("soft_credit_amount[{$rowNumber}]", ts('Amount'), FALSE, NULL, FALSE);
2118 elseif ($fieldName == 'product_name') {
2119 list($products, $options) = CRM_Contribute_BAO_Premium
::getPremiumProductInfo();
2120 $sel = &$form->addElement('hierselect', $name, $title);
2122 '0' => ts('- select -'),
2124 $sel->setOptions(array($products, $options));
2126 elseif ($fieldName == 'payment_instrument') {
2127 $form->add('select', $name, $title,
2128 array('' => ts('- select -')) + CRM_Contribute_PseudoConstant
::paymentInstrument(), $required);
2130 elseif ($fieldName == 'financial_type') {
2131 $form->add('select', $name, $title,
2133 '' => ts('- select -'),
2134 ) + CRM_Contribute_PseudoConstant
::financialType(), $required
2137 elseif ($fieldName == 'contribution_status_id') {
2138 $contributionStatuses = CRM_Contribute_PseudoConstant
::contributionStatus();
2139 $statusName = CRM_Contribute_PseudoConstant
::contributionStatus(NULL, 'name');
2145 unset($contributionStatuses[CRM_Utils_Array
::key($suppress, $statusName)]);
2148 $form->add('select', $name, $title,
2150 '' => ts('- select -'),
2151 ) +
$contributionStatuses, $required
2154 elseif ($fieldName == 'soft_credit_type') {
2155 $name = "soft_credit_type[$rowNumber]";
2156 $form->add('select', $name, $title,
2158 '' => ts('- select -'),
2159 ) + CRM_Core_OptionGroup
::values("soft_credit_type")
2161 //CRM-15350: choose SCT field default value as 'Gift' for membership use
2162 //else (for contribution), use configured SCT default value
2163 $SCTDefaultValue = CRM_Core_OptionGroup
::getDefaultValue("soft_credit_type");
2164 if ($field['field_type'] == 'Membership') {
2165 $SCTDefaultValue = CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_ContributionSoft', 'soft_credit_type_id', 'gift');
2167 $form->addElement('hidden', 'sct_default_id', $SCTDefaultValue, array('id' => 'sct_default_id'));
2169 elseif ($fieldName == 'contribution_soft_credit_pcp_id') {
2170 CRM_Contribute_Form_SoftCredit
::addPCPFields($form, "[$rowNumber]");
2172 elseif ($fieldName == 'currency') {
2173 $form->addCurrency($name, $title, $required, NULL, FALSE, FALSE);
2175 elseif ($fieldName == 'contribution_page_id') {
2176 $form->add('select', $name, $title,
2178 '' => ts('- select -'),
2179 ) + CRM_Contribute_PseudoConstant
::contributionPage(), $required, 'class="big"'
2182 elseif ($fieldName == 'activity_status_id') {
2183 $form->add('select', $name, $title,
2185 '' => ts('- select -'),
2186 ) + CRM_Core_PseudoConstant
::activityStatus(), $required
2189 elseif ($fieldName == 'activity_engagement_level') {
2190 $form->add('select', $name, $title,
2192 '' => ts('- select -'),
2193 ) + CRM_Campaign_PseudoConstant
::engagementLevel(), $required
2196 elseif ($fieldName == 'participant_status') {
2198 if ($online == TRUE) {
2199 $cond = 'visibility_id = 1';
2201 $form->add('select', $name, $title,
2203 '' => ts('- select -'),
2204 ) + CRM_Event_PseudoConstant
::participantStatus(NULL, $cond, 'label'), $required
2207 elseif ($fieldName == 'participant_role') {
2208 if (!empty($field['is_multiple'])) {
2209 $form->addCheckBox($name, $title, CRM_Event_PseudoConstant
::participantRole(), NULL, NULL, NULL, NULL, ' ', TRUE);
2212 $form->add('select', $name, $title,
2214 '' => ts('- select -'),
2215 ) + CRM_Event_PseudoConstant
::participantRole(), $required
2219 elseif ($fieldName == 'world_region') {
2220 $form->add('select', $name, $title, CRM_Core_PseudoConstant
::worldRegion(), $required, $selectAttributes);
2222 elseif ($fieldName == 'signature_html') {
2223 $form->add('wysiwyg', $name, $title, CRM_Core_DAO
::getAttribute('CRM_Core_DAO_Email', $fieldName));
2225 elseif ($fieldName == 'signature_text') {
2226 $form->add('textarea', $name, $title, CRM_Core_DAO
::getAttribute('CRM_Core_DAO_Email', $fieldName));
2228 elseif (substr($fieldName, -11) == 'campaign_id') {
2229 if (CRM_Campaign_BAO_Campaign
::isCampaignEnable()) {
2230 $campaigns = CRM_Campaign_BAO_Campaign
::getCampaigns(CRM_Utils_Array
::value($contactId,
2231 $form->_componentCampaigns
2233 $form->add('select', $name, $title,
2235 '' => ts('- select -'),
2236 ) +
$campaigns, $required, 'class="crm-select2 big"'
2240 elseif ($fieldName == 'activity_details') {
2241 $form->add('wysiwyg', $fieldName, $title, array('rows' => 4, 'cols' => 60), $required);
2243 elseif ($fieldName == 'activity_duration') {
2244 $form->add('text', $name, $title, $attributes, $required);
2245 $form->addRule($name, ts('Please enter the duration as number of minutes (integers only).'), 'positiveInteger');
2247 elseif ($fieldName == 'case_status') {
2248 $form->add('select', $name, $title,
2250 '' => ts('- select -'),
2251 ) + CRM_Case_BAO_Case
::buildOptions('case_status_id', 'create'),
2256 if (substr($fieldName, 0, 3) === 'is_' or substr($fieldName, 0, 7) === 'do_not_') {
2257 $form->add('advcheckbox', $name, $title, $attributes, $required);
2259 elseif (CRM_Utils_Array
::value('html_type', $field) === 'Select Date') {
2260 $extra = isset($field['datepicker']) ?
$field['datepicker']['extra'] : CRM_Utils_Date
::getDatePickerExtra($field);
2261 $attributes = isset($field['datepicker']) ?
$field['datepicker']['attributes'] : CRM_Utils_Date
::getDatePickerAttributes($field);
2262 $form->add('datepicker', $name, $title, $attributes, $required, $extra);
2265 $form->add('text', $name, $title, $attributes, $required);
2269 static $hiddenSubtype = FALSE;
2270 if (!$hiddenSubtype && CRM_Contact_BAO_ContactType
::isaSubType($field['field_type'])) {
2271 // In registration mode params are submitted via POST and we don't have any clue
2272 // about profile-id or the profile-type (which could be a subtype)
2273 // To generalize the behavior and simplify the process,
2274 // lets always add the hidden
2275 //subtype value if there is any, and we won't have to
2276 // compute it while processing.
2278 $form->addElement('hidden', $usedFor . '[contact_sub_type]', $field['field_type']);
2281 $form->addElement('hidden', 'contact_sub_type_hidden', $field['field_type']);
2283 $hiddenSubtype = TRUE;
2286 if (($view && $mode != CRM_Profile_Form
::MODE_SEARCH
) ||
$isShared) {
2287 $form->freeze($name);
2291 if (in_array($fieldName, array(
2292 'non_deductible_amount',
2297 $form->addRule($name, ts('Please enter a valid amount.'), 'money');
2300 if (!($rule == 'email' && $mode == CRM_Profile_Form
::MODE_SEARCH
)) {
2301 $form->addRule($name, ts('Please enter a valid %1', array(1 => $title)), $rule);
2307 * Set profile defaults.
2309 * @param int $contactId
2311 * @param array $fields
2312 * Associative array of fields.
2313 * @param array $defaults
2315 * @param bool $singleProfile
2316 * True for single profile else false(Update multiple items).
2317 * @param int $componentId
2318 * Id for specific components like contribute, event etc.
2319 * @param null $component
2321 public static function setProfileDefaults(
2322 $contactId, &$fields, &$defaults,
2323 $singleProfile = TRUE, $componentId = NULL, $component = NULL
2325 if (!$componentId) {
2326 //get the contact details
2327 list($contactDetails, $options) = CRM_Contact_BAO_Contact
::getHierContactDetails($contactId, $fields);
2328 $details = CRM_Utils_Array
::value($contactId, $contactDetails);
2329 $multipleFields = array('website' => 'url');
2331 //start of code to set the default values
2332 foreach ($fields as $name => $field) {
2333 // skip pseudo fields
2334 if (substr($name, 0, 9) == 'phone_ext') {
2338 //set the field name depending upon the profile mode(single/multiple)
2339 if ($singleProfile) {
2343 $fldName = "field[$contactId][$name]";
2346 if ($name == 'group') {
2347 CRM_Contact_Form_Edit_TagsAndGroups
::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups
::GROUP
, $fldName);
2349 if ($name == 'tag') {
2350 CRM_Contact_Form_Edit_TagsAndGroups
::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups
::TAG
, $fldName);
2353 if (!empty($details[$name]) ||
isset($details[$name])) {
2354 //to handle custom data (checkbox) to be written
2355 // to handle birth/deceased date, greeting_type and few other fields
2356 if (in_array($name, CRM_Contact_BAO_Contact
::$_greetingTypes)) {
2357 $defaults[$fldName] = $details[$name . '_id'];
2358 $defaults[$name . '_custom'] = $details[$name . '_custom'];
2360 elseif ($name == 'preferred_communication_method') {
2361 $v = $details[$name];
2362 if (!is_array($details[$name])) {
2363 $v = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $v);
2365 foreach ($v as $item) {
2367 $defaults[$fldName . "[$item]"] = 1;
2371 elseif ($name == 'contact_sub_type') {
2372 $defaults[$fldName] = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, trim($details[$name], CRM_Core_DAO
::VALUE_SEPARATOR
));
2374 elseif ($name == 'world_region') {
2375 $defaults[$fldName] = $details['worldregion_id'];
2377 elseif ($customFieldId = CRM_Core_BAO_CustomField
::getKeyID($name)) {
2378 // @todo retrieving the custom fields here seems obsolete - $field holds more data for the fields.
2379 $customFields = CRM_Core_BAO_CustomField
::getFields(CRM_Utils_Array
::value('contact_type', $details));
2381 // hack to add custom data for components
2382 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
2383 foreach ($components as $value) {
2384 $customFields = CRM_Utils_Array
::crmArrayMerge($customFields,
2385 CRM_Core_BAO_CustomField
::getFieldsForImport($value)
2389 switch ($customFields[$customFieldId]['html_type']) {
2390 case 'Multi-Select State/Province':
2391 case 'Multi-Select Country':
2392 case 'Multi-Select':
2393 $v = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $details[$name]);
2394 foreach ($v as $item) {
2396 $defaults[$fldName][$item] = $item;
2402 $v = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $details[$name]);
2403 foreach ($v as $item) {
2405 $defaults[$fldName][$item] = 1;
2406 // seems like we need this for QF style checkboxes in profile where its multiindexed
2408 $defaults["{$fldName}[{$item}]"] = 1;
2414 $defaults[$fldName] = $details[$name];
2419 $defaults[$fldName] = $details[$name];
2423 $blocks = array('email', 'phone', 'im', 'openid');
2424 list($fieldName, $locTypeId, $phoneTypeId) = CRM_Utils_System
::explode('-', $name, 3);
2425 if (!in_array($fieldName, $multipleFields)) {
2426 if (is_array($details)) {
2427 foreach ($details as $key => $value) {
2428 // when we fixed CRM-5319 - get primary loc
2429 // type as per loc field and removed below code.
2430 $primaryLocationType = FALSE;
2431 if ($locTypeId == 'Primary') {
2432 if (is_array($value) && array_key_exists($fieldName, $value)) {
2433 $primaryLocationType = TRUE;
2434 if (in_array($fieldName, $blocks)) {
2435 $locTypeId = CRM_Contact_BAO_Contact
::getPrimaryLocationType($contactId, FALSE, $fieldName);
2438 $locTypeId = CRM_Contact_BAO_Contact
::getPrimaryLocationType($contactId, FALSE, 'address');
2443 // fixed for CRM-665
2444 if (is_numeric($locTypeId)) {
2445 if ($primaryLocationType ||
$locTypeId == CRM_Utils_Array
::value('location_type_id', $value)) {
2446 if (!empty($value[$fieldName])) {
2447 //to handle stateprovince and country
2448 if ($fieldName == 'state_province') {
2449 $defaults[$fldName] = $value['state_province_id'];
2451 elseif ($fieldName == 'county') {
2452 $defaults[$fldName] = $value['county_id'];
2454 elseif ($fieldName == 'country') {
2455 if (!isset($value['country_id']) ||
!$value['country_id']) {
2456 $config = CRM_Core_Config
::singleton();
2457 if ($config->defaultContactCountry
) {
2458 $defaults[$fldName] = $config->defaultContactCountry
;
2462 $defaults[$fldName] = $value['country_id'];
2465 elseif ($fieldName == 'phone') {
2467 if (isset($value['phone'][$phoneTypeId])) {
2468 $defaults[$fldName] = $value['phone'][$phoneTypeId];
2470 if (isset($value['phone_ext'][$phoneTypeId])) {
2471 $defaults[str_replace('phone', 'phone_ext', $fldName)] = $value['phone_ext'][$phoneTypeId];
2475 $phoneDefault = CRM_Utils_Array
::value('phone', $value);
2477 if (!is_array($phoneDefault)) {
2478 $defaults[$fldName] = $phoneDefault;
2482 elseif ($fieldName == 'email') {
2483 //adding the first email (currently we don't support multiple emails of same location type)
2484 $defaults[$fldName] = $value['email'];
2486 elseif ($fieldName == 'im') {
2487 //adding the first im (currently we don't support multiple ims of same location type)
2488 $defaults[$fldName] = $value['im'];
2489 $defaults[$fldName . '-provider_id'] = $value['im_provider_id'];
2492 $defaults[$fldName] = $value[$fieldName];
2495 elseif (substr($fieldName, 0, 14) === 'address_custom' &&
2496 CRM_Utils_Array
::value(substr($fieldName, 8), $value)
2498 $defaults[$fldName] = $value[substr($fieldName, 8)];
2506 if (is_array($details)) {
2507 if ($fieldName === 'url'
2508 && !empty($details['website'])
2509 && !empty($details['website'][$locTypeId])
2511 $defaults[$fldName] = CRM_Utils_Array
::value('url', $details['website'][$locTypeId]);
2519 // Handling Contribution Part of the batch profile
2520 if (CRM_Core_Permission
::access('CiviContribute') && $component == 'Contribute') {
2521 self
::setComponentDefaults($fields, $componentId, $component, $defaults);
2524 // Handling Event Participation Part of the batch profile
2525 if (CRM_Core_Permission
::access('CiviEvent') && $component == 'Event') {
2526 self
::setComponentDefaults($fields, $componentId, $component, $defaults);
2529 // Handling membership Part of the batch profile
2530 if (CRM_Core_Permission
::access('CiviMember') && $component == 'Membership') {
2531 self
::setComponentDefaults($fields, $componentId, $component, $defaults);
2534 // Handling Activity Part of the batch profile
2535 if ($component == 'Activity') {
2536 self
::setComponentDefaults($fields, $componentId, $component, $defaults);
2539 // Handling Case Part of the batch profile
2540 if (CRM_Core_Permission
::access('CiviCase') && $component == 'Case') {
2541 self
::setComponentDefaults($fields, $componentId, $component, $defaults);
2546 * Get profiles by type eg: pure Individual etc
2548 * @param array $types
2549 * Associative array of types eg: types('Individual').
2550 * @param bool $onlyPure
2551 * True if only pure profiles are required.
2554 * associative array of profiles
2556 public static function getProfiles($types, $onlyPure = FALSE) {
2557 $profiles = array();
2558 $ufGroups = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_UFField', 'uf_group_id');
2560 CRM_Utils_Hook
::aclGroup(CRM_Core_Permission
::ADMIN
, NULL, 'civicrm_uf_group', $ufGroups, $ufGroups);
2562 // Exclude Batch Data Entry profiles - CRM-10901
2563 $batchProfiles = CRM_Core_BAO_UFGroup
::getBatchProfiles();
2565 foreach ($ufGroups as $id => $title) {
2566 $ptype = CRM_Core_BAO_UFField
::getProfileType($id, FALSE, $onlyPure);
2567 if (in_array($ptype, $types) && !array_key_exists($id, $batchProfiles)) {
2568 $profiles[$id] = $title;
2575 * Check whether a profile is valid combination of
2576 * required and/or optional profile types
2578 * @param array $required
2579 * Array of types those are required.
2580 * @param array $optional
2581 * Array of types those are optional.
2584 * associative array of profiles
2586 public static function getValidProfiles($required, $optional = NULL) {
2587 if (!is_array($required) ||
empty($required)) {
2591 $profiles = array();
2592 $ufGroups = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_UFField', 'uf_group_id');
2594 CRM_Utils_Hook
::aclGroup(CRM_Core_Permission
::ADMIN
, NULL, 'civicrm_uf_group', $ufGroups, $ufGroups);
2596 foreach ($ufGroups as $id => $title) {
2597 $type = CRM_Core_BAO_UFField
::checkValidProfileType($id, $required, $optional);
2599 $profiles[$id] = $title;
2607 * Check whether a profile is valid combination of
2608 * required profile fields
2610 * @param array $ufId
2611 * Integer id of the profile.
2612 * @param array $required
2613 * Array of fields those are required in the profile.
2616 * associative array of profiles
2618 public static function checkValidProfile($ufId, $required = NULL) {
2619 $validProfile = FALSE;
2621 return $validProfile;
2624 if (!CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $ufId, 'is_active')) {
2625 return $validProfile;
2628 $profileFields = self
::getFields($ufId, FALSE, CRM_Core_Action
::VIEW
, NULL,
2629 NULL, FALSE, NULL, FALSE, NULL,
2630 CRM_Core_Permission
::CREATE
, NULL
2633 $validProfile = array();
2634 if (!empty($profileFields)) {
2635 $fields = array_keys($profileFields);
2636 foreach ($fields as $val) {
2637 foreach ($required as $key => $field) {
2638 if (strpos($val, $field) === 0) {
2639 unset($required[$key]);
2644 $validProfile = (empty($required)) ?
TRUE : FALSE;
2647 return $validProfile;
2651 * Get default value for Register.
2653 * @param array $fields
2654 * @param array $defaults
2658 public static function setRegisterDefaults(&$fields, &$defaults) {
2659 $config = CRM_Core_Config
::singleton();
2660 foreach ($fields as $name => $field) {
2661 if (substr($name, 0, 8) == 'country-') {
2662 if (!empty($config->defaultContactCountry
)) {
2663 $defaults[$name] = $config->defaultContactCountry
;
2666 elseif (substr($name, 0, 15) == 'state_province-') {
2667 if (!empty($config->defaultContactStateProvince
)) {
2668 $defaults[$name] = $config->defaultContactStateProvince
;
2676 * make a copy of a profile, including
2677 * all the fields in the profile
2680 * The profile id to copy.
2682 * @return \CRM_Core_DAO
2684 public static function copy($id) {
2685 $maxId = CRM_Core_DAO
::singleValueQuery("SELECT max(id) FROM civicrm_uf_group");
2687 $title = ts('[Copy id %1]', array(1 => $maxId +
1));
2690 'title' => ' ' . $title,
2691 'name' => '__Copy_id_' . ($maxId +
1) . '_',
2695 $copy = &CRM_Core_DAO
::copyGeneric('CRM_Core_DAO_UFGroup',
2701 if ($pos = strrpos($copy->name
, "_{$id}")) {
2702 $copy->name
= substr_replace($copy->name
, '', $pos);
2704 $copy->name
= CRM_Utils_String
::munge($copy->name
, '_', 56) . "_{$copy->id}";
2707 $copyUFJoin = &CRM_Core_DAO
::copyGeneric('CRM_Core_DAO_UFJoin',
2708 array('uf_group_id' => $id),
2709 array('uf_group_id' => $copy->id
),
2714 $copyUFField = &CRM_Core_DAO
::copyGeneric('CRM_Core_BAO_UFField',
2715 array('uf_group_id' => $id),
2716 array('uf_group_id' => $copy->id
)
2719 $maxWeight = CRM_Utils_Weight
::getMax('CRM_Core_DAO_UFJoin', NULL, 'weight');
2723 UPDATE civicrm_uf_join
2725 WHERE uf_group_id = %2
2726 AND ( entity_id IS NULL OR entity_id <= 0 )
2729 1 => array($maxWeight +
1, 'Integer'),
2730 2 => array($copy->id
, 'Integer'),
2732 CRM_Core_DAO
::executeQuery($query, $p);
2733 if ($copy->is_reserved
) {
2734 $query = "UPDATE civicrm_uf_group SET is_reserved = 0 WHERE id = %1";
2735 $params = array(1 => array($copy->id
, 'Integer'));
2736 CRM_Core_DAO
::executeQuery($query, $params);
2738 CRM_Utils_Hook
::copy('UFGroup', $copy);
2744 * Process that send notification e-mails
2746 * @param int $contactID
2748 * @param array $values
2749 * Associative array of name/value pair.
2751 public static function commonSendMail($contactID, &$values) {
2752 if (!$contactID ||
!$values) {
2756 $template = CRM_Core_Smarty
::singleton();
2758 $displayName = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_Contact',
2763 self
::profileDisplay($values['id'], $values['values'], $template);
2764 $emailList = explode(',', $values['email']);
2766 $contactLink = CRM_Utils_System
::url('civicrm/contact/view',
2767 "reset=1&cid=$contactID",
2768 TRUE, NULL, FALSE, FALSE, TRUE
2771 //get the default domain email address.
2772 list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain
::getNameAndEmail();
2774 if (!$domainEmailAddress ||
$domainEmailAddress == 'info@EXAMPLE.ORG') {
2775 $fixUrl = CRM_Utils_System
::url('civicrm/admin/domain', 'action=update&reset=1');
2776 CRM_Core_Error
::fatal(ts('The site administrator needs to enter a valid \'FROM Email Address\' in <a href="%1">Administer CiviCRM » Communications » FROM Email Addresses</a>. The email address used may need to be a valid mail account with your email service provider.', array(1 => $fixUrl)));
2779 foreach ($emailList as $emailTo) {
2780 // FIXME: take the below out of the foreach loop
2781 CRM_Core_BAO_MessageTemplate
::sendTemplate(
2783 'groupName' => 'msg_tpl_workflow_uf',
2784 'valueName' => 'uf_notify',
2785 'contactId' => $contactID,
2786 'tplParams' => array(
2787 'displayName' => $displayName,
2788 'currentDate' => date('r'),
2789 'contactLink' => $contactLink,
2791 'from' => "$domainEmailName <$domainEmailAddress>",
2792 'toEmail' => $emailTo,
2799 * Given a contact id and a group id, returns the field values from the db
2800 * for this group and notify email only if group's notify field is
2801 * set and field values are not empty
2807 * @param array $params
2808 * @param bool $skipCheck
2812 public function checkFieldsEmptyValues($gid, $cid, $params, $skipCheck = FALSE) {
2814 if (CRM_Core_BAO_UFGroup
::filterUFGroups($gid, $cid) ||
$skipCheck) {
2816 $fields = CRM_Core_BAO_UFGroup
::getFields($gid, FALSE, CRM_Core_Action
::VIEW
);
2817 CRM_Core_BAO_UFGroup
::getValues($cid, $fields, $values, FALSE, $params, TRUE);
2819 $email = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'notify');
2821 if (!empty($values) &&
2826 'values' => $values,
2837 * Assign uf fields to template.
2841 * @param array $values
2842 * @param CRM_Core_Smarty $template
2844 static public function profileDisplay($gid, $values, $template) {
2845 $groupTitle = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'title');
2846 $template->assign('grouptitle', $groupTitle);
2847 if (count($values)) {
2848 $template->assign('values', $values);
2853 * Format fields for dupe Contact Matching.
2855 * @param array $params
2857 * @param int $contactId
2860 * associated formatted array
2862 public static function formatFields($params, $contactId = NULL) {
2864 // get the primary location type id and email
2865 list($name, $primaryEmail, $primaryLocationType) = CRM_Contact_BAO_Contact_Location
::getEmailDetails($contactId);
2868 $defaultLocationType = CRM_Core_BAO_LocationType
::getDefault();
2869 $primaryLocationType = $defaultLocationType->id
;
2873 $locationType = array();
2875 $primaryLocation = 0;
2876 foreach ($params as $key => $value) {
2877 list($fieldName, $locTypeId, $phoneTypeId) = explode('-', $key);
2879 if ($locTypeId == 'Primary') {
2880 $locTypeId = $primaryLocationType;
2883 if (is_numeric($locTypeId)) {
2884 if (!in_array($locTypeId, $locationType)) {
2885 $locationType[$count] = $locTypeId;
2888 $loc = CRM_Utils_Array
::key($locTypeId, $locationType);
2890 $data['location'][$loc]['location_type_id'] = $locTypeId;
2892 // if we are getting in a new primary email, dont overwrite the new one
2893 if ($locTypeId == $primaryLocationType) {
2894 if (!empty($params['email-' . $primaryLocationType])) {
2895 $data['location'][$loc]['email'][$loc]['email'] = $fields['email-' . $primaryLocationType];
2897 elseif (isset($primaryEmail)) {
2898 $data['location'][$loc]['email'][$loc]['email'] = $primaryEmail;
2904 $data['location'][$loc]['is_primary'] = 1;
2906 if ($fieldName == 'phone') {
2908 $data['location'][$loc]['phone'][$loc]['phone_type_id'] = $phoneTypeId;
2911 $data['location'][$loc]['phone'][$loc]['phone_type_id'] = '';
2913 $data['location'][$loc]['phone'][$loc]['phone'] = $value;
2915 elseif ($fieldName == 'email') {
2916 $data['location'][$loc]['email'][$loc]['email'] = $value;
2918 elseif ($fieldName == 'im') {
2919 $data['location'][$loc]['im'][$loc]['name'] = $value;
2922 if ($fieldName === 'state_province') {
2923 $data['location'][$loc]['address']['state_province_id'] = $value;
2925 elseif ($fieldName === 'country') {
2926 $data['location'][$loc]['address']['country_id'] = $value;
2929 $data['location'][$loc]['address'][$fieldName] = $value;
2934 // TODO: prefix, suffix and gender translation may no longer be necessary - check inputs
2935 if ($key === 'individual_suffix') {
2936 $data['suffix_id'] = $value;
2938 elseif ($key === 'individual_prefix') {
2939 $data['prefix_id'] = $value;
2941 elseif ($key === 'gender') {
2942 $data['gender_id'] = $value;
2944 elseif (substr($key, 0, 6) === 'custom') {
2945 if ($customFieldID = CRM_Core_BAO_CustomField
::getKeyID($key)) {
2947 if ($customFields[$customFieldID]['html_type'] == 'CheckBox') {
2948 $value = implode(CRM_Core_DAO
::VALUE_SEPARATOR
, array_keys($value));
2950 // fix the date field
2951 if ($customFields[$customFieldID]['data_type'] == 'Date') {
2952 $date = CRM_Utils_Date
::format($value);
2959 $data['custom'][$customFieldID] = array(
2962 'extends' => $customFields[$customFieldID]['extends'],
2963 'type' => $customFields[$customFieldID]['data_type'],
2964 'custom_field_id' => $customFieldID,
2968 elseif ($key == 'edit') {
2972 $data[$key] = $value;
2977 if (!$primaryLocation) {
2979 $data['location'][$loc]['email'][$loc]['email'] = $primaryEmail;
2986 * Calculate the profile type 'group_type' as per profile fields.
2990 * @param bool $includeTypeValues
2991 * @param int $ignoreFieldId
2992 * Ignore particular profile field.
2995 * list of calculated group type
2997 public static function calculateGroupType($gId, $includeTypeValues = FALSE, $ignoreFieldId = NULL) {
2998 //get the profile fields.
2999 $ufFields = self
::getFields($gId, FALSE, NULL, NULL, NULL, TRUE, NULL, TRUE);
3000 return self
::_calculateGroupType($ufFields, $includeTypeValues, $ignoreFieldId);
3004 * Calculate the profile type 'group_type' as per profile fields.
3007 * @param bool $includeTypeValues
3008 * @param int $ignoreFieldId
3009 * Ignore perticular profile field.
3012 * list of calculated group type
3014 public static function _calculateGroupType($ufFields, $includeTypeValues = FALSE, $ignoreFieldId = NULL) {
3015 $groupType = $groupTypeValues = $customFieldIds = array();
3016 if (!empty($ufFields)) {
3017 foreach ($ufFields as $fieldName => $fieldValue) {
3018 //ignore field from group type when provided.
3019 //in case of update profile field.
3020 if ($ignoreFieldId && ($ignoreFieldId == $fieldValue['field_id'])) {
3023 if (!in_array($fieldValue['field_type'], $groupType)) {
3024 $groupType[$fieldValue['field_type']] = $fieldValue['field_type'];
3027 if ($includeTypeValues && ($fldId = CRM_Core_BAO_CustomField
::getKeyID($fieldName))) {
3028 $customFieldIds[$fldId] = $fldId;
3033 if (!empty($customFieldIds)) {
3034 $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) . ')';
3036 $customGroups = CRM_Core_DAO
::executeQuery($query);
3037 while ($customGroups->fetch()) {
3038 if (!$customGroups->extends_entity_column_value
) {
3042 $groupTypeName = "{$customGroups->extends}Type";
3043 if ($customGroups->extends == 'Participant' && $customGroups->extends_entity_column_id
) {
3044 $groupTypeName = CRM_Core_PseudoConstant
::getName('CRM_Core_DAO_CustomGroup', 'extends_entity_column_id', $customGroups->extends_entity_column_id
);
3047 foreach (explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $customGroups->extends_entity_column_value
) as $val) {
3049 $groupTypeValues[$groupTypeName][$val] = $val;
3054 if (!empty($groupTypeValues)) {
3055 $groupType = array_merge($groupType, $groupTypeValues);
3063 * Update the profile type 'group_type' as per profile fields including group types and group subtype values.
3064 * Build and store string like: group_type1,group_type2[VALUE_SEPERATOR]group_type1Type:1:2:3,group_type2Type:1:2
3067 * BirthDate + Email Individual,Contact
3068 * BirthDate + Subject Individual,Activity
3069 * BirthDate + Subject + SurveyOnlyField Individual,Activity\0ActivityType:28
3070 * BirthDate + Subject + SurveyOnlyField + PhoneOnlyField (Not allowed)
3071 * BirthDate + SurveyOnlyField Individual,Activity\0ActivityType:28
3072 * BirthDate + Subject + SurveyOrPhoneField Individual,Activity\0ActivityType:2:28
3073 * BirthDate + SurveyOrPhoneField Individual,Activity\0ActivityType:2:28
3074 * BirthDate + SurveyOrPhoneField + SurveyOnlyField Individual,Activity\0ActivityType:2:28
3075 * BirthDate + StudentField + Subject + SurveyOnlyField Individual,Activity,Student\0ActivityType:28
3078 * @param array $groupTypes
3079 * With key having group type names.
3083 public static function updateGroupTypes($gId, $groupTypes = array()) {
3084 if (!is_array($groupTypes) ||
!$gId) {
3088 // If empty group types set group_type as 'null'
3089 if (empty($groupTypes)) {
3090 return CRM_Core_DAO
::setFieldValue('CRM_Core_DAO_UFGroup', $gId, 'group_type', 'null');
3093 $componentGroupTypes = array('Contribution', 'Participant', 'Membership', 'Activity', 'Case');
3094 $validGroupTypes = array_merge(array(
3099 ), $componentGroupTypes, CRM_Contact_BAO_ContactType
::subTypes());
3101 $gTypes = $gTypeValues = array();
3103 $participantExtends = array('ParticipantRole', 'ParticipantEventName', 'ParticipantEventType');
3104 // Get valid group type and group subtypes
3105 foreach ($groupTypes as $groupType => $value) {
3106 if (in_array($groupType, $validGroupTypes) && !in_array($groupType, $gTypes)) {
3107 $gTypes[] = $groupType;
3112 if (in_array($groupType, $participantExtends)) {
3113 $subTypesOf = $groupType;
3115 elseif (strpos($groupType, 'Type') > 0) {
3116 $subTypesOf = substr($groupType, 0, strpos($groupType, 'Type'));
3122 if (!empty($value) &&
3123 (in_array($subTypesOf, $componentGroupTypes) ||
3124 in_array($subTypesOf, $participantExtends)
3127 $gTypeValues[$subTypesOf] = $groupType . ":" . implode(':', $value);
3131 if (empty($gTypes)) {
3135 // Build String to store group types and group subtypes
3136 $groupTypeString = implode(',', $gTypes);
3137 if (!empty($gTypeValues)) {
3138 $groupTypeString .= CRM_Core_DAO
::VALUE_SEPARATOR
. implode(',', $gTypeValues);
3141 return CRM_Core_DAO
::setFieldValue('CRM_Core_DAO_UFGroup', $gId, 'group_type', $groupTypeString);
3145 * Create a "group_type" string.
3147 * @param array $coreTypes
3148 * E.g. array('Individual','Contact','Student').
3149 * @param array $subTypes
3150 * E.g. array('ActivityType' => array(7, 11)).
3151 * @param string $delim
3154 * @throws CRM_Core_Exception
3156 public static function encodeGroupType($coreTypes, $subTypes, $delim = CRM_Core_DAO
::VALUE_SEPARATOR
) {
3157 $groupTypeExpr = '';
3159 $groupTypeExpr .= implode(',', $coreTypes);
3162 //CRM-15427 Allow Multiple subtype filtering
3163 //if (count($subTypes) > 1) {
3164 //throw new CRM_Core_Exception("Multiple subtype filtering is not currently supported by widget.");
3166 foreach ($subTypes as $subType => $subTypeIds) {
3167 $groupTypeExpr .= $delim . $subType . ':' . implode(':', $subTypeIds);
3170 return $groupTypeExpr;
3174 * setDefault componet specific profile fields.
3176 * @param array $fields
3178 * @param int $componentId
3180 * @param string $component
3182 * @param array $defaults
3183 * An array of default values.
3185 * @param bool $isStandalone
3187 public static function setComponentDefaults(&$fields, $componentId, $component, &$defaults, $isStandalone = FALSE) {
3188 if (!$componentId ||
3189 !in_array($component, array('Contribute', 'Membership', 'Event', 'Activity', 'Case'))
3194 $componentBAO = $componentSubType = NULL;
3195 switch ($component) {
3197 $componentBAO = 'CRM_Member_BAO_Membership';
3198 $componentBAOName = 'Membership';
3199 $componentSubType = array('membership_type_id');
3203 $componentBAO = 'CRM_Contribute_BAO_Contribution';
3204 $componentBAOName = 'Contribution';
3205 $componentSubType = array('financial_type_id');
3209 $componentBAO = 'CRM_Event_BAO_Participant';
3210 $componentBAOName = 'Participant';
3211 $componentSubType = array('role_id', 'event_id', 'event_type_id');
3215 $componentBAO = 'CRM_Activity_BAO_Activity';
3216 $componentBAOName = 'Activity';
3217 $componentSubType = array('activity_type_id');
3221 $componentBAO = 'CRM_Case_BAO_Case';
3222 $componentBAOName = 'Case';
3223 $componentSubType = array('case_type_id');
3228 $params = array('id' => $componentId);
3230 //get the component values.
3231 CRM_Core_DAO
::commonRetrieve($componentBAO, $params, $values);
3232 if ($componentBAOName == 'Participant') {
3233 $values +
= array('event_type_id' => CRM_Core_DAO
::getFieldValue('CRM_Event_DAO_Event', $values['event_id'], 'event_type_id'));
3236 $formattedGroupTree = array();
3238 foreach ($fields as $name => $field) {
3239 $fldName = $isStandalone ?
$name : "field[$componentId][$name]";
3240 if (array_key_exists($name, $values)) {
3241 $defaults[$fldName] = $values[$name];
3243 elseif ($name == 'participant_note') {
3244 $noteDetails = CRM_Core_BAO_Note
::getNote($componentId, 'civicrm_participant');
3245 $defaults[$fldName] = array_pop($noteDetails);
3247 elseif (in_array($name, array(
3249 'payment_instrument',
3250 'participant_status',
3253 $defaults[$fldName] = $values["{$name}_id"];
3255 elseif ($name == 'membership_type') {
3256 // since membership_type field is a hierselect -
3257 $defaults[$fldName][0]
3258 = CRM_Core_DAO
::getFieldValue('CRM_Member_DAO_MembershipType', $values['membership_type_id'], 'member_of_contact_id', 'id');
3259 $defaults[$fldName][1] = $values['membership_type_id'];
3261 elseif ($name == 'membership_status') {
3262 $defaults[$fldName] = $values['status_id'];
3264 elseif ($name == 'case_status') {
3265 $defaults[$fldName] = $values['case_status_id'];
3267 elseif (CRM_Core_BAO_CustomField
::getKeyID($name, TRUE) !== array(NULL, NULL)) {
3268 if (empty($formattedGroupTree)) {
3269 //get the groupTree as per subTypes.
3270 $groupTree = array();
3271 foreach ($componentSubType as $subType) {
3272 $subTree = CRM_Core_BAO_CustomGroup
::getTree($componentBAOName, NULL,
3273 $componentId, 0, $values[$subType]
3275 $groupTree = CRM_Utils_Array
::crmArrayMerge($groupTree, $subTree);
3277 $formattedGroupTree = CRM_Core_BAO_CustomGroup
::formatGroupTree($groupTree, 1);
3278 CRM_Core_BAO_CustomGroup
::setDefaults($formattedGroupTree, $defaults);
3281 //FIX ME: We need to loop defaults, but once we move to custom_1_x convention this code can be simplified.
3282 foreach ($defaults as $customKey => $customValue) {
3283 if ($customFieldDetails = CRM_Core_BAO_CustomField
::getKeyID($customKey, TRUE)) {
3284 if ($name == 'custom_' . $customFieldDetails[0]) {
3286 //hack to set default for checkbox
3287 //basically this is for weired field name like field[33][custom_19]
3288 //we are converting this field name to array structure and assign value.
3291 foreach ($formattedGroupTree as $tree) {
3292 if (!empty($tree['fields'][$customFieldDetails[0]])) {
3293 if ('CheckBox' == CRM_Utils_Array
::value('html_type', $tree['fields'][$customFieldDetails[0]])) {
3295 $defaults['field'][$componentId][$name] = $customValue;
3298 elseif (CRM_Utils_Array
::value('data_type', $tree['fields'][$customFieldDetails[0]]) == 'Date') {
3301 // CRM-6681, $default contains formatted date, time values.
3302 $defaults[$fldName] = $customValue;
3303 if (!empty($defaults[$customKey . '_time'])) {
3304 $defaults['field'][$componentId][$name . '_time'] = $defaults[$customKey . '_time'];
3310 if (!$skipValue ||
$isStandalone) {
3311 $defaults[$fldName] = $customValue;
3313 unset($defaults[$customKey]);
3319 elseif (isset($values[$fldName])) {
3320 $defaults[$fldName] = $values[$fldName];
3326 * Retrieve groups of profiles.
3328 * @param int $profileID
3329 * Id of the profile.
3334 public static function profileGroups($profileID) {
3335 $groupTypes = array();
3336 $profileTypes = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $profileID, 'group_type');
3337 if ($profileTypes) {
3338 $groupTypeParts = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $profileTypes);
3339 $groupTypes = explode(',', $groupTypeParts[0]);
3345 * Alter contact params by filtering existing subscribed groups and returns
3346 * unsubscribed groups array for subscription.
3348 * @param array $params
3350 * @param int $contactId
3354 * This contains array of groups for subscription
3356 public static function getDoubleOptInGroupIds(&$params, $contactId = NULL) {
3357 $config = CRM_Core_Config
::singleton();
3358 $subscribeGroupIds = array();
3360 // process further only if profileDoubleOptIn enabled and if groups exist
3361 if (!array_key_exists('group', $params) ||
3362 !self
::isProfileDoubleOptin() ||
3363 CRM_Utils_System
::isNull($params['group'])
3365 return $subscribeGroupIds;
3368 //check if contact email exist.
3370 foreach ($params as $name => $value) {
3371 if (strpos($name, 'email-') !== FALSE) {
3377 //Proceed furthur only if email present
3379 return $subscribeGroupIds;
3382 //do check for already subscriptions.
3383 $contactGroups = array();
3387 FROM civicrm_group_contact
3388 WHERE status = 'Added'
3389 AND contact_id = %1";
3391 $dao = CRM_Core_DAO
::executeQuery($query, array(1 => array($contactId, 'Integer')));
3392 while ($dao->fetch()) {
3393 $contactGroups[$dao->group_id
] = $dao->group_id
;
3397 //since we don't have names, compare w/ label.
3398 $mailingListGroupType = array_search('Mailing List', CRM_Core_OptionGroup
::values('group_type'));
3400 //actual processing start.
3401 foreach ($params['group'] as $groupId => $isSelected) {
3402 //unset group those are not selected.
3404 unset($params['group'][$groupId]);
3408 $groupTypes = explode(CRM_Core_DAO
::VALUE_SEPARATOR
,
3409 CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_Group', $groupId, 'group_type', 'id')
3411 //get only mailing type group and unset it from params
3412 if (in_array($mailingListGroupType, $groupTypes) && !in_array($groupId, $contactGroups)) {
3413 $subscribeGroupIds[$groupId] = $groupId;
3414 unset($params['group'][$groupId]);
3418 return $subscribeGroupIds;
3422 * Check if we are rendering mixed profiles.
3424 * @param array $profileIds
3425 * Associated array of profile ids.
3428 * true if profile is mixed
3430 public static function checkForMixProfiles($profileIds) {
3431 $mixProfile = FALSE;
3433 $contactTypes = array('Individual', 'Household', 'Organization');
3434 $subTypes = CRM_Contact_BAO_ContactType
::subTypes();
3436 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
3438 $typeCount = array('ctype' => array(), 'subtype' => array());
3439 foreach ($profileIds as $gid) {
3440 $profileType = CRM_Core_BAO_UFField
::getProfileType($gid);
3441 // ignore profile of type Contact
3442 if ($profileType == 'Contact') {
3445 if (in_array($profileType, $contactTypes)) {
3446 if (!isset($typeCount['ctype'][$profileType])) {
3447 $typeCount['ctype'][$profileType] = 1;
3450 // check if we are rendering profile of different contact types
3451 if (count($typeCount['ctype']) == 2) {
3456 elseif (in_array($profileType, $components)) {
3461 if (!isset($typeCount['subtype'][$profileType])) {
3462 $typeCount['subtype'][$profileType] = 1;
3464 // check if we are rendering profile of different contact sub types
3465 if (count($typeCount['subtype']) == 2) {
3475 * Determine of we show overlay profile or not.
3478 * true if profile should be shown else false
3480 public static function showOverlayProfile() {
3481 $showOverlay = TRUE;
3483 // get the id of overlay profile
3484 $overlayProfileId = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', 'summary_overlay', 'id', 'name');
3485 $query = "SELECT count(id) FROM civicrm_uf_field WHERE uf_group_id = {$overlayProfileId} AND visibility IN ('Public Pages', 'Public Pages and Listings') ";
3487 $count = CRM_Core_DAO
::singleValueQuery($query);
3489 //check if there are no public fields and use is anonymous
3490 $session = CRM_Core_Session
::singleton();
3491 if (!$count && !$session->get('userID')) {
3492 $showOverlay = FALSE;
3495 return $showOverlay;
3499 * Get group type values of the profile.
3501 * @param int $profileId
3502 * @param string $groupType
3507 public static function groupTypeValues($profileId, $groupType = NULL) {
3508 $groupTypeValue = array();
3509 $groupTypes = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $profileId, 'group_type');
3511 $groupTypeParts = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $groupTypes);
3512 if (empty($groupTypeParts[1])) {
3513 return $groupTypeValue;
3515 $participantExtends = array('ParticipantRole', 'ParticipantEventName', 'ParticipantEventType');
3517 foreach (explode(',', $groupTypeParts[1]) as $groupTypeValues) {
3519 $valueParts = explode(':', $groupTypeValues);
3521 ($valueParts[0] != "{$groupType}Type" ||
3522 ($groupType == 'Participant' &&
3523 !in_array($valueParts[0], $participantExtends)
3529 foreach ($valueParts as $val) {
3530 if (CRM_Utils_Rule
::integer($val)) {
3531 $values[$val] = $val;
3534 if (!empty($values)) {
3535 $typeName = substr($valueParts[0], 0, -4);
3536 if (in_array($valueParts[0], $participantExtends)) {
3537 $typeName = $valueParts[0];
3539 $groupTypeValue[$typeName] = $values;
3543 return $groupTypeValue;
3547 * @return bool|object
3549 public static function isProfileDoubleOptin() {
3550 // check for double optin
3551 $config = CRM_Core_Config
::singleton();
3552 if (in_array('CiviMail', $config->enableComponents
)) {
3553 return Civi
::settings()->get('profile_double_optin');
3559 * @return bool|object
3561 public static function isProfileAddToGroupDoubleOptin() {
3562 // check for add to group double optin
3563 $config = CRM_Core_Config
::singleton();
3564 if (in_array('CiviMail', $config->enableComponents
)) {
3565 return Civi
::settings()->get('profile_add_to_group_double_optin');
3571 * Get profiles used for batch entry.
3574 * profileIds profile ids
3576 public static function getBatchProfiles() {
3578 FROM civicrm_uf_group
3579 WHERE name IN ('contribution_batch_entry', 'membership_batch_entry')";
3580 $dao = CRM_Core_DAO
::executeQuery($query);
3581 $profileIds = array();
3582 while ($dao->fetch()) {
3583 $profileIds[$dao->id
] = $dao->id
;
3589 * @todo what do I do?
3591 * @param $destination
3592 * @param bool $returnMultiSummaryFields
3594 * @return array|null
3596 public static function shiftMultiRecordFields(&$source, &$destination, $returnMultiSummaryFields = FALSE) {
3597 $multiSummaryFields = $returnMultiSummaryFields ?
array() : NULL;
3598 foreach ($source as $field => $properties) {
3599 if (!CRM_Core_BAO_CustomField
::getKeyID($field)) {
3602 if (CRM_Core_BAO_CustomField
::isMultiRecordField($field)) {
3603 $destination[$field] = $properties;
3604 if ($returnMultiSummaryFields) {
3605 if ($properties['is_multi_summary']) {
3606 $multiSummaryFields[$field] = $properties;
3609 unset($source[$field]);
3612 return $multiSummaryFields;
3616 * This is function is used to format pseudo fields.
3618 * @param array $fields
3619 * Associated array of profile fields.
3622 public static function reformatProfileFields(&$fields) {
3623 //reformat fields array
3624 foreach ($fields as $name => $field) {
3625 //reformat phone and extension field
3626 if (substr($field['name'], 0, 13) == 'phone_and_ext') {
3627 $fieldSuffix = str_replace('phone_and_ext-', '', $field['name']);
3629 // retain existing element properties and just update and replace key
3630 CRM_Utils_Array
::crmReplaceKey($fields, $name, "phone-{$fieldSuffix}");
3631 $fields["phone-{$fieldSuffix}"]['name'] = "phone-{$fieldSuffix}";
3632 $fields["phone-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone';
3634 // add additional phone extension field
3635 $fields["phone_ext-{$fieldSuffix}"] = $field;
3636 $fields["phone_ext-{$fieldSuffix}"]['title'] = $field['title'] . ' - ' . ts('Ext.');
3637 $fields["phone_ext-{$fieldSuffix}"]['name'] = "phone_ext-{$fieldSuffix}";
3638 $fields["phone_ext-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone_ext';
3639 $fields["phone_ext-{$fieldSuffix}"]['skipDisplay'] = 1;
3640 //ignore required for extension field
3641 $fields["phone_ext-{$fieldSuffix}"]['is_required'] = 0;