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 if (!$details->fetch()) {
999 $query->convertToPseudoNames($details);
1000 $config = CRM_Core_Config
::singleton();
1002 $locationTypes = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Address', 'location_type_id');
1003 $imProviders = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_IM', 'provider_id');
1004 $websiteTypes = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Website', 'website_type_id');
1006 $multipleFields = array('url');
1008 //start of code to set the default values
1009 foreach ($fields as $name => $field) {
1011 if ($name == 'id') {
1012 $name = 'contact_id';
1015 // skip fields that should not be displayed separately
1016 if (!empty($field['skipDisplay'])) {
1020 // Create a unique, non-empty index for each field.
1021 $index = $field['title'];
1022 if ($index === '') {
1025 while (array_key_exists($index, $values)) {
1029 $params[$index] = $values[$index] = '';
1030 $customFieldName = NULL;
1032 if (isset($details->$name) ||
$name == 'group' ||
$name == 'tag') {
1033 // to handle gender / suffix / prefix
1034 if (in_array(substr($name, 0, -3), array('gender', 'prefix', 'suffix'))) {
1035 $params[$index] = $details->$name;
1036 $values[$index] = $details->$name;
1038 elseif (in_array($name, CRM_Contact_BAO_Contact
::$_greetingTypes)) {
1039 $dname = $name . '_display';
1040 $values[$index] = $details->$dname;
1041 $name = $name . '_id';
1042 $params[$index] = $details->$name;
1044 elseif (in_array($name, array(
1049 $values[$index] = $details->$name;
1050 $idx = $name . '_id';
1051 $params[$index] = $details->$idx;
1053 elseif ($name === 'preferred_language') {
1054 $params[$index] = $details->$name;
1055 $values[$index] = CRM_Core_PseudoConstant
::getLabel('CRM_Contact_DAO_Contact', 'preferred_language', $details->$name);
1057 elseif ($name == 'group') {
1058 $groups = CRM_Contact_BAO_GroupContact
::getContactGroup($cid, 'Added', NULL, FALSE, TRUE);
1059 $title = $ids = array();
1061 foreach ($groups as $g) {
1062 // CRM-8362: User and User Admin visibility groups should be included in display if user has
1063 // VIEW permission on that group
1064 $groupPerm = CRM_Contact_BAO_Group
::checkPermission($g['group_id'], TRUE);
1066 if ($g['visibility'] != 'User and User Admin Only' ||
1067 CRM_Utils_Array
::key(CRM_Core_Permission
::VIEW
, $groupPerm)
1069 $title[] = $g['title'];
1070 if ($g['visibility'] == 'Public Pages') {
1071 $ids[] = $g['group_id'];
1075 $values[$index] = implode(', ', $title);
1076 $params[$index] = implode(',', $ids);
1078 elseif ($name == 'tag') {
1079 $entityTags = CRM_Core_BAO_EntityTag
::getTag($cid);
1080 $allTags = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_EntityTag', 'tag_id', array('onlyActive' => FALSE));
1082 foreach ($entityTags as $tagId) {
1083 $title[] = $allTags[$tagId];
1085 $values[$index] = implode(', ', $title);
1086 $params[$index] = implode(',', $entityTags);
1088 elseif ($name == 'activity_status_id') {
1089 $activityStatus = CRM_Core_PseudoConstant
::activityStatus();
1090 $values[$index] = $activityStatus[$details->$name];
1091 $params[$index] = $details->$name;
1093 elseif ($name == 'activity_date_time') {
1094 $values[$index] = CRM_Utils_Date
::customFormat($details->$name);
1095 $params[$index] = $details->$name;
1097 elseif ($name == 'contact_sub_type') {
1098 $contactSubTypeNames = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $details->$name);
1099 if (!empty($contactSubTypeNames)) {
1100 $contactSubTypeLabels = array();
1101 // get all contact subtypes
1102 $allContactSubTypes = CRM_Contact_BAO_ContactType
::subTypeInfo();
1103 // build contact subtype labels array
1104 foreach ($contactSubTypeNames as $cstName) {
1106 $contactSubTypeLabels[] = $allContactSubTypes[$cstName]['label'];
1109 $values[$index] = implode(',', $contactSubTypeLabels);
1112 $params[$index] = $details->$name;
1115 if (substr($name, 0, 7) === 'do_not_' ||
substr($name, 0, 3) === 'is_') {
1116 if ($details->$name) {
1117 $values[$index] = '[ x ]';
1121 if ($cfID = CRM_Core_BAO_CustomField
::getKeyID($name)) {
1122 $htmlType = $field['html_type'];
1124 // field_type is only set when we are retrieving profile values
1125 // when sending email, we call the same function to get custom field
1126 // values etc, i.e. emulating a profile
1127 $fieldType = CRM_Utils_Array
::value('field_type', $field);
1129 if ($htmlType == 'File') {
1132 $fieldType == 'Activity' && !empty($componentWhere[0][2])
1134 $entityId = $componentWhere[0][2];
1137 $fileURL = CRM_Core_BAO_CustomField
::getFileURL($entityId,
1141 $additionalWhereClause
1143 $params[$index] = $values[$index] = $fileURL['file_url'];
1147 if (isset($dao) && property_exists($dao, 'data_type') &&
1148 ($dao->data_type
== 'Int' ||
1149 $dao->data_type
== 'Boolean'
1152 $customVal = (int ) ($details->{$name});
1154 elseif (isset($dao) && property_exists($dao, 'data_type')
1155 && $dao->data_type
== 'Float'
1157 $customVal = (float ) ($details->{$name});
1159 elseif (!CRM_Utils_System
::isNull(explode(CRM_Core_DAO
::VALUE_SEPARATOR
,
1163 $customVal = $details->{$name};
1167 if (CRM_Utils_System
::isNull($customVal)) {
1171 $params[$index] = $customVal;
1172 $values[$index] = CRM_Core_BAO_CustomField
::displayValue($customVal, $cfID);
1173 if ($field['data_type'] == 'ContactReference') {
1174 $params[$index] = $values[$index];
1176 if (CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomField',
1177 $cfID, 'is_search_range'
1180 $customFieldName = "{$name}_from";
1184 elseif ($name == 'image_URL') {
1185 list($width, $height) = getimagesize(CRM_Utils_String
::unstupifyUrl($details->$name));
1186 list($thumbWidth, $thumbHeight) = CRM_Contact_BAO_Contact
::getThumbSize($width, $height);
1188 $image_URL = '<img src="' . $details->$name . '" height= ' . $thumbHeight . ' width= ' . $thumbWidth . ' />';
1189 $values[$index] = "<a href='#' onclick='contactImagePopUp(\"{$details->$name}\", {$width}, {$height});'>{$image_URL}</a>";
1191 elseif (in_array($name, array(
1195 // @todo this set should be determined from metadata, not hard-coded.
1196 $values[$index] = CRM_Utils_Date
::customFormat($details->$name);
1197 $params[$index] = CRM_Utils_Date
::isoToMysql($details->$name);
1201 if ($index == 'Campaign') {
1202 $dao = 'CRM_Campaign_DAO_Campaign';
1204 elseif ($index == 'Contribution Page') {
1205 $dao = 'CRM_Contribute_DAO_ContributionPage';
1208 $value = CRM_Core_DAO
::getFieldValue($dao, $details->$name, 'title');
1211 $value = $details->$name;
1213 $values[$index] = $value;
1218 elseif (strpos($name, '-') !== FALSE) {
1219 list($fieldName, $id, $type) = CRM_Utils_System
::explode('-', $name, 3);
1221 if (!in_array($fieldName, $multipleFields)) {
1222 if ($id == 'Primary') {
1224 // not sure why we'd every use Primary location type id
1225 // we need to fix the source if we are using it
1226 // $locationTypeName = CRM_Contact_BAO_Contact::getPrimaryLocationType( $cid );
1227 $locationTypeName = 1;
1230 $locationTypeName = CRM_Utils_Array
::value($id, $locationTypes);
1233 if (!$locationTypeName) {
1237 $detailName = "{$locationTypeName}-{$fieldName}";
1238 $detailName = str_replace(' ', '_', $detailName);
1240 if (in_array($fieldName, array(
1247 $detailName .= "-{$type}";
1251 if (in_array($fieldName, array(
1256 $values[$index] = $details->$detailName;
1257 $idx = $detailName . '_id';
1258 $params[$index] = $details->$idx;
1260 elseif ($fieldName == 'im') {
1261 $providerId = $detailName . '-provider_id';
1262 if (isset($imProviders[$details->$providerId])) {
1263 $values[$index] = $details->$detailName . " (" . $imProviders[$details->$providerId] . ")";
1266 $values[$index] = $details->$detailName;
1268 $params[$index] = $details->$detailName;
1270 elseif ($fieldName == 'phone') {
1271 $phoneExtField = str_replace('phone', 'phone_ext', $detailName);
1272 if (isset($details->$phoneExtField)) {
1273 $values[$index] = $details->$detailName . " (" . $details->$phoneExtField . ")";
1276 $values[$index] = $details->$detailName;
1278 $params[$index] = $details->$detailName;
1281 $values[$index] = $params[$index] = $details->$detailName;
1285 $detailName = "website-{$id}-{$fieldName}";
1286 $url = CRM_Utils_System
::fixURL($details->$detailName);
1287 if ($details->$detailName) {
1288 $websiteTypeId = "website-{$id}-website_type_id";
1289 $websiteType = $websiteTypes[$details->$websiteTypeId];
1290 $values[$index] = "<a href=\"$url\">{$details->$detailName} ( {$websiteType} )</a>";
1293 $values[$index] = '';
1298 if ((CRM_Utils_Array
::value('visibility', $field) == 'Public Pages and Listings') &&
1299 CRM_Core_Permission
::check('profile listings and forms')
1302 if (CRM_Utils_System
::isNull($params[$index])) {
1303 $params[$index] = $values[$index];
1305 if (!isset($params[$index])) {
1308 if (!$customFieldName) {
1309 $fieldName = $field['name'];
1312 $fieldName = $customFieldName;
1316 if (CRM_Core_BAO_CustomField
::getKeyID($field['name'])) {
1317 $htmlType = $field['html_type'];
1318 if ($htmlType == 'Link') {
1319 $url = $params[$index];
1321 elseif (in_array($htmlType, array(
1324 'Multi-Select State/Province',
1325 'Multi-Select Country',
1327 $valSeperator = CRM_Core_DAO
::VALUE_SEPARATOR
;
1328 $selectedOptions = explode($valSeperator, $params[$index]);
1330 foreach ($selectedOptions as $key => $multiOption) {
1332 $url[] = CRM_Utils_System
::url('civicrm/profile',
1333 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1334 urlencode($fieldName) .
1336 urlencode($multiOption)
1342 $url = CRM_Utils_System
::url('civicrm/profile',
1343 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1344 urlencode($fieldName) .
1346 urlencode($params[$index])
1351 $url = CRM_Utils_System
::url('civicrm/profile',
1352 'reset=1&force=1&gid=' . $field['group_id'] . '&' .
1353 urlencode($fieldName) .
1355 urlencode($params[$index])
1360 !empty($values[$index]) &&
1364 if (is_array($url) && !empty($url)) {
1366 $eachMultiValue = explode(', ', $values[$index]);
1367 foreach ($eachMultiValue as $key => $valueLabel) {
1368 $links[] = '<a href="' . $url[$key] . '">' . $valueLabel . '</a>';
1370 $values[$index] = implode(', ', $links);
1373 $values[$index] = '<a href="' . $url . '">' . $values[$index] . '</a>';
1381 * Check if profile Group used by any module.
1389 public static function usedByModule($id) {
1390 //check whether this group is used by any module(check uf join records)
1392 FROM civicrm_uf_join
1393 WHERE civicrm_uf_join.uf_group_id=$id";
1395 $dao = new CRM_Core_DAO();
1397 if ($dao->fetch()) {
1406 * Delete the profile Group.
1414 public static function del($id) {
1415 //check whether this group contains any profile fields
1416 $profileField = new CRM_Core_DAO_UFField();
1417 $profileField->uf_group_id
= $id;
1418 $profileField->find();
1419 while ($profileField->fetch()) {
1420 CRM_Core_BAO_UFField
::del($profileField->id
);
1423 //delete records from uf join table
1424 $ufJoin = new CRM_Core_DAO_UFJoin();
1425 $ufJoin->uf_group_id
= $id;
1428 //delete profile group
1429 $group = new CRM_Core_DAO_UFGroup();
1438 * @param array $params
1439 * Reference array contains the values submitted by the form.
1441 * Reference array contains the id.
1446 public static function add(&$params, $ids = array()) {
1456 foreach ($fields as $field) {
1457 $params[$field] = CRM_Utils_Array
::value($field, $params, FALSE);
1460 $params['limit_listings_group_id'] = CRM_Utils_Array
::value('group', $params);
1461 $params['add_to_group_id'] = CRM_Utils_Array
::value('add_contact_to_group', $params);
1464 if (!empty($params['group_type']) && is_array($params['group_type'])) {
1465 $params['group_type'] = implode(',', $params['group_type']);
1467 $ufGroup = new CRM_Core_DAO_UFGroup();
1468 $ufGroup->copyValues($params);
1470 $ufGroupID = CRM_Utils_Array
::value('ufgroup', $ids, CRM_Utils_Array
::value('id', $params));
1471 if (!$ufGroupID && empty($params['name'])) {
1472 $ufGroup->name
= CRM_Utils_String
::munge($ufGroup->title
, '_', 56);
1474 $ufGroup->id
= $ufGroupID;
1478 if (!$ufGroupID && empty($params['name'])) {
1479 $ufGroup->name
= $ufGroup->name
. "_{$ufGroup->id}";
1487 * Make uf join entries for an uf group.
1489 * @param array $params
1490 * (reference) an assoc array of name/value pairs.
1491 * @param int $ufGroupId
1494 public static function createUFJoin(&$params, $ufGroupId) {
1495 $groupTypes = CRM_Utils_Array
::value('uf_group_type', $params);
1497 // get ufjoin records for uf group
1498 $ufGroupRecord = CRM_Core_BAO_UFGroup
::getUFJoinRecord($ufGroupId);
1500 // get the list of all ufgroup types
1501 $allUFGroupType = CRM_Core_SelectValues
::ufGroupTypes();
1503 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
1504 if (!is_array($groupTypes)) {
1505 $groupTypes = array();
1508 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
1509 if (!is_array($ufGroupRecord)) {
1510 $ufGroupRecord = array();
1513 // check which values has to be inserted/deleted for contact
1514 $menuRebuild = FALSE;
1515 foreach ($allUFGroupType as $key => $value) {
1516 $joinParams = array();
1517 $joinParams['uf_group_id'] = $ufGroupId;
1518 $joinParams['module'] = $key;
1519 if ($key == 'User Account') {
1520 $menuRebuild = TRUE;
1522 if (array_key_exists($key, $groupTypes) && !in_array($key, $ufGroupRecord)) {
1523 // insert a new record
1524 CRM_Core_BAO_UFGroup
::addUFJoin($joinParams);
1526 elseif (!array_key_exists($key, $groupTypes) && in_array($key, $ufGroupRecord)) {
1527 // delete a record for existing ufgroup
1528 CRM_Core_BAO_UFGroup
::delUFJoin($joinParams);
1534 UPDATE civicrm_uf_join
1536 WHERE uf_group_id = %2
1537 AND ( entity_id IS NULL OR entity_id <= 0 )
1540 1 => array($params['weight'], 'Integer'),
1541 2 => array($ufGroupId, 'Integer'),
1543 CRM_Core_DAO
::executeQuery($query, $p);
1545 // Do a menu rebuild, so it gets all the new menu entries for user account
1547 $config = CRM_Core_Config
::singleton();
1548 $config->userSystem
->updateCategories();
1553 * Get the UF Join records for an ufgroup id.
1555 * @param int $ufGroupId
1557 * @param int $displayName
1558 * If set return display name in array.
1559 * @param int $status
1560 * If set return module other than default modules (User Account/User registration/Profile).
1565 public static function getUFJoinRecord($ufGroupId = NULL, $displayName = NULL, $status = NULL) {
1567 $UFGroupType = array();
1568 $UFGroupType = CRM_Core_SelectValues
::ufGroupTypes();
1572 $dao = new CRM_Core_DAO_UFJoin();
1575 $dao->uf_group_id
= $ufGroupId;
1581 while ($dao->fetch()) {
1582 if (!$displayName) {
1583 $ufJoin[$dao->id
] = $dao->module
;
1586 if (isset($UFGroupType[$dao->module
])) {
1587 // skip the default modules
1589 $ufJoin[$dao->id
] = $UFGroupType[$dao->module
];
1591 // added for CRM-1475
1593 elseif (!CRM_Utils_Array
::key($dao->module
, $ufJoin)) {
1594 $ufJoin[$dao->id
] = $dao->module
;
1602 * Function takes an associative array and creates a ufjoin record for ufgroup.
1604 * @param array $params
1605 * (reference) an assoc array of name/value pairs.
1607 * @return CRM_Core_BAO_UFJoin
1609 public static function addUFJoin(&$params) {
1610 $ufJoin = new CRM_Core_DAO_UFJoin();
1611 $ufJoin->copyValues($params);
1617 * Delete the uf join record for an uf group.
1619 * @param array $params
1620 * (reference) an assoc array of name/value pairs.
1622 public static function delUFJoin(&$params) {
1623 $ufJoin = new CRM_Core_DAO_UFJoin();
1624 $ufJoin->copyValues($params);
1629 * Get the weight for ufjoin record.
1631 * @param int $ufGroupId
1632 * If $ufGroupId get update weight or add weight.
1635 * weight of the UFGroup
1637 public static function getWeight($ufGroupId = NULL) {
1638 //calculate the weight
1641 $queryString = "SELECT ( MAX(civicrm_uf_join.weight)+1) as new_weight
1642 FROM civicrm_uf_join
1643 WHERE module = 'User Registration' OR module = 'User Account' OR module = 'Profile'";
1646 $queryString = "SELECT MAX(civicrm_uf_join.weight) as new_weight
1647 FROM civicrm_uf_join
1648 WHERE civicrm_uf_join.uf_group_id = %1
1649 AND ( entity_id IS NULL OR entity_id <= 0 )";
1650 $p[1] = array($ufGroupId, 'Integer');
1653 $dao = CRM_Core_DAO
::executeQuery($queryString, $p);
1655 return ($dao->new_weight
) ?
$dao->new_weight
: 1;
1659 * Get the uf group for a module.
1661 * @param string $moduleName
1664 * No to increment the weight.
1665 * @param bool $skipPermission
1667 * Which operation (view, edit, create, etc) to check permission for.
1668 * @param array|NULL $returnFields list of UFGroup fields to return; NULL for default
1671 * array of ufgroups for a module
1673 public static function getModuleUFGroup($moduleName = NULL, $count = 0, $skipPermission = TRUE, $op = CRM_Core_Permission
::VIEW
, $returnFields = NULL) {
1674 $selectFields = array('id', 'title', 'created_id', 'is_active', 'is_reserved', 'group_type');
1676 if (CRM_Core_BAO_SchemaHandler
::checkIfFieldExists('civicrm_uf_group', 'description')) {
1677 // CRM-13555, since description field was added later (4.4), and to avoid any problems with upgrade
1678 $selectFields[] = 'description';
1681 if (CRM_Core_BAO_SchemaHandler
::checkIfFieldExists('civicrm_uf_group', 'frontend_title')) {
1682 $selectFields[] = 'frontend_title';
1685 if (!empty($returnFields)) {
1686 $selectFields = array_merge($returnFields, array_diff($selectFields, $returnFields));
1689 $queryString = 'SELECT civicrm_uf_group.' . implode(', civicrm_uf_group.', $selectFields) . '
1690 FROM civicrm_uf_group
1691 LEFT JOIN civicrm_uf_join ON (civicrm_uf_group.id = uf_group_id)';
1694 $queryString .= ' AND civicrm_uf_group.is_active = 1
1695 WHERE civicrm_uf_join.module = %2';
1696 $p[2] = array($moduleName, 'String');
1699 // add permissioning for profiles only if not registration
1700 if (!$skipPermission) {
1701 $permissionClause = CRM_Core_Permission
::ufGroupClause($op, 'civicrm_uf_group.');
1702 if (strpos($queryString, 'WHERE') !== FALSE) {
1703 $queryString .= " AND $permissionClause ";
1706 $queryString .= " $permissionClause ";
1710 $queryString .= ' ORDER BY civicrm_uf_join.weight, civicrm_uf_group.title';
1711 $dao = CRM_Core_DAO
::executeQuery($queryString, $p);
1713 $ufGroups = array();
1714 while ($dao->fetch()) {
1715 //skip mix profiles in user Registration / User Account
1716 if (($moduleName == 'User Registration' ||
$moduleName == 'User Account') &&
1717 CRM_Core_BAO_UFField
::checkProfileType($dao->id
)
1721 foreach ($selectFields as $key => $field) {
1722 if ($field == 'id') {
1725 $ufGroups[$dao->id
][$field] = $dao->$field;
1729 // Allow other modules to alter/override the UFGroups.
1730 CRM_Utils_Hook
::buildUFGroupsForModule($moduleName, $ufGroups);
1736 * Filter ufgroups based on logged in user contact type.
1738 * @param int $ufGroupId
1739 * Uf group id (profile id).
1740 * @param int $contactID
1745 public static function filterUFGroups($ufGroupId, $contactID = NULL) {
1747 $session = CRM_Core_Session
::singleton();
1748 $contactID = $session->get('userID');
1752 //get the contact type
1753 $contactType = CRM_Contact_BAO_Contact
::getContactType($contactID);
1755 //match if exixting contact type is same as profile contact type
1756 $profileType = CRM_Core_BAO_UFField
::getProfileType($ufGroupId);
1758 if (CRM_Contact_BAO_ContactType
::isaSubType($profileType)) {
1759 $profileType = CRM_Contact_BAO_ContactType
::getBasicType($profileType);
1761 //in some cases getBasicType() returns a cached array instead of string. Example: array ('sponsor' => 'organization')
1762 if (is_array($profileType)) {
1763 $profileType = array_shift($profileType);
1767 //allow special mix profiles for Contribution and Participant
1768 $specialProfiles = array('Contribution', 'Participant', 'Membership');
1770 if (in_array($profileType, $specialProfiles)) {
1774 if (($contactType == $profileType) ||
$profileType == 'Contact') {
1783 * Add profile field to a form.
1785 * @param CRM_Core_Form $form
1786 * @param array $field
1790 * @param int $contactId
1791 * @param bool $online
1792 * @param string $usedFor
1793 * For building up prefixed fieldname for special cases (e.g. onBehalf, Honor).
1794 * @param int $rowNumber
1795 * @param string $prefix
1799 public static function buildProfile(
1809 $defaultValues = array();
1810 $fieldName = $field['name'];
1811 $title = $field['title'];
1812 $attributes = $field['attributes'];
1813 $rule = $field['rule'];
1814 $view = $field['is_view'];
1815 $required = ($mode == CRM_Profile_Form
::MODE_SEARCH
) ?
FALSE : $field['is_required'];
1816 $search = ($mode == CRM_Profile_Form
::MODE_SEARCH
) ?
TRUE : FALSE;
1817 $isShared = CRM_Utils_Array
::value('is_shared', $field, 0);
1819 // do not display view fields in drupal registration form
1821 if ($view && $mode == CRM_Profile_Form
::MODE_REGISTER
) {
1825 if ($usedFor == 'onbehalf') {
1826 $name = "onbehalf[$fieldName]";
1828 elseif ($usedFor == 'honor') {
1829 $name = "honor[$fieldName]";
1831 elseif ($contactId && !$online) {
1832 $name = "field[$contactId][$fieldName]";
1834 elseif ($rowNumber) {
1835 $name = "field[$rowNumber][$fieldName]";
1837 elseif (!empty($prefix)) {
1838 $name = $prefix . "[$fieldName]";
1844 $selectAttributes = array('class' => 'crm-select2', 'placeholder' => TRUE);
1846 if ($fieldName == 'image_URL' && $mode == CRM_Profile_Form
::MODE_EDIT
) {
1847 $deleteExtra = json_encode(ts('Are you sure you want to delete contact image.'));
1849 CRM_Core_Action
::DELETE
=> array(
1850 'name' => ts('Delete Contact Image'),
1851 'url' => 'civicrm/contact/image',
1852 'qs' => 'reset=1&id=%%id%%&gid=%%gid%%&action=delete',
1853 'extra' => 'onclick = "' . htmlspecialchars("if (confirm($deleteExtra)) this.href+='&confirmed=1'; else return false;") . '"',
1856 $deleteURL = CRM_Core_Action
::formLink($deleteURL,
1857 CRM_Core_Action
::DELETE
,
1859 'id' => $form->get('id'),
1860 'gid' => $form->get('gid'),
1864 'contact.profileimage.delete',
1868 $form->assign('deleteURL', $deleteURL);
1870 $addressOptions = CRM_Core_BAO_Setting
::valueOptions(CRM_Core_BAO_Setting
::SYSTEM_PREFERENCES_NAME
,
1871 'address_options', TRUE, NULL, TRUE
1874 if (substr($fieldName, 0, 14) === 'state_province') {
1875 $form->addChainSelect($name, array('label' => $title, 'required' => $required));
1876 $config = CRM_Core_Config
::singleton();
1877 if (!in_array($mode, array(
1878 CRM_Profile_Form
::MODE_EDIT
,
1879 CRM_Profile_Form
::MODE_SEARCH
,
1881 $config->defaultContactStateProvince
1883 $defaultValues[$name] = $config->defaultContactStateProvince
;
1884 $form->setDefaults($defaultValues);
1887 elseif (substr($fieldName, 0, 7) === 'country') {
1888 $form->add('select', $name, $title, array('' => ts('- select -')) + CRM_Core_PseudoConstant
::country(), $required, $selectAttributes);
1889 $config = CRM_Core_Config
::singleton();
1890 if (!in_array($mode, array(
1891 CRM_Profile_Form
::MODE_EDIT
,
1892 CRM_Profile_Form
::MODE_SEARCH
,
1894 $config->defaultContactCountry
1896 $defaultValues[$name] = $config->defaultContactCountry
;
1897 $form->setDefaults($defaultValues);
1900 elseif (substr($fieldName, 0, 6) === 'county') {
1901 if ($addressOptions['county']) {
1902 $form->addChainSelect($name, array('label' => $title, 'required' => $required));
1905 elseif (substr($fieldName, 0, 9) === 'image_URL') {
1906 $form->add('file', $name, $title, $attributes, $required);
1907 $form->addUploadElement($name);
1909 elseif (substr($fieldName, 0, 2) === 'im') {
1910 $form->add('text', $name, $title, $attributes, $required);
1913 if (substr($name, -1) == ']') {
1914 $providerName = substr($name, 0, -1) . '-provider_id]';
1916 $form->add('select', $providerName, NULL,
1918 '' => ts('- select -'),
1919 ) + CRM_Core_PseudoConstant
::get('CRM_Core_DAO_IM', 'provider_id'), $required
1923 $form->add('select', $name . '-provider_id', $title,
1925 '' => ts('- select -'),
1926 ) + CRM_Core_PseudoConstant
::get('CRM_Core_DAO_IM', 'provider_id'), $required
1930 if ($view && $mode != CRM_Profile_Form
::MODE_SEARCH
) {
1931 $form->freeze($name . '-provider_id');
1935 elseif (CRM_Utils_Array
::value('name', $field) == 'membership_type') {
1936 list($orgInfo, $types) = CRM_Member_BAO_MembershipType
::getMembershipTypeInfo();
1937 $sel = &$form->addElement('hierselect', $name, $title);
1938 $select = array('' => ts('- select -'));
1939 if (count($orgInfo) == 1 && $field['is_required']) {
1940 // we only have one org - so we should default to it. Not sure about defaulting to first type
1941 // as it could be missed - so adding a select
1942 // however, possibly that is more similar to the membership form
1943 if (count($types[1]) > 1) {
1944 $types[1] = $select +
$types[1];
1948 $orgInfo = $select +
$orgInfo;
1950 $sel->setOptions(array($orgInfo, $types));
1952 elseif (CRM_Utils_Array
::value('name', $field) == 'membership_status') {
1953 $form->add('select', $name, $title,
1955 '' => ts('- select -'),
1956 ) + CRM_Member_PseudoConstant
::membershipStatus(NULL, NULL, 'label'), $required
1959 elseif (in_array($fieldName, array('gender_id', 'communication_style_id'))) {
1961 $pseudoValues = CRM_Core_PseudoConstant
::get('CRM_Contact_DAO_Contact', $fieldName);
1962 foreach ($pseudoValues as $key => $var) {
1963 $options[$key] = $form->createElement('radio', NULL, ts($title), $var, $key);
1965 $group = $form->addGroup($options, $name, $title);
1967 $form->addRule($name, ts('%1 is a required field.', array(1 => $title)), 'required');
1970 $group->setAttribute('allowClear', TRUE);
1973 elseif ($fieldName === 'prefix_id' ||
$fieldName === 'suffix_id') {
1974 $form->addSelect($name, array(
1976 'entity' => 'contact',
1977 'field' => $fieldName,
1979 'placeholder' => '',
1982 elseif ($fieldName === 'contact_sub_type') {
1983 $gId = $form->get('gid') ?
$form->get('gid') : CRM_Utils_Array
::value('group_id', $field);
1984 if ($usedFor == 'onbehalf') {
1985 $profileType = 'Organization';
1987 elseif ($usedFor == 'honor') {
1988 $profileType = CRM_Core_BAO_UFField
::getProfileType($form->_params
['honoree_profile_id']);
1991 $profileType = $gId ? CRM_Core_BAO_UFField
::getProfileType($gId) : NULL;
1992 if ($profileType == 'Contact') {
1993 $profileType = 'Individual';
1997 $setSubtype = FALSE;
1998 if (CRM_Contact_BAO_ContactType
::isaSubType($profileType)) {
1999 $setSubtype = $profileType;
2000 $profileType = CRM_Contact_BAO_ContactType
::getBasicType($profileType);
2003 $subtypes = $profileType ? CRM_Contact_BAO_ContactType
::subTypePairs($profileType) : array();
2006 $subtypeList = array();
2007 $subtypeList[$setSubtype] = $subtypes[$setSubtype];
2010 $subtypeList = $subtypes;
2013 $form->add('select', $name, $title, $subtypeList, $required, array('class' => 'crm-select2', 'multiple' => TRUE));
2015 elseif (in_array($fieldName, CRM_Contact_BAO_Contact
::$_greetingTypes)) {
2016 //add email greeting, postal greeting, addressee, CRM-4575
2017 $gId = $form->get('gid') ?
$form->get('gid') : CRM_Utils_Array
::value('group_id', $field);
2018 $profileType = CRM_Core_BAO_UFField
::getProfileType($gId, TRUE, FALSE, TRUE);
2020 if (empty($profileType) ||
in_array($profileType, array(
2027 $profileType = 'Individual';
2029 if (CRM_Contact_BAO_ContactType
::isaSubType($profileType)) {
2030 $profileType = CRM_Contact_BAO_ContactType
::getBasicType($profileType);
2033 'contact_type' => $profileType,
2034 'greeting_type' => $fieldName,
2036 $form->add('select', $name, $title,
2038 '' => ts('- select -'),
2039 ) + CRM_Core_PseudoConstant
::greeting($greeting), $required
2041 // add custom greeting element
2042 $form->add('text', $fieldName . '_custom', ts('Custom %1', array(1 => ucwords(str_replace('_', ' ', $fieldName)))),
2046 elseif ($fieldName === 'preferred_communication_method') {
2047 $communicationFields = CRM_Core_PseudoConstant
::get('CRM_Contact_DAO_Contact', 'preferred_communication_method');
2048 foreach ($communicationFields as $key => $var) {
2052 $communicationOptions[] = $form->createElement('checkbox', $key, NULL, $var);
2054 $form->addGroup($communicationOptions, $name, $title, '<br/>');
2056 elseif ($fieldName === 'preferred_mail_format') {
2057 $form->add('select', $name, $title, CRM_Core_SelectValues
::pmf());
2059 elseif ($fieldName === 'preferred_language') {
2060 $form->add('select', $name, $title, array('' => ts('- select -')) + CRM_Contact_BAO_Contact
::buildOptions('preferred_language'));
2062 elseif ($fieldName == 'external_identifier') {
2063 $form->add('text', $name, $title, $attributes, $required);
2064 $contID = $contactId;
2066 $contID = $form->get('id');
2068 $form->addRule($name,
2069 ts('External ID already exists in Database.'),
2071 array('CRM_Contact_DAO_Contact', $contID, 'external_identifier')
2074 elseif ($fieldName === 'group') {
2075 CRM_Contact_Form_Edit_TagsAndGroups
::buildQuickForm($form, $contactId,
2076 CRM_Contact_Form_Edit_TagsAndGroups
::GROUP
,
2081 elseif ($fieldName === 'tag') {
2082 CRM_Contact_Form_Edit_TagsAndGroups
::buildQuickForm($form, $contactId,
2083 CRM_Contact_Form_Edit_TagsAndGroups
::TAG
,
2088 elseif (substr($fieldName, 0, 4) === 'url-') {
2089 $form->add('text', $name, $title, CRM_Core_DAO
::getAttribute('CRM_Core_DAO_Website', 'url'), $required);
2090 $form->addRule($name, ts('Enter a valid web address beginning with \'http://\' or \'https://\'.'), 'url');
2092 // Note should be rendered as textarea
2093 elseif (substr($fieldName, -4) == 'note') {
2094 $form->add('textarea', $name, $title, $attributes, $required);
2096 elseif (substr($fieldName, 0, 6) === 'custom') {
2097 $customFieldID = CRM_Core_BAO_CustomField
::getKeyID($fieldName);
2098 if ($customFieldID) {
2099 CRM_Core_BAO_CustomField
::addQuickFormElement($form, $name, $customFieldID, $required, $search, $title);
2102 elseif (substr($fieldName, 0, 14) === 'address_custom') {
2103 list($fName, $locTypeId) = CRM_Utils_System
::explode('-', $fieldName, 2);
2104 $customFieldID = CRM_Core_BAO_CustomField
::getKeyID(substr($fName, 8));
2105 if ($customFieldID) {
2106 CRM_Core_BAO_CustomField
::addQuickFormElement($form, $name, $customFieldID, $required, $search, $title);
2109 elseif ($fieldName == 'send_receipt') {
2110 $form->addElement('checkbox', $name, $title);
2112 elseif ($fieldName == 'soft_credit') {
2113 $form->addEntityRef("soft_credit_contact_id[$rowNumber]", ts('Soft Credit To'), array('create' => TRUE));
2114 $form->addMoney("soft_credit_amount[{$rowNumber}]", ts('Amount'), FALSE, NULL, FALSE);
2116 elseif ($fieldName == 'product_name') {
2117 list($products, $options) = CRM_Contribute_BAO_Premium
::getPremiumProductInfo();
2118 $sel = &$form->addElement('hierselect', $name, $title);
2120 '0' => ts('- select -'),
2122 $sel->setOptions(array($products, $options));
2124 elseif ($fieldName == 'payment_instrument') {
2125 $form->add('select', $name, $title,
2126 array('' => ts('- select -')) + CRM_Contribute_PseudoConstant
::paymentInstrument(), $required);
2128 elseif ($fieldName == 'financial_type') {
2129 $form->add('select', $name, $title,
2131 '' => ts('- select -'),
2132 ) + CRM_Contribute_PseudoConstant
::financialType(), $required
2135 elseif ($fieldName == 'contribution_status_id') {
2136 $contributionStatuses = CRM_Contribute_PseudoConstant
::contributionStatus();
2137 $statusName = CRM_Contribute_PseudoConstant
::contributionStatus(NULL, 'name');
2143 unset($contributionStatuses[CRM_Utils_Array
::key($suppress, $statusName)]);
2146 $form->add('select', $name, $title,
2148 '' => ts('- select -'),
2149 ) +
$contributionStatuses, $required
2152 elseif ($fieldName == 'soft_credit_type') {
2153 $name = "soft_credit_type[$rowNumber]";
2154 $form->add('select', $name, $title,
2156 '' => ts('- select -'),
2157 ) + CRM_Core_OptionGroup
::values("soft_credit_type")
2159 //CRM-15350: choose SCT field default value as 'Gift' for membership use
2160 //else (for contribution), use configured SCT default value
2161 $SCTDefaultValue = CRM_Core_OptionGroup
::getDefaultValue("soft_credit_type");
2162 if ($field['field_type'] == 'Membership') {
2163 $SCTDefaultValue = CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_ContributionSoft', 'soft_credit_type_id', 'gift');
2165 $form->addElement('hidden', 'sct_default_id', $SCTDefaultValue, array('id' => 'sct_default_id'));
2167 elseif ($fieldName == 'contribution_soft_credit_pcp_id') {
2168 CRM_Contribute_Form_SoftCredit
::addPCPFields($form, "[$rowNumber]");
2170 elseif ($fieldName == 'currency') {
2171 $form->addCurrency($name, $title, $required, NULL, FALSE, FALSE);
2173 elseif ($fieldName == 'contribution_page_id') {
2174 $form->add('select', $name, $title,
2176 '' => ts('- select -'),
2177 ) + CRM_Contribute_PseudoConstant
::contributionPage(), $required, 'class="big"'
2180 elseif ($fieldName == 'activity_status_id') {
2181 $form->add('select', $name, $title,
2183 '' => ts('- select -'),
2184 ) + CRM_Core_PseudoConstant
::activityStatus(), $required
2187 elseif ($fieldName == 'activity_engagement_level') {
2188 $form->add('select', $name, $title,
2190 '' => ts('- select -'),
2191 ) + CRM_Campaign_PseudoConstant
::engagementLevel(), $required
2194 elseif ($fieldName == 'participant_status') {
2196 if ($online == TRUE) {
2197 $cond = 'visibility_id = 1';
2199 $form->add('select', $name, $title,
2201 '' => ts('- select -'),
2202 ) + CRM_Event_PseudoConstant
::participantStatus(NULL, $cond, 'label'), $required
2205 elseif ($fieldName == 'participant_role') {
2206 if (!empty($field['is_multiple'])) {
2207 $form->addCheckBox($name, $title, CRM_Event_PseudoConstant
::participantRole(), NULL, NULL, NULL, NULL, ' ', TRUE);
2210 $form->add('select', $name, $title,
2212 '' => ts('- select -'),
2213 ) + CRM_Event_PseudoConstant
::participantRole(), $required
2217 elseif ($fieldName == 'world_region') {
2218 $form->add('select', $name, $title, CRM_Core_PseudoConstant
::worldRegion(), $required, $selectAttributes);
2220 elseif ($fieldName == 'signature_html') {
2221 $form->add('wysiwyg', $name, $title, CRM_Core_DAO
::getAttribute('CRM_Core_DAO_Email', $fieldName));
2223 elseif ($fieldName == 'signature_text') {
2224 $form->add('textarea', $name, $title, CRM_Core_DAO
::getAttribute('CRM_Core_DAO_Email', $fieldName));
2226 elseif (substr($fieldName, -11) == 'campaign_id') {
2227 if (CRM_Campaign_BAO_Campaign
::isCampaignEnable()) {
2228 $campaigns = CRM_Campaign_BAO_Campaign
::getCampaigns(CRM_Utils_Array
::value($contactId,
2229 $form->_componentCampaigns
2231 $form->add('select', $name, $title,
2233 '' => ts('- select -'),
2234 ) +
$campaigns, $required, 'class="crm-select2 big"'
2238 elseif ($fieldName == 'activity_details') {
2239 $form->add('wysiwyg', $fieldName, $title, array('rows' => 4, 'cols' => 60), $required);
2241 elseif ($fieldName == 'activity_duration') {
2242 $form->add('text', $name, $title, $attributes, $required);
2243 $form->addRule($name, ts('Please enter the duration as number of minutes (integers only).'), 'positiveInteger');
2245 elseif ($fieldName == 'case_status') {
2246 $form->add('select', $name, $title,
2248 '' => ts('- select -'),
2249 ) + CRM_Case_BAO_Case
::buildOptions('case_status_id', 'create'),
2254 if (substr($fieldName, 0, 3) === 'is_' or substr($fieldName, 0, 7) === 'do_not_') {
2255 $form->add('advcheckbox', $name, $title, $attributes, $required);
2257 elseif (CRM_Utils_Array
::value('html_type', $field) === 'Select Date') {
2258 $extra = isset($field['datepicker']) ?
$field['datepicker']['extra'] : CRM_Utils_Date
::getDatePickerExtra($field);
2259 $attributes = isset($field['datepicker']) ?
$field['datepicker']['attributes'] : CRM_Utils_Date
::getDatePickerAttributes($field);
2260 $form->add('datepicker', $name, $title, $attributes, $required, $extra);
2263 $form->add('text', $name, $title, $attributes, $required);
2267 static $hiddenSubtype = FALSE;
2268 if (!$hiddenSubtype && CRM_Contact_BAO_ContactType
::isaSubType($field['field_type'])) {
2269 // In registration mode params are submitted via POST and we don't have any clue
2270 // about profile-id or the profile-type (which could be a subtype)
2271 // To generalize the behavior and simplify the process,
2272 // lets always add the hidden
2273 //subtype value if there is any, and we won't have to
2274 // compute it while processing.
2276 $form->addElement('hidden', $usedFor . '[contact_sub_type]', $field['field_type']);
2279 $form->addElement('hidden', 'contact_sub_type_hidden', $field['field_type']);
2281 $hiddenSubtype = TRUE;
2284 if (($view && $mode != CRM_Profile_Form
::MODE_SEARCH
) ||
$isShared) {
2285 $form->freeze($name);
2289 if (in_array($fieldName, array(
2290 'non_deductible_amount',
2295 $form->addRule($name, ts('Please enter a valid amount.'), 'money');
2298 if (!($rule == 'email' && $mode == CRM_Profile_Form
::MODE_SEARCH
)) {
2299 $form->addRule($name, ts('Please enter a valid %1', array(1 => $title)), $rule);
2305 * Set profile defaults.
2307 * @param int $contactId
2309 * @param array $fields
2310 * Associative array of fields.
2311 * @param array $defaults
2313 * @param bool $singleProfile
2314 * True for single profile else false(Update multiple items).
2315 * @param int $componentId
2316 * Id for specific components like contribute, event etc.
2317 * @param null $component
2319 public static function setProfileDefaults(
2320 $contactId, &$fields, &$defaults,
2321 $singleProfile = TRUE, $componentId = NULL, $component = NULL
2323 if (!$componentId) {
2324 //get the contact details
2325 list($contactDetails, $options) = CRM_Contact_BAO_Contact
::getHierContactDetails($contactId, $fields);
2326 $details = CRM_Utils_Array
::value($contactId, $contactDetails);
2327 $multipleFields = array('website' => 'url');
2329 //start of code to set the default values
2330 foreach ($fields as $name => $field) {
2331 // skip pseudo fields
2332 if (substr($name, 0, 9) == 'phone_ext') {
2336 //set the field name depending upon the profile mode(single/multiple)
2337 if ($singleProfile) {
2341 $fldName = "field[$contactId][$name]";
2344 if ($name == 'group') {
2345 CRM_Contact_Form_Edit_TagsAndGroups
::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups
::GROUP
, $fldName);
2347 if ($name == 'tag') {
2348 CRM_Contact_Form_Edit_TagsAndGroups
::setDefaults($contactId, $defaults, CRM_Contact_Form_Edit_TagsAndGroups
::TAG
, $fldName);
2351 if (!empty($details[$name]) ||
isset($details[$name])) {
2352 //to handle custom data (checkbox) to be written
2353 // to handle birth/deceased date, greeting_type and few other fields
2354 if (in_array($name, CRM_Contact_BAO_Contact
::$_greetingTypes)) {
2355 $defaults[$fldName] = $details[$name . '_id'];
2356 $defaults[$name . '_custom'] = $details[$name . '_custom'];
2358 elseif ($name == 'preferred_communication_method') {
2359 $v = $details[$name];
2360 if (!is_array($details[$name])) {
2361 $v = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $v);
2363 foreach ($v as $item) {
2365 $defaults[$fldName . "[$item]"] = 1;
2369 elseif ($name == 'contact_sub_type') {
2370 $defaults[$fldName] = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, trim($details[$name], CRM_Core_DAO
::VALUE_SEPARATOR
));
2372 elseif ($name == 'world_region') {
2373 $defaults[$fldName] = $details['worldregion_id'];
2375 elseif ($customFieldId = CRM_Core_BAO_CustomField
::getKeyID($name)) {
2376 // @todo retrieving the custom fields here seems obsolete - $field holds more data for the fields.
2377 $customFields = CRM_Core_BAO_CustomField
::getFields(CRM_Utils_Array
::value('contact_type', $details));
2379 // hack to add custom data for components
2380 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
2381 foreach ($components as $value) {
2382 $customFields = CRM_Utils_Array
::crmArrayMerge($customFields,
2383 CRM_Core_BAO_CustomField
::getFieldsForImport($value)
2387 switch ($customFields[$customFieldId]['html_type']) {
2388 case 'Multi-Select State/Province':
2389 case 'Multi-Select Country':
2390 case 'Multi-Select':
2391 $v = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $details[$name]);
2392 foreach ($v as $item) {
2394 $defaults[$fldName][$item] = $item;
2400 $v = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $details[$name]);
2401 foreach ($v as $item) {
2403 $defaults[$fldName][$item] = 1;
2404 // seems like we need this for QF style checkboxes in profile where its multiindexed
2406 $defaults["{$fldName}[{$item}]"] = 1;
2412 $defaults[$fldName] = $details[$name];
2417 $defaults[$fldName] = $details[$name];
2421 $blocks = array('email', 'phone', 'im', 'openid');
2422 list($fieldName, $locTypeId, $phoneTypeId) = CRM_Utils_System
::explode('-', $name, 3);
2423 if (!in_array($fieldName, $multipleFields)) {
2424 if (is_array($details)) {
2425 foreach ($details as $key => $value) {
2426 // when we fixed CRM-5319 - get primary loc
2427 // type as per loc field and removed below code.
2428 $primaryLocationType = FALSE;
2429 if ($locTypeId == 'Primary') {
2430 if (is_array($value) && array_key_exists($fieldName, $value)) {
2431 $primaryLocationType = TRUE;
2432 if (in_array($fieldName, $blocks)) {
2433 $locTypeId = CRM_Contact_BAO_Contact
::getPrimaryLocationType($contactId, FALSE, $fieldName);
2436 $locTypeId = CRM_Contact_BAO_Contact
::getPrimaryLocationType($contactId, FALSE, 'address');
2441 // fixed for CRM-665
2442 if (is_numeric($locTypeId)) {
2443 if ($primaryLocationType ||
$locTypeId == CRM_Utils_Array
::value('location_type_id', $value)) {
2444 if (!empty($value[$fieldName])) {
2445 //to handle stateprovince and country
2446 if ($fieldName == 'state_province') {
2447 $defaults[$fldName] = $value['state_province_id'];
2449 elseif ($fieldName == 'county') {
2450 $defaults[$fldName] = $value['county_id'];
2452 elseif ($fieldName == 'country') {
2453 if (!isset($value['country_id']) ||
!$value['country_id']) {
2454 $config = CRM_Core_Config
::singleton();
2455 if ($config->defaultContactCountry
) {
2456 $defaults[$fldName] = $config->defaultContactCountry
;
2460 $defaults[$fldName] = $value['country_id'];
2463 elseif ($fieldName == 'phone') {
2465 if (isset($value['phone'][$phoneTypeId])) {
2466 $defaults[$fldName] = $value['phone'][$phoneTypeId];
2468 if (isset($value['phone_ext'][$phoneTypeId])) {
2469 $defaults[str_replace('phone', 'phone_ext', $fldName)] = $value['phone_ext'][$phoneTypeId];
2473 $phoneDefault = CRM_Utils_Array
::value('phone', $value);
2475 if (!is_array($phoneDefault)) {
2476 $defaults[$fldName] = $phoneDefault;
2480 elseif ($fieldName == 'email') {
2481 //adding the first email (currently we don't support multiple emails of same location type)
2482 $defaults[$fldName] = $value['email'];
2484 elseif ($fieldName == 'im') {
2485 //adding the first im (currently we don't support multiple ims of same location type)
2486 $defaults[$fldName] = $value['im'];
2487 $defaults[$fldName . '-provider_id'] = $value['im_provider_id'];
2490 $defaults[$fldName] = $value[$fieldName];
2493 elseif (substr($fieldName, 0, 14) === 'address_custom' &&
2494 CRM_Utils_Array
::value(substr($fieldName, 8), $value)
2496 $defaults[$fldName] = $value[substr($fieldName, 8)];
2504 if (is_array($details)) {
2505 if ($fieldName === 'url'
2506 && !empty($details['website'])
2507 && !empty($details['website'][$locTypeId])
2509 $defaults[$fldName] = CRM_Utils_Array
::value('url', $details['website'][$locTypeId]);
2517 // Handling Contribution Part of the batch profile
2518 if (CRM_Core_Permission
::access('CiviContribute') && $component == 'Contribute') {
2519 self
::setComponentDefaults($fields, $componentId, $component, $defaults);
2522 // Handling Event Participation Part of the batch profile
2523 if (CRM_Core_Permission
::access('CiviEvent') && $component == 'Event') {
2524 self
::setComponentDefaults($fields, $componentId, $component, $defaults);
2527 // Handling membership Part of the batch profile
2528 if (CRM_Core_Permission
::access('CiviMember') && $component == 'Membership') {
2529 self
::setComponentDefaults($fields, $componentId, $component, $defaults);
2532 // Handling Activity Part of the batch profile
2533 if ($component == 'Activity') {
2534 self
::setComponentDefaults($fields, $componentId, $component, $defaults);
2537 // Handling Case Part of the batch profile
2538 if (CRM_Core_Permission
::access('CiviCase') && $component == 'Case') {
2539 self
::setComponentDefaults($fields, $componentId, $component, $defaults);
2544 * Get profiles by type eg: pure Individual etc
2546 * @param array $types
2547 * Associative array of types eg: types('Individual').
2548 * @param bool $onlyPure
2549 * True if only pure profiles are required.
2552 * associative array of profiles
2554 public static function getProfiles($types, $onlyPure = FALSE) {
2555 $profiles = array();
2556 $ufGroups = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_UFField', 'uf_group_id');
2558 CRM_Utils_Hook
::aclGroup(CRM_Core_Permission
::ADMIN
, NULL, 'civicrm_uf_group', $ufGroups, $ufGroups);
2560 // Exclude Batch Data Entry profiles - CRM-10901
2561 $batchProfiles = CRM_Core_BAO_UFGroup
::getBatchProfiles();
2563 foreach ($ufGroups as $id => $title) {
2564 $ptype = CRM_Core_BAO_UFField
::getProfileType($id, FALSE, $onlyPure);
2565 if (in_array($ptype, $types) && !array_key_exists($id, $batchProfiles)) {
2566 $profiles[$id] = $title;
2573 * Check whether a profile is valid combination of
2574 * required and/or optional profile types
2576 * @param array $required
2577 * Array of types those are required.
2578 * @param array $optional
2579 * Array of types those are optional.
2582 * associative array of profiles
2584 public static function getValidProfiles($required, $optional = NULL) {
2585 if (!is_array($required) ||
empty($required)) {
2589 $profiles = array();
2590 $ufGroups = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_UFField', 'uf_group_id');
2592 CRM_Utils_Hook
::aclGroup(CRM_Core_Permission
::ADMIN
, NULL, 'civicrm_uf_group', $ufGroups, $ufGroups);
2594 foreach ($ufGroups as $id => $title) {
2595 $type = CRM_Core_BAO_UFField
::checkValidProfileType($id, $required, $optional);
2597 $profiles[$id] = $title;
2605 * Check whether a profile is valid combination of
2606 * required profile fields
2608 * @param array $ufId
2609 * Integer id of the profile.
2610 * @param array $required
2611 * Array of fields those are required in the profile.
2614 * associative array of profiles
2616 public static function checkValidProfile($ufId, $required = NULL) {
2617 $validProfile = FALSE;
2619 return $validProfile;
2622 if (!CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $ufId, 'is_active')) {
2623 return $validProfile;
2626 $profileFields = self
::getFields($ufId, FALSE, CRM_Core_Action
::VIEW
, NULL,
2627 NULL, FALSE, NULL, FALSE, NULL,
2628 CRM_Core_Permission
::CREATE
, NULL
2631 $validProfile = array();
2632 if (!empty($profileFields)) {
2633 $fields = array_keys($profileFields);
2634 foreach ($fields as $val) {
2635 foreach ($required as $key => $field) {
2636 if (strpos($val, $field) === 0) {
2637 unset($required[$key]);
2642 $validProfile = (empty($required)) ?
TRUE : FALSE;
2645 return $validProfile;
2649 * Get default value for Register.
2651 * @param array $fields
2652 * @param array $defaults
2656 public static function setRegisterDefaults(&$fields, &$defaults) {
2657 $config = CRM_Core_Config
::singleton();
2658 foreach ($fields as $name => $field) {
2659 if (substr($name, 0, 8) == 'country-') {
2660 if (!empty($config->defaultContactCountry
)) {
2661 $defaults[$name] = $config->defaultContactCountry
;
2664 elseif (substr($name, 0, 15) == 'state_province-') {
2665 if (!empty($config->defaultContactStateProvince
)) {
2666 $defaults[$name] = $config->defaultContactStateProvince
;
2674 * make a copy of a profile, including
2675 * all the fields in the profile
2678 * The profile id to copy.
2680 * @return \CRM_Core_DAO
2682 public static function copy($id) {
2683 $maxId = CRM_Core_DAO
::singleValueQuery("SELECT max(id) FROM civicrm_uf_group");
2685 $title = ts('[Copy id %1]', array(1 => $maxId +
1));
2688 'title' => ' ' . $title,
2689 'name' => '__Copy_id_' . ($maxId +
1) . '_',
2693 $copy = &CRM_Core_DAO
::copyGeneric('CRM_Core_DAO_UFGroup',
2699 if ($pos = strrpos($copy->name
, "_{$id}")) {
2700 $copy->name
= substr_replace($copy->name
, '', $pos);
2702 $copy->name
= CRM_Utils_String
::munge($copy->name
, '_', 56) . "_{$copy->id}";
2705 $copyUFJoin = &CRM_Core_DAO
::copyGeneric('CRM_Core_DAO_UFJoin',
2706 array('uf_group_id' => $id),
2707 array('uf_group_id' => $copy->id
),
2712 $copyUFField = &CRM_Core_DAO
::copyGeneric('CRM_Core_BAO_UFField',
2713 array('uf_group_id' => $id),
2714 array('uf_group_id' => $copy->id
)
2717 $maxWeight = CRM_Utils_Weight
::getMax('CRM_Core_DAO_UFJoin', NULL, 'weight');
2721 UPDATE civicrm_uf_join
2723 WHERE uf_group_id = %2
2724 AND ( entity_id IS NULL OR entity_id <= 0 )
2727 1 => array($maxWeight +
1, 'Integer'),
2728 2 => array($copy->id
, 'Integer'),
2730 CRM_Core_DAO
::executeQuery($query, $p);
2731 if ($copy->is_reserved
) {
2732 $query = "UPDATE civicrm_uf_group SET is_reserved = 0 WHERE id = %1";
2733 $params = array(1 => array($copy->id
, 'Integer'));
2734 CRM_Core_DAO
::executeQuery($query, $params);
2736 CRM_Utils_Hook
::copy('UFGroup', $copy);
2742 * Process that send notification e-mails
2744 * @param int $contactID
2746 * @param array $values
2747 * Associative array of name/value pair.
2749 public static function commonSendMail($contactID, &$values) {
2750 if (!$contactID ||
!$values) {
2754 $template = CRM_Core_Smarty
::singleton();
2756 $displayName = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_Contact',
2761 self
::profileDisplay($values['id'], $values['values'], $template);
2762 $emailList = explode(',', $values['email']);
2764 $contactLink = CRM_Utils_System
::url('civicrm/contact/view',
2765 "reset=1&cid=$contactID",
2766 TRUE, NULL, FALSE, FALSE, TRUE
2769 //get the default domain email address.
2770 list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain
::getNameAndEmail();
2772 if (!$domainEmailAddress ||
$domainEmailAddress == 'info@EXAMPLE.ORG') {
2773 $fixUrl = CRM_Utils_System
::url('civicrm/admin/domain', 'action=update&reset=1');
2774 CRM_Core_Error
::fatal(ts('The site administrator needs to enter a valid \'FROM Email Address\' in <a href="%1">Administer CiviCRM » 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)));
2777 foreach ($emailList as $emailTo) {
2778 // FIXME: take the below out of the foreach loop
2779 CRM_Core_BAO_MessageTemplate
::sendTemplate(
2781 'groupName' => 'msg_tpl_workflow_uf',
2782 'valueName' => 'uf_notify',
2783 'contactId' => $contactID,
2784 'tplParams' => array(
2785 'displayName' => $displayName,
2786 'currentDate' => date('r'),
2787 'contactLink' => $contactLink,
2789 'from' => "$domainEmailName <$domainEmailAddress>",
2790 'toEmail' => $emailTo,
2797 * Given a contact id and a group id, returns the field values from the db
2798 * for this group and notify email only if group's notify field is
2799 * set and field values are not empty
2805 * @param array $params
2806 * @param bool $skipCheck
2810 public function checkFieldsEmptyValues($gid, $cid, $params, $skipCheck = FALSE) {
2812 if (CRM_Core_BAO_UFGroup
::filterUFGroups($gid, $cid) ||
$skipCheck) {
2814 $fields = CRM_Core_BAO_UFGroup
::getFields($gid, FALSE, CRM_Core_Action
::VIEW
);
2815 CRM_Core_BAO_UFGroup
::getValues($cid, $fields, $values, FALSE, $params, TRUE);
2817 $email = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'notify');
2819 if (!empty($values) &&
2824 'values' => $values,
2835 * Assign uf fields to template.
2839 * @param array $values
2840 * @param CRM_Core_Smarty $template
2842 static public function profileDisplay($gid, $values, $template) {
2843 $groupTitle = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'title');
2844 $template->assign('grouptitle', $groupTitle);
2845 if (count($values)) {
2846 $template->assign('values', $values);
2851 * Format fields for dupe Contact Matching.
2853 * @param array $params
2855 * @param int $contactId
2858 * associated formatted array
2860 public static function formatFields($params, $contactId = NULL) {
2862 // get the primary location type id and email
2863 list($name, $primaryEmail, $primaryLocationType) = CRM_Contact_BAO_Contact_Location
::getEmailDetails($contactId);
2866 $defaultLocationType = CRM_Core_BAO_LocationType
::getDefault();
2867 $primaryLocationType = $defaultLocationType->id
;
2871 $locationType = array();
2873 $primaryLocation = 0;
2874 foreach ($params as $key => $value) {
2875 list($fieldName, $locTypeId, $phoneTypeId) = explode('-', $key);
2877 if ($locTypeId == 'Primary') {
2878 $locTypeId = $primaryLocationType;
2881 if (is_numeric($locTypeId)) {
2882 if (!in_array($locTypeId, $locationType)) {
2883 $locationType[$count] = $locTypeId;
2886 $loc = CRM_Utils_Array
::key($locTypeId, $locationType);
2888 $data['location'][$loc]['location_type_id'] = $locTypeId;
2890 // if we are getting in a new primary email, dont overwrite the new one
2891 if ($locTypeId == $primaryLocationType) {
2892 if (!empty($params['email-' . $primaryLocationType])) {
2893 $data['location'][$loc]['email'][$loc]['email'] = $fields['email-' . $primaryLocationType];
2895 elseif (isset($primaryEmail)) {
2896 $data['location'][$loc]['email'][$loc]['email'] = $primaryEmail;
2902 $data['location'][$loc]['is_primary'] = 1;
2904 if ($fieldName == 'phone') {
2906 $data['location'][$loc]['phone'][$loc]['phone_type_id'] = $phoneTypeId;
2909 $data['location'][$loc]['phone'][$loc]['phone_type_id'] = '';
2911 $data['location'][$loc]['phone'][$loc]['phone'] = $value;
2913 elseif ($fieldName == 'email') {
2914 $data['location'][$loc]['email'][$loc]['email'] = $value;
2916 elseif ($fieldName == 'im') {
2917 $data['location'][$loc]['im'][$loc]['name'] = $value;
2920 if ($fieldName === 'state_province') {
2921 $data['location'][$loc]['address']['state_province_id'] = $value;
2923 elseif ($fieldName === 'country') {
2924 $data['location'][$loc]['address']['country_id'] = $value;
2927 $data['location'][$loc]['address'][$fieldName] = $value;
2932 // TODO: prefix, suffix and gender translation may no longer be necessary - check inputs
2933 if ($key === 'individual_suffix') {
2934 $data['suffix_id'] = $value;
2936 elseif ($key === 'individual_prefix') {
2937 $data['prefix_id'] = $value;
2939 elseif ($key === 'gender') {
2940 $data['gender_id'] = $value;
2942 elseif (substr($key, 0, 6) === 'custom') {
2943 if ($customFieldID = CRM_Core_BAO_CustomField
::getKeyID($key)) {
2945 if ($customFields[$customFieldID]['html_type'] == 'CheckBox') {
2946 $value = implode(CRM_Core_DAO
::VALUE_SEPARATOR
, array_keys($value));
2948 // fix the date field
2949 if ($customFields[$customFieldID]['data_type'] == 'Date') {
2950 $date = CRM_Utils_Date
::format($value);
2957 $data['custom'][$customFieldID] = array(
2960 'extends' => $customFields[$customFieldID]['extends'],
2961 'type' => $customFields[$customFieldID]['data_type'],
2962 'custom_field_id' => $customFieldID,
2966 elseif ($key == 'edit') {
2970 $data[$key] = $value;
2975 if (!$primaryLocation) {
2977 $data['location'][$loc]['email'][$loc]['email'] = $primaryEmail;
2984 * Calculate the profile type 'group_type' as per profile fields.
2988 * @param bool $includeTypeValues
2989 * @param int $ignoreFieldId
2990 * Ignore particular profile field.
2993 * list of calculated group type
2995 public static function calculateGroupType($gId, $includeTypeValues = FALSE, $ignoreFieldId = NULL) {
2996 //get the profile fields.
2997 $ufFields = self
::getFields($gId, FALSE, NULL, NULL, NULL, TRUE, NULL, TRUE);
2998 return self
::_calculateGroupType($ufFields, $includeTypeValues, $ignoreFieldId);
3002 * Calculate the profile type 'group_type' as per profile fields.
3005 * @param bool $includeTypeValues
3006 * @param int $ignoreFieldId
3007 * Ignore perticular profile field.
3010 * list of calculated group type
3012 public static function _calculateGroupType($ufFields, $includeTypeValues = FALSE, $ignoreFieldId = NULL) {
3013 $groupType = $groupTypeValues = $customFieldIds = array();
3014 if (!empty($ufFields)) {
3015 foreach ($ufFields as $fieldName => $fieldValue) {
3016 //ignore field from group type when provided.
3017 //in case of update profile field.
3018 if ($ignoreFieldId && ($ignoreFieldId == $fieldValue['field_id'])) {
3021 if (!in_array($fieldValue['field_type'], $groupType)) {
3022 $groupType[$fieldValue['field_type']] = $fieldValue['field_type'];
3025 if ($includeTypeValues && ($fldId = CRM_Core_BAO_CustomField
::getKeyID($fieldName))) {
3026 $customFieldIds[$fldId] = $fldId;
3031 if (!empty($customFieldIds)) {
3032 $query = 'SELECT DISTINCT(cg.id), cg.extends, cg.extends_entity_column_id, cg.extends_entity_column_value FROM civicrm_custom_group cg LEFT JOIN civicrm_custom_field cf ON cf.custom_group_id = cg.id WHERE cg.extends_entity_column_value IS NOT NULL AND cf.id IN (' . implode(',', $customFieldIds) . ')';
3034 $customGroups = CRM_Core_DAO
::executeQuery($query);
3035 while ($customGroups->fetch()) {
3036 if (!$customGroups->extends_entity_column_value
) {
3040 $groupTypeName = "{$customGroups->extends}Type";
3041 if ($customGroups->extends == 'Participant' && $customGroups->extends_entity_column_id
) {
3042 $groupTypeName = CRM_Core_PseudoConstant
::getName('CRM_Core_DAO_CustomGroup', 'extends_entity_column_id', $customGroups->extends_entity_column_id
);
3045 foreach (explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $customGroups->extends_entity_column_value
) as $val) {
3047 $groupTypeValues[$groupTypeName][$val] = $val;
3052 if (!empty($groupTypeValues)) {
3053 $groupType = array_merge($groupType, $groupTypeValues);
3061 * Update the profile type 'group_type' as per profile fields including group types and group subtype values.
3062 * Build and store string like: group_type1,group_type2[VALUE_SEPERATOR]group_type1Type:1:2:3,group_type2Type:1:2
3065 * BirthDate + Email Individual,Contact
3066 * BirthDate + Subject Individual,Activity
3067 * BirthDate + Subject + SurveyOnlyField Individual,Activity\0ActivityType:28
3068 * BirthDate + Subject + SurveyOnlyField + PhoneOnlyField (Not allowed)
3069 * BirthDate + SurveyOnlyField Individual,Activity\0ActivityType:28
3070 * BirthDate + Subject + SurveyOrPhoneField Individual,Activity\0ActivityType:2:28
3071 * BirthDate + SurveyOrPhoneField Individual,Activity\0ActivityType:2:28
3072 * BirthDate + SurveyOrPhoneField + SurveyOnlyField Individual,Activity\0ActivityType:2:28
3073 * BirthDate + StudentField + Subject + SurveyOnlyField Individual,Activity,Student\0ActivityType:28
3076 * @param array $groupTypes
3077 * With key having group type names.
3081 public static function updateGroupTypes($gId, $groupTypes = array()) {
3082 if (!is_array($groupTypes) ||
!$gId) {
3086 // If empty group types set group_type as 'null'
3087 if (empty($groupTypes)) {
3088 return CRM_Core_DAO
::setFieldValue('CRM_Core_DAO_UFGroup', $gId, 'group_type', 'null');
3091 $componentGroupTypes = array('Contribution', 'Participant', 'Membership', 'Activity', 'Case');
3092 $validGroupTypes = array_merge(array(
3097 ), $componentGroupTypes, CRM_Contact_BAO_ContactType
::subTypes());
3099 $gTypes = $gTypeValues = array();
3101 $participantExtends = array('ParticipantRole', 'ParticipantEventName', 'ParticipantEventType');
3102 // Get valid group type and group subtypes
3103 foreach ($groupTypes as $groupType => $value) {
3104 if (in_array($groupType, $validGroupTypes) && !in_array($groupType, $gTypes)) {
3105 $gTypes[] = $groupType;
3110 if (in_array($groupType, $participantExtends)) {
3111 $subTypesOf = $groupType;
3113 elseif (strpos($groupType, 'Type') > 0) {
3114 $subTypesOf = substr($groupType, 0, strpos($groupType, 'Type'));
3120 if (!empty($value) &&
3121 (in_array($subTypesOf, $componentGroupTypes) ||
3122 in_array($subTypesOf, $participantExtends)
3125 $gTypeValues[$subTypesOf] = $groupType . ":" . implode(':', $value);
3129 if (empty($gTypes)) {
3133 // Build String to store group types and group subtypes
3134 $groupTypeString = implode(',', $gTypes);
3135 if (!empty($gTypeValues)) {
3136 $groupTypeString .= CRM_Core_DAO
::VALUE_SEPARATOR
. implode(',', $gTypeValues);
3139 return CRM_Core_DAO
::setFieldValue('CRM_Core_DAO_UFGroup', $gId, 'group_type', $groupTypeString);
3143 * Create a "group_type" string.
3145 * @param array $coreTypes
3146 * E.g. array('Individual','Contact','Student').
3147 * @param array $subTypes
3148 * E.g. array('ActivityType' => array(7, 11)).
3149 * @param string $delim
3152 * @throws CRM_Core_Exception
3154 public static function encodeGroupType($coreTypes, $subTypes, $delim = CRM_Core_DAO
::VALUE_SEPARATOR
) {
3155 $groupTypeExpr = '';
3157 $groupTypeExpr .= implode(',', $coreTypes);
3160 //CRM-15427 Allow Multiple subtype filtering
3161 //if (count($subTypes) > 1) {
3162 //throw new CRM_Core_Exception("Multiple subtype filtering is not currently supported by widget.");
3164 foreach ($subTypes as $subType => $subTypeIds) {
3165 $groupTypeExpr .= $delim . $subType . ':' . implode(':', $subTypeIds);
3168 return $groupTypeExpr;
3172 * setDefault componet specific profile fields.
3174 * @param array $fields
3176 * @param int $componentId
3178 * @param string $component
3180 * @param array $defaults
3181 * An array of default values.
3183 * @param bool $isStandalone
3185 public static function setComponentDefaults(&$fields, $componentId, $component, &$defaults, $isStandalone = FALSE) {
3186 if (!$componentId ||
3187 !in_array($component, array('Contribute', 'Membership', 'Event', 'Activity', 'Case'))
3192 $componentBAO = $componentSubType = NULL;
3193 switch ($component) {
3195 $componentBAO = 'CRM_Member_BAO_Membership';
3196 $componentBAOName = 'Membership';
3197 $componentSubType = array('membership_type_id');
3201 $componentBAO = 'CRM_Contribute_BAO_Contribution';
3202 $componentBAOName = 'Contribution';
3203 $componentSubType = array('financial_type_id');
3207 $componentBAO = 'CRM_Event_BAO_Participant';
3208 $componentBAOName = 'Participant';
3209 $componentSubType = array('role_id', 'event_id', 'event_type_id');
3213 $componentBAO = 'CRM_Activity_BAO_Activity';
3214 $componentBAOName = 'Activity';
3215 $componentSubType = array('activity_type_id');
3219 $componentBAO = 'CRM_Case_BAO_Case';
3220 $componentBAOName = 'Case';
3221 $componentSubType = array('case_type_id');
3226 $params = array('id' => $componentId);
3228 //get the component values.
3229 CRM_Core_DAO
::commonRetrieve($componentBAO, $params, $values);
3230 if ($componentBAOName == 'Participant') {
3231 $values +
= array('event_type_id' => CRM_Core_DAO
::getFieldValue('CRM_Event_DAO_Event', $values['event_id'], 'event_type_id'));
3234 $formattedGroupTree = array();
3236 foreach ($fields as $name => $field) {
3237 $fldName = $isStandalone ?
$name : "field[$componentId][$name]";
3238 if (array_key_exists($name, $values)) {
3239 $defaults[$fldName] = $values[$name];
3241 elseif ($name == 'participant_note') {
3242 $noteDetails = CRM_Core_BAO_Note
::getNote($componentId, 'civicrm_participant');
3243 $defaults[$fldName] = array_pop($noteDetails);
3245 elseif (in_array($name, array(
3247 'payment_instrument',
3248 'participant_status',
3251 $defaults[$fldName] = $values["{$name}_id"];
3253 elseif ($name == 'membership_type') {
3254 // since membership_type field is a hierselect -
3255 $defaults[$fldName][0]
3256 = CRM_Core_DAO
::getFieldValue('CRM_Member_DAO_MembershipType', $values['membership_type_id'], 'member_of_contact_id', 'id');
3257 $defaults[$fldName][1] = $values['membership_type_id'];
3259 elseif ($name == 'membership_status') {
3260 $defaults[$fldName] = $values['status_id'];
3262 elseif ($name == 'case_status') {
3263 $defaults[$fldName] = $values['case_status_id'];
3265 elseif (CRM_Core_BAO_CustomField
::getKeyID($name, TRUE) !== array(NULL, NULL)) {
3266 if (empty($formattedGroupTree)) {
3267 //get the groupTree as per subTypes.
3268 $groupTree = array();
3269 foreach ($componentSubType as $subType) {
3270 $subTree = CRM_Core_BAO_CustomGroup
::getTree($componentBAOName, NULL,
3271 $componentId, 0, $values[$subType]
3273 $groupTree = CRM_Utils_Array
::crmArrayMerge($groupTree, $subTree);
3275 $formattedGroupTree = CRM_Core_BAO_CustomGroup
::formatGroupTree($groupTree, 1);
3276 CRM_Core_BAO_CustomGroup
::setDefaults($formattedGroupTree, $defaults);
3279 //FIX ME: We need to loop defaults, but once we move to custom_1_x convention this code can be simplified.
3280 foreach ($defaults as $customKey => $customValue) {
3281 if ($customFieldDetails = CRM_Core_BAO_CustomField
::getKeyID($customKey, TRUE)) {
3282 if ($name == 'custom_' . $customFieldDetails[0]) {
3284 //hack to set default for checkbox
3285 //basically this is for weired field name like field[33][custom_19]
3286 //we are converting this field name to array structure and assign value.
3289 foreach ($formattedGroupTree as $tree) {
3290 if (!empty($tree['fields'][$customFieldDetails[0]])) {
3291 if ('CheckBox' == CRM_Utils_Array
::value('html_type', $tree['fields'][$customFieldDetails[0]])) {
3293 $defaults['field'][$componentId][$name] = $customValue;
3296 elseif (CRM_Utils_Array
::value('data_type', $tree['fields'][$customFieldDetails[0]]) == 'Date') {
3299 // CRM-6681, $default contains formatted date, time values.
3300 $defaults[$fldName] = $customValue;
3301 if (!empty($defaults[$customKey . '_time'])) {
3302 $defaults['field'][$componentId][$name . '_time'] = $defaults[$customKey . '_time'];
3308 if (!$skipValue ||
$isStandalone) {
3309 $defaults[$fldName] = $customValue;
3311 unset($defaults[$customKey]);
3317 elseif (isset($values[$fldName])) {
3318 $defaults[$fldName] = $values[$fldName];
3324 * Retrieve groups of profiles.
3326 * @param int $profileID
3327 * Id of the profile.
3332 public static function profileGroups($profileID) {
3333 $groupTypes = array();
3334 $profileTypes = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $profileID, 'group_type');
3335 if ($profileTypes) {
3336 $groupTypeParts = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $profileTypes);
3337 $groupTypes = explode(',', $groupTypeParts[0]);
3343 * Alter contact params by filtering existing subscribed groups and returns
3344 * unsubscribed groups array for subscription.
3346 * @param array $params
3348 * @param int $contactId
3352 * This contains array of groups for subscription
3354 public static function getDoubleOptInGroupIds(&$params, $contactId = NULL) {
3355 $config = CRM_Core_Config
::singleton();
3356 $subscribeGroupIds = array();
3358 // process further only if profileDoubleOptIn enabled and if groups exist
3359 if (!array_key_exists('group', $params) ||
3360 !self
::isProfileDoubleOptin() ||
3361 CRM_Utils_System
::isNull($params['group'])
3363 return $subscribeGroupIds;
3366 //check if contact email exist.
3368 foreach ($params as $name => $value) {
3369 if (strpos($name, 'email-') !== FALSE) {
3375 //Proceed furthur only if email present
3377 return $subscribeGroupIds;
3380 //do check for already subscriptions.
3381 $contactGroups = array();
3385 FROM civicrm_group_contact
3386 WHERE status = 'Added'
3387 AND contact_id = %1";
3389 $dao = CRM_Core_DAO
::executeQuery($query, array(1 => array($contactId, 'Integer')));
3390 while ($dao->fetch()) {
3391 $contactGroups[$dao->group_id
] = $dao->group_id
;
3395 //since we don't have names, compare w/ label.
3396 $mailingListGroupType = array_search('Mailing List', CRM_Core_OptionGroup
::values('group_type'));
3398 //actual processing start.
3399 foreach ($params['group'] as $groupId => $isSelected) {
3400 //unset group those are not selected.
3402 unset($params['group'][$groupId]);
3406 $groupTypes = explode(CRM_Core_DAO
::VALUE_SEPARATOR
,
3407 CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_Group', $groupId, 'group_type', 'id')
3409 //get only mailing type group and unset it from params
3410 if (in_array($mailingListGroupType, $groupTypes) && !in_array($groupId, $contactGroups)) {
3411 $subscribeGroupIds[$groupId] = $groupId;
3412 unset($params['group'][$groupId]);
3416 return $subscribeGroupIds;
3420 * Check if we are rendering mixed profiles.
3422 * @param array $profileIds
3423 * Associated array of profile ids.
3426 * true if profile is mixed
3428 public static function checkForMixProfiles($profileIds) {
3429 $mixProfile = FALSE;
3431 $contactTypes = array('Individual', 'Household', 'Organization');
3432 $subTypes = CRM_Contact_BAO_ContactType
::subTypes();
3434 $components = array('Contribution', 'Participant', 'Membership', 'Activity');
3436 $typeCount = array('ctype' => array(), 'subtype' => array());
3437 foreach ($profileIds as $gid) {
3438 $profileType = CRM_Core_BAO_UFField
::getProfileType($gid);
3439 // ignore profile of type Contact
3440 if ($profileType == 'Contact') {
3443 if (in_array($profileType, $contactTypes)) {
3444 if (!isset($typeCount['ctype'][$profileType])) {
3445 $typeCount['ctype'][$profileType] = 1;
3448 // check if we are rendering profile of different contact types
3449 if (count($typeCount['ctype']) == 2) {
3454 elseif (in_array($profileType, $components)) {
3459 if (!isset($typeCount['subtype'][$profileType])) {
3460 $typeCount['subtype'][$profileType] = 1;
3462 // check if we are rendering profile of different contact sub types
3463 if (count($typeCount['subtype']) == 2) {
3473 * Determine of we show overlay profile or not.
3476 * true if profile should be shown else false
3478 public static function showOverlayProfile() {
3479 $showOverlay = TRUE;
3481 // get the id of overlay profile
3482 $overlayProfileId = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', 'summary_overlay', 'id', 'name');
3483 $query = "SELECT count(id) FROM civicrm_uf_field WHERE uf_group_id = {$overlayProfileId} AND visibility IN ('Public Pages', 'Public Pages and Listings') ";
3485 $count = CRM_Core_DAO
::singleValueQuery($query);
3487 //check if there are no public fields and use is anonymous
3488 $session = CRM_Core_Session
::singleton();
3489 if (!$count && !$session->get('userID')) {
3490 $showOverlay = FALSE;
3493 return $showOverlay;
3497 * Get group type values of the profile.
3499 * @param int $profileId
3500 * @param string $groupType
3505 public static function groupTypeValues($profileId, $groupType = NULL) {
3506 $groupTypeValue = array();
3507 $groupTypes = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $profileId, 'group_type');
3509 $groupTypeParts = explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $groupTypes);
3510 if (empty($groupTypeParts[1])) {
3511 return $groupTypeValue;
3513 $participantExtends = array('ParticipantRole', 'ParticipantEventName', 'ParticipantEventType');
3515 foreach (explode(',', $groupTypeParts[1]) as $groupTypeValues) {
3517 $valueParts = explode(':', $groupTypeValues);
3519 ($valueParts[0] != "{$groupType}Type" ||
3520 ($groupType == 'Participant' &&
3521 !in_array($valueParts[0], $participantExtends)
3527 foreach ($valueParts as $val) {
3528 if (CRM_Utils_Rule
::integer($val)) {
3529 $values[$val] = $val;
3532 if (!empty($values)) {
3533 $typeName = substr($valueParts[0], 0, -4);
3534 if (in_array($valueParts[0], $participantExtends)) {
3535 $typeName = $valueParts[0];
3537 $groupTypeValue[$typeName] = $values;
3541 return $groupTypeValue;
3545 * @return bool|object
3547 public static function isProfileDoubleOptin() {
3548 // check for double optin
3549 $config = CRM_Core_Config
::singleton();
3550 if (in_array('CiviMail', $config->enableComponents
)) {
3551 return Civi
::settings()->get('profile_double_optin');
3557 * @return bool|object
3559 public static function isProfileAddToGroupDoubleOptin() {
3560 // check for add to group double optin
3561 $config = CRM_Core_Config
::singleton();
3562 if (in_array('CiviMail', $config->enableComponents
)) {
3563 return Civi
::settings()->get('profile_add_to_group_double_optin');
3569 * Get profiles used for batch entry.
3572 * profileIds profile ids
3574 public static function getBatchProfiles() {
3576 FROM civicrm_uf_group
3577 WHERE name IN ('contribution_batch_entry', 'membership_batch_entry')";
3578 $dao = CRM_Core_DAO
::executeQuery($query);
3579 $profileIds = array();
3580 while ($dao->fetch()) {
3581 $profileIds[$dao->id
] = $dao->id
;
3587 * @todo what do I do?
3589 * @param $destination
3590 * @param bool $returnMultiSummaryFields
3592 * @return array|null
3594 public static function shiftMultiRecordFields(&$source, &$destination, $returnMultiSummaryFields = FALSE) {
3595 $multiSummaryFields = $returnMultiSummaryFields ?
array() : NULL;
3596 foreach ($source as $field => $properties) {
3597 if (!CRM_Core_BAO_CustomField
::getKeyID($field)) {
3600 if (CRM_Core_BAO_CustomField
::isMultiRecordField($field)) {
3601 $destination[$field] = $properties;
3602 if ($returnMultiSummaryFields) {
3603 if ($properties['is_multi_summary']) {
3604 $multiSummaryFields[$field] = $properties;
3607 unset($source[$field]);
3610 return $multiSummaryFields;
3614 * This is function is used to format pseudo fields.
3616 * @param array $fields
3617 * Associated array of profile fields.
3620 public static function reformatProfileFields(&$fields) {
3621 //reformat fields array
3622 foreach ($fields as $name => $field) {
3623 //reformat phone and extension field
3624 if (substr($field['name'], 0, 13) == 'phone_and_ext') {
3625 $fieldSuffix = str_replace('phone_and_ext-', '', $field['name']);
3627 // retain existing element properties and just update and replace key
3628 CRM_Utils_Array
::crmReplaceKey($fields, $name, "phone-{$fieldSuffix}");
3629 $fields["phone-{$fieldSuffix}"]['name'] = "phone-{$fieldSuffix}";
3630 $fields["phone-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone';
3632 // add additional phone extension field
3633 $fields["phone_ext-{$fieldSuffix}"] = $field;
3634 $fields["phone_ext-{$fieldSuffix}"]['title'] = $field['title'] . ' - ' . ts('Ext.');
3635 $fields["phone_ext-{$fieldSuffix}"]['name'] = "phone_ext-{$fieldSuffix}";
3636 $fields["phone_ext-{$fieldSuffix}"]['where'] = 'civicrm_phone.phone_ext';
3637 $fields["phone_ext-{$fieldSuffix}"]['skipDisplay'] = 1;
3638 //ignore required for extension field
3639 $fields["phone_ext-{$fieldSuffix}"]['is_required'] = 0;