3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2018 |
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-2018
35 * Form to process actions on the field aspect of Custom.
37 class CRM_UF_Form_Field
extends CRM_Core_Form
{
40 * The uf group id saved to the session for an update.
47 * The field id, used when editing the field.
54 * The set of fields that we can view/edit in the user field framework
61 * The title for field.
68 * The set of fields sent to the select element.
72 protected $_selectFields;
75 * store fields with if locationtype exits status.
79 protected $_hasLocationTypes;
82 * Is this profile has searchable field.
83 * or is any field having in selector true.
87 protected $_hasSearchableORInSelector;
90 * Set variables up before form is built.
94 public function preProcess() {
95 $this->_gid
= CRM_Utils_Request
::retrieve('gid', 'Positive', $this);
96 $this->_id
= CRM_Utils_Request
::retrieve('id', 'Positive', $this);
98 $this->_title
= CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $this->_gid
, 'title');
100 $this->setPageTitle(ts('Profile Field'));
102 $url = CRM_Utils_System
::url('civicrm/admin/uf/group/field',
103 "reset=1&action=browse&gid={$this->_gid}"
106 $session = CRM_Core_Session
::singleton();
107 $session->pushUserContext($url);
110 'title' => ts('CiviCRM Profile Fields'),
114 CRM_Utils_System
::appendBreadCrumb($breadCrumb);
117 $showBestResult = CRM_Utils_Request
::retrieve('sbr', 'Positive', CRM_Core_DAO
::$_nullArray);
118 if ($showBestResult) {
119 $this->assign('showBestResult', $showBestResult);
122 $this->_fields
= CRM_Contact_BAO_Contact
::importableFields('All', TRUE, TRUE, TRUE, TRUE, TRUE);
123 $this->_fields
= array_merge(CRM_Activity_BAO_Activity
::exportableFields('Activity'), $this->_fields
);
125 //unset campaign related fields.
126 if (isset($this->_fields
['activity_campaign_id'])) {
127 $this->_fields
['activity_campaign_id']['title'] = ts('Campaign');
128 if (isset($this->_fields
['activity_campaign'])) {
129 unset($this->_fields
['activity_campaign']);
133 if (CRM_Core_Permission
::access('CiviContribute')) {
134 $this->_fields
= array_merge(CRM_Contribute_BAO_Contribution
::getContributionFields(FALSE), $this->_fields
);
135 $this->_fields
= array_merge(CRM_Core_BAO_UFField
::getContribBatchEntryFields(), $this->_fields
);
138 if (CRM_Core_Permission
::access('CiviMember')) {
139 $this->_fields
= array_merge(CRM_Member_BAO_Membership
::getMembershipFields(), $this->_fields
);
142 if (CRM_Core_Permission
::access('CiviEvent')) {
143 $this->_fields
= array_merge(CRM_Event_BAO_Query
::getParticipantFields(), $this->_fields
);
146 if (CRM_Core_Permission
::access('CiviCase')) {
147 $this->_fields
= array_merge(CRM_Case_BAO_Query
::getFields(), $this->_fields
);
150 $this->_fields
= array_merge($this->_fields
, CRM_Contact_BAO_Query_Hook
::singleton()->getFields());
152 $this->_selectFields
= array();
153 foreach ($this->_fields
as $name => $field) {
154 // lets skip note for now since we dont support it
155 if ($name == 'note') {
158 $this->_selectFields
[$name] = $field['title'];
159 $this->_hasLocationTypes
[$name] = CRM_Utils_Array
::value('hasLocationType', $field);
162 // lets add group, tag and current_employer to this list
163 $this->_selectFields
['group'] = ts('Group(s)');
164 $this->_selectFields
['tag'] = ts('Tag(s)');
165 $this->_selectFields
['current_employer'] = ts('Current Employer');
166 $this->_selectFields
['phone_and_ext'] = ts('Phone and Extension');
168 //CRM-4363 check for in selector or searchable fields.
169 $this->_hasSearchableORInSelector
= CRM_Core_BAO_UFField
::checkSearchableORInSelector($this->_gid
);
171 $this->assign('fieldId', $this->_id
);
173 $fieldTitle = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFField', $this->_id
, 'label');
174 $this->assign('fieldTitle', $fieldTitle);
179 * Build the form object.
183 public function buildQuickForm() {
184 if ($this->_action
& CRM_Core_Action
::DELETE
) {
185 $this->addButtons(array(
188 'name' => ts('Delete Profile Field'),
189 'spacing' => ' ',
194 'name' => ts('Cancel'),
199 $addressCustomFields = array_keys(CRM_Core_BAO_CustomField
::getFieldsForImport('Address'));
201 if (isset($this->_id
)) {
202 $params = array('id' => $this->_id
);
203 CRM_Core_BAO_UFField
::retrieve($params, $defaults);
205 // set it to null if so (avoids crappy E_NOTICE errors below
206 $defaults['location_type_id'] = CRM_Utils_Array
::value('location_type_id', $defaults);
208 //CRM-20861 - Include custom fields defined for address to set its default location type to 0.
209 $specialFields = array_merge(CRM_Core_BAO_UFGroup
::getLocationFields(), $addressCustomFields);
210 if (!$defaults['location_type_id'] &&
211 $defaults["field_type"] != "Formatting" &&
212 in_array($defaults['field_name'], $specialFields)
214 $defaults['location_type_id'] = 0;
217 $defaults['field_name'] = array(
218 $defaults['field_type'],
219 ($defaults['field_type'] == "Formatting" ?
"" : $defaults['field_name']),
220 ($defaults['field_name'] == "url") ?
$defaults['website_type_id'] : $defaults['location_type_id'],
221 CRM_Utils_Array
::value('phone_type_id', $defaults),
223 $this->_gid
= $defaults['uf_group_id'];
226 $defaults['is_active'] = 1;
229 $otherModules = array_values(CRM_Core_BAO_UFGroup
::getUFJoinRecord($this->_gid
));
230 $this->assign('otherModules', $otherModules);
232 if ($this->_action
& CRM_Core_Action
::ADD
) {
233 $fieldValues = array('uf_group_id' => $this->_gid
);
234 $defaults['weight'] = CRM_Utils_Weight
::getDefaultWeight('CRM_Core_DAO_UFField', $fieldValues);
237 // lets trim all the whitespace
238 $this->applyFilter('__ALL__', 'trim');
240 //hidden field to catch the group id in profile
241 $this->add('hidden', 'group_id', $this->_gid
);
243 //hidden field to catch the field id in profile
244 $this->add('hidden', 'field_id', $this->_id
);
246 $fields = CRM_Core_BAO_UFField
::getAvailableFields($this->_gid
, $defaults);
248 $noSearchable = $hasWebsiteTypes = array();
250 foreach ($fields as $key => $value) {
251 foreach ($value as $key1 => $value1) {
252 //CRM-2676, replacing the conflict for same custom field name from different custom group.
253 if ($customFieldId = CRM_Core_BAO_CustomField
::getKeyID($key1)) {
254 $customGroupId = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomField', $customFieldId, 'custom_group_id');
255 $customGroupName = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomGroup', $customGroupId, 'title');
256 $this->_mapperFields
[$key][$key1] = $value1['title'] . ' :: ' . $customGroupName;
257 if (in_array($key1, $addressCustomFields)) {
258 $noSearchable[] = $value1['title'] . ' :: ' . $customGroupName;
262 $this->_mapperFields
[$key][$key1] = $value1['title'];
264 $hasLocationTypes[$key][$key1] = CRM_Utils_Array
::value('hasLocationType', $value1);
265 $hasWebsiteTypes[$key][$key1] = CRM_Utils_Array
::value('hasWebsiteType', $value1);
266 // hide the 'is searchable' field for 'File' custom data
267 if (isset($value1['data_type']) &&
268 isset($value1['html_type']) &&
269 (($value1['data_type'] == 'File' && $value1['html_type'] == 'File')
270 ||
($value1['data_type'] == 'Link' && $value1['html_type'] == 'Link')
273 if (!in_array($value1['title'], $noSearchable)) {
274 $noSearchable[] = $value1['title'];
279 $this->assign('noSearchable', $noSearchable);
281 $this->_location_types
= CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Address', 'location_type_id');
282 $defaultLocationType = CRM_Core_BAO_LocationType
::getDefault();
283 $this->_website_types
= CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Website', 'website_type_id');
286 * FIXME: dirty hack to make the default option show up first. This
287 * avoids a mozilla browser bug with defaults on dynamically constructed
290 if ($defaultLocationType) {
291 $defaultLocation = $this->_location_types
[$defaultLocationType->id
];
292 unset($this->_location_types
[$defaultLocationType->id
]);
293 $this->_location_types
= array(
294 $defaultLocationType->id
=> $defaultLocation,
295 ) +
$this->_location_types
;
298 $this->_location_types
= array('Primary') +
$this->_location_types
;
300 // since we need a hierarchical list to display contact types & subtypes,
301 // this is what we going to display in first selector
302 $contactTypes = CRM_Contact_BAO_ContactType
::getSelectElements(FALSE, FALSE);
303 unset($contactTypes['']);
305 $contactTypes = !empty($contactTypes) ?
array('Contact' => 'Contacts') +
$contactTypes : array();
306 $sel1 = array('' => '- select -') +
$contactTypes;
308 if (!empty($fields['Activity'])) {
309 $sel1['Activity'] = 'Activity';
312 if (CRM_Core_Permission
::access('CiviEvent')) {
313 $sel1['Participant'] = 'Participants';
316 if (!empty($fields['Contribution'])) {
317 $sel1['Contribution'] = 'Contributions';
320 if (!empty($fields['Membership'])) {
321 $sel1['Membership'] = 'Membership';
324 if (!empty($fields['Case'])) {
325 $sel1['Case'] = 'Case';
328 if (!empty($fields['Formatting'])) {
329 $sel1['Formatting'] = 'Formatting';
332 foreach ($sel1 as $key => $sel) {
334 $sel2[$key] = $this->_mapperFields
[$key];
338 $phoneTypes = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Phone', 'phone_type_id');
341 foreach ($sel1 as $k => $sel) {
343 foreach ($this->_location_types
as $key => $value) {
344 $sel4[$k]['phone'][$key] = &$phoneTypes;
345 $sel4[$k]['phone_and_ext'][$key] = &$phoneTypes;
350 foreach ($sel1 as $k => $sel) {
352 if (is_array($this->_mapperFields
[$k])) {
353 foreach ($this->_mapperFields
[$k] as $key => $value) {
354 if ($hasLocationTypes[$k][$key]) {
355 $sel3[$k][$key] = $this->_location_types
;
357 elseif ($hasWebsiteTypes[$k][$key]) {
358 $sel3[$k][$key] = $this->_website_types
;
368 $this->_defaults
= array();
369 $js = "<script type='text/javascript'>\n";
370 $formName = "document.{$this->_name}";
372 $alreadyMixProfile = FALSE;
373 if (CRM_Core_BAO_UFField
::checkProfileType($this->_gid
)) {
374 $alreadyMixProfile = TRUE;
376 $this->assign('alreadyMixProfile', $alreadyMixProfile);
378 $sel = &$this->addElement('hierselect', 'field_name', ts('Field Name'));
380 $formValues = $this->exportValues();
382 if (empty($formValues)) {
383 for ($k = 1; $k < 4; $k++
) {
384 if (!isset($defaults['field_name'][$k])) {
385 $js .= "{$formName}['field_name[$k]'].style.display = 'none';\n";
390 if (!empty($formValues['field_name'])) {
391 for ($key = 1; $key < 4; $key++
) {
392 if (!isset($formValues['field_name'][$key])) {
393 $js .= "{$formName}['field_name[$key]'].style.display = 'none';\n";
396 $js .= "{$formName}['field_name[$key]'].style.display = '';\n";
401 for ($k = 1; $k < 4; $k++
) {
402 if (!isset($defaults['field_name'][$k])) {
403 $js .= "{$formName}['field_name[$k]'].style.display = 'none';\n";
409 foreach ($sel2 as $k => $v) {
410 if (is_array($sel2[$k])) {
415 $sel->setOptions(array($sel1, $sel2, $sel3, $sel4));
417 // proper interpretation of spec in CRM-8732
418 if (!isset($this->_id
) && in_array('Search Profile', $otherModules)) {
419 $defaults['visibility'] = 'Public Pages and Listings';
422 $js .= "</script>\n";
423 $this->assign('initHideBoxes', $js);
428 CRM_Core_SelectValues
::ufVisibility(),
430 array('onChange' => "showHideSeletorSearch(this.value);")
434 $js = array('onChange' => "mixProfile();");
435 // should the field appear in selectors (as a column)?
436 $this->add('advcheckbox', 'in_selector', ts('Results Column?'), NULL, NULL, $js);
437 $this->add('advcheckbox', 'is_searchable', ts('Searchable?'), NULL, NULL, $js);
439 $attributes = CRM_Core_DAO
::getAttribute('CRM_Core_DAO_UFField');
442 $this->add('text', 'weight', ts('Order'), $attributes['weight'], TRUE);
443 $this->addRule('weight', ts('is a numeric field'), 'numeric');
445 $this->add('textarea', 'help_pre', ts('Field Pre Help'), $attributes['help_pre']);
446 $this->add('textarea', 'help_post', ts('Field Post Help'), $attributes['help_post']);
448 $this->add('advcheckbox', 'is_required', ts('Required?'));
450 $this->add('advcheckbox', 'is_multi_summary', ts('Include in multi-record listing?'));
451 $this->add('advcheckbox', 'is_active', ts('Active?'));
452 $this->add('advcheckbox', 'is_view', ts('View Only?'));
454 $this->add('text', 'label', ts('Field Label'), $attributes['label']);
457 if ($this->_hasSearchableORInSelector
) {
458 $js = array('onclick' => "return verify( );");
462 $this->addButtons(array(
465 'name' => ts('Save'),
471 'name' => ts('Save and New'),
477 'name' => ts('Cancel'),
481 $this->addFormRule(array('CRM_UF_Form_Field', 'formRule'), $this);
483 // if view mode pls freeze it with the done button.
484 if ($this->_action
& CRM_Core_Action
::VIEW
) {
486 $this->addElement('button', 'done', ts('Done'),
487 array('onclick' => "location.href='civicrm/admin/uf/group/field?reset=1&action=browse&gid=" . $this->_gid
. "'")
491 $this->setDefaults($defaults);
499 public function postProcess() {
501 if ($this->_action
& CRM_Core_Action
::DELETE
) {
502 $fieldValues = array('uf_group_id' => $this->_gid
);
503 CRM_Utils_Weight
::delWeight('CRM_Core_DAO_UFField', $this->_id
, $fieldValues);
504 $deleted = CRM_Core_BAO_UFField
::del($this->_id
);
506 //update group_type every time. CRM-3608
507 if ($this->_gid
&& $deleted) {
508 //get the profile type.
509 $fieldsType = CRM_Core_BAO_UFGroup
::calculateGroupType($this->_gid
, TRUE);
510 CRM_Core_BAO_UFGroup
::updateGroupTypes($this->_gid
, $fieldsType);
513 CRM_Core_Session
::setStatus(ts('Selected Profile Field has been deleted.'), ts('Profile Field Deleted'), 'success');
517 // store the submitted values in an array
518 $params = $this->controller
->exportValues('Field');
519 $params['uf_group_id'] = $this->_gid
;
520 if ($params['visibility'] == 'User and User Admin Only') {
521 $params['is_searchable'] = $params['in_selector'] = 0;
524 if ($this->_action
& CRM_Core_Action
::UPDATE
) {
525 $params['id'] = $this->_id
;
529 if (isset($params['field_name'][1]) && isset($this->_selectFields
[$params['field_name'][1]])) {
530 // we dont get a name for a html formatting element
531 $name = $this->_selectFields
[$params['field_name'][1]];
534 //Hack for Formatting Field Name
535 if ($params['field_name'][0] == 'Formatting') {
536 $fieldName = 'formatting_' . rand(1000, 9999);
539 $fieldName = $params['field_name'][1];
542 //check for duplicate fields
543 $apiFormattedParams = $params;
544 $apiFormattedParams['field_type'] = $params['field_name'][0];
545 $apiFormattedParams['field_name'] = $fieldName;
546 if (!empty($params['field_name'][2])) {
547 if ($fieldName === 'url') {
548 $apiFormattedParams['website_type_id'] = $params['field_name'][2];
551 $apiFormattedParams['location_type_id'] = $params['field_name'][2];
554 elseif ($params['field_name'][2] == 0) {
555 // 0 is Primary location type
556 $apiFormattedParams['location_type_id'] = NULL;
558 if (!empty($params['field_name'][3])) {
559 $apiFormattedParams['phone_type_id'] = $params['field_name'][3];
562 if ($apiFormattedParams['field_type'] != "Formatting" && CRM_Core_BAO_UFField
::duplicateField($apiFormattedParams)) {
563 CRM_Core_Error
::statusBounce(ts('The selected field already exists in this profile.'), NULL, ts('Field Not Added'));
566 $apiFormattedParams['weight'] = CRM_Core_BAO_UFField
::autoWeight($params);
567 civicrm_api3('UFField', 'create', $apiFormattedParams);
569 //reset other field is searchable and in selector settings, CRM-4363
570 if ($this->_hasSearchableORInSelector
&&
571 in_array($apiFormattedParams['field_type'], array('Participant', 'Contribution', 'Membership', 'Activity', 'Case'))
573 CRM_Core_BAO_UFField
::resetInSelectorANDSearchable($this->_gid
);
576 $this->setMessageIfCountryNotAboveState($fieldName, CRM_Utils_Array
::value('location_type_id', $apiFormattedParams), $apiFormattedParams['weight'], $apiFormattedParams['uf_group_id']);
578 CRM_Core_Session
::setStatus(ts('Your CiviCRM Profile Field \'%1\' has been saved to \'%2\'.',
579 array(1 => $name, 2 => $this->_title
)
580 ), ts('Profile Field Saved'), 'success');
582 $buttonName = $this->controller
->getButtonName();
584 $session = CRM_Core_Session
::singleton();
585 if ($buttonName == $this->getButtonName('next', 'new')) {
586 $session->replaceUserContext(CRM_Utils_System
::url('civicrm/admin/uf/group/field/add',
587 "reset=1&action=add&gid={$this->_gid}"
591 $session->replaceUserContext(CRM_Utils_System
::url('civicrm/admin/uf/group/field',
592 "reset=1&action=browse&gid={$this->_gid}"
598 * Validation rule for subtype.
600 * @param string $fieldType
602 * @param array $groupType
603 * Contains all groupTypes.
604 * @param array $errors
605 * List of errors to be posted back to the form.
607 public static function formRuleSubType($fieldType, $groupType, &$errors) {
608 if (in_array($fieldType, array(
614 $individualSubTypes = CRM_Contact_BAO_ContactType
::subTypes('Individual');
615 foreach ($groupType as $value) {
616 if (!in_array($value, $individualSubTypes) &&
617 !in_array($value, array(
627 $errors['field_name'] = ts('Cannot add or update profile field "%1" with combination of Household or Organization or any subtypes of Household or Organization.', array(1 => $fieldType));
633 $basicType = CRM_Contact_BAO_ContactType
::getBasicType($groupType);
635 if (!is_array($basicType)) {
636 $basicType = array($basicType);
638 if (!in_array($fieldType, $basicType) && $fieldType != 'Contact') {
639 $errors['field_name'] = ts('Cannot add or update profile field type "%1" with combination of subtype other than "%1".',
640 array(1 => $fieldType)
648 * Validation rule for custom data extends entity column values.
650 * @param Object $customField
654 * @param string $fieldType
655 * Group type of the field.
656 * @param array $errors
660 * list of errors to be posted back to the form
662 public static function formRuleCustomDataExtentColumnValue($customField, $gid, $fieldType, &$errors) {
663 // fix me : check object $customField
664 if (in_array($fieldType, array(
671 $params = array('id' => $customField->custom_group_id
);
672 $customGroup = array();
673 CRM_Core_BAO_CustomGroup
::retrieve($params, $customGroup);
674 if (($fieldType != CRM_Utils_Array
::value('extends', $customGroup)) ||
empty($customGroup['extends_entity_column_value'])) {
678 $extendsColumnValues = array();
679 foreach (explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $customGroup['extends_entity_column_value']) as $val) {
681 $extendsColumnValues[] = $val;
685 if (empty($extendsColumnValues)) {
689 $fieldTypeValues = CRM_Core_BAO_UFGroup
::groupTypeValues($gid, $fieldType);
690 if (empty($fieldTypeValues[$fieldType])) {
694 $disallowedTypes = array_diff($extendsColumnValues, $fieldTypeValues[$fieldType]);
695 if (!empty($disallowedTypes)) {
696 $errors['field_name'] = ts('Profile is already having custom fields extending different group types, you can not add or update this custom field.');
702 * Validation rule to prevent multiple fields of primary location type within the same communication type.
704 * @param array $fields
706 * @param string $profileFieldName
708 * @param array $groupFields
709 * List of fields already in the group.
710 * @param array $errors
714 public static function formRulePrimaryCheck($fields, $profileFieldName, $groupFields, &$errors) {
715 //FIXME: This may need to also apply to website fields if they are refactored to allow more than one per profile
716 $checkPrimary = array('phone' => 'civicrm_phone.phone', 'phone_and_ext' => 'civicrm_phone.phone');
718 $primaryOfSameTypeFound = NULL;
719 $fieldID = empty($fields['field_id']) ?
0 : $fields['field_id'];
720 // Is this a primary location type field of interest
721 if (array_key_exists($profileFieldName, $checkPrimary)) {
722 $whereCheck = $checkPrimary[$profileFieldName];
724 $potentialLocationType = CRM_Utils_Array
::value(2, $fields['field_name']);
726 if ($whereCheck && $potentialLocationType == 0) {
727 $primaryOfSameTypeFound = '';
729 foreach ($groupFields as $groupField) {
731 if ($groupField['where'] == $whereCheck && is_null($groupField['location_type_id']) && $groupField['field_id'] != $fieldID) {
732 $primaryOfSameTypeFound = $groupField['title'];
736 if ($primaryOfSameTypeFound) {
737 $errors['field_name'] = ts('You have already added a primary location field of this type: %1', array(1 => $primaryOfSameTypeFound));
743 * Global validation rules for the form.
745 * @param array $fields
746 * Posted values of the form.
752 * list of errors to be posted back to the form
754 public static function formRule($fields, $files, $self) {
755 $is_required = CRM_Utils_Array
::value('is_required', $fields, FALSE);
756 $is_registration = CRM_Utils_Array
::value('is_registration', $fields, FALSE);
757 $is_view = CRM_Utils_Array
::value('is_view', $fields, FALSE);
758 $in_selector = CRM_Utils_Array
::value('in_selector', $fields, FALSE);
759 $is_active = CRM_Utils_Array
::value('is_active', $fields, FALSE);
762 if ($is_view && $is_registration) {
763 $errors['is_registration'] = ts('View Only cannot be selected if this field is to be included on the registration form');
765 if ($is_view && $is_required) {
766 $errors['is_view'] = ts('A View Only field cannot be required');
769 $entityName = $fields['field_name'][0];
771 $errors['field_name'] = ts('Please select a field name');
774 if ($in_selector && in_array($entityName, array(
781 $errors['in_selector'] = ts("'Results Column' cannot be checked for %1 fields.", array(1 => $entityName));
784 $isCustomField = FALSE;
785 $profileFieldName = CRM_Utils_Array
::value(1, $fields['field_name']);
786 if ($profileFieldName) {
787 //get custom field id
788 $customFieldId = explode('_', $profileFieldName);
789 if ($customFieldId[0] == 'custom') {
790 $customField = new CRM_Core_DAO_CustomField();
791 $customField->id
= $customFieldId[1];
792 $customField->find(TRUE);
793 $isCustomField = TRUE;
794 if (!empty($fields['field_id']) && !$customField->is_active
&& $is_active) {
795 $errors['field_name'] = ts('Cannot set this field "Active" since the selected custom field is disabled.');
798 //check if profile already has a different multi-record custom set field configured
799 $customGroupId = CRM_Core_BAO_CustomField
::isMultiRecordField($profileFieldName);
800 if ($customGroupId) {
801 if ($profileMultiRecordCustomGid = CRM_Core_BAO_UFField
::checkMultiRecordFieldExists($self->_gid
)) {
802 if ($customGroupId != $profileMultiRecordCustomGid) {
803 $errors['field_name'] = ts("You cannot configure multi-record custom fields belonging to different custom sets in one profile");
810 // Get list of fields already in the group
811 $groupFields = CRM_Core_BAO_UFGroup
::getFields($fields['group_id'], FALSE, NULL, NULL, NULL, TRUE, NULL, TRUE);
812 // Check if we already added a primary field of the same communication type
813 self
::formRulePrimaryCheck($fields, $profileFieldName, $groupFields, $errors);
815 //check profile is configured for double option process
816 //adding group field, email field should be present in the group
817 //fixed for issue CRM-2861 & CRM-4153
818 if (CRM_Core_BAO_UFGroup
::isProfileDoubleOptin()) {
819 if (CRM_Utils_Array
::value(1, $fields['field_name']) == 'group') {
820 $dao = new CRM_Core_BAO_UFField();
821 $dao->uf_group_id
= $fields['group_id'];
824 while ($dao->fetch()) {
825 //check email field is present in the group
826 if ($dao->field_name
== 'email') {
833 $disableSettingURL = CRM_Utils_System
::url(
834 'civicrm/admin/setting/preferences/mailing',
838 $errors['field_name'] = ts('Your site is currently configured to require double-opt in when users join (subscribe) to Group(s) via a Profile form. In this mode, you need to include an Email field in a Profile BEFORE you can add the Group(s) field. This ensures that an opt-in confirmation email can be sent. Your site administrator can disable double opt-in on the civimail admin settings: <em>%1</em>', array(1 => $disableSettingURL));
844 $fieldType = $fields['field_name'][0];
846 //get the group type.
847 $groupType = CRM_Core_BAO_UFGroup
::calculateGroupType($self->_gid
, FALSE, CRM_Utils_Array
::value('field_id', $fields));
849 switch ($fieldType) {
851 self
::formRuleSubType($fieldType, $groupType, $errors);
855 if (in_array('Activity', $groupType) ||
856 in_array('Household', $groupType) ||
857 in_array('Organization', $groupType)
860 //CRM-7603 - need to support activity + individual.
861 //$errors['field_name'] =
862 //ts( 'Cannot add or update profile field type Individual with combination of Household or Organization or Activity' );
863 if (in_array('Household', $groupType) ||
864 in_array('Organization', $groupType)
866 $errors['field_name'] = ts('Cannot add or update profile field type Individual with combination of Household or Organization');
870 self
::formRuleSubType($fieldType, $groupType, $errors);
875 if (in_array('Activity', $groupType) ||
in_array('Individual', $groupType) ||
in_array('Organization', $groupType)) {
876 $errors['field_name'] = ts('Cannot add or update profile field type Household with combination of Individual or Organization or Activity');
879 self
::formRuleSubType($fieldType, $groupType, $errors);
884 if (in_array('Activity', $groupType) ||
in_array('Household', $groupType) ||
in_array('Individual', $groupType)) {
885 $errors['field_name'] = ts('Cannot add or update profile field type Organization with combination of Household or Individual or Activity');
888 self
::formRuleSubType($fieldType, $groupType, $errors);
893 if (in_array('Individual', $groupType) ||
894 in_array('Membership', $groupType) ||
895 in_array('Contribution', $groupType) ||
896 in_array('Organization', $groupType) ||
897 in_array('Household', $groupType) ||
898 in_array('Participant', $groupType)
901 //CRM-7603 - need to support activity + contact type.
902 //$errors['field_name'] =
903 //ts( 'Cannot add or update profile field type Activity with combination Participant or Membership or Contribution or Household or Organization or Individual' );
904 if (in_array('Membership', $groupType) ||
905 in_array('Contribution', $groupType) ||
906 in_array('Participant', $groupType)
908 $errors['field_name'] = ts('Cannot add or update profile field type Activity with combination Participant or Membership or Contribution');
912 self
::formRuleSubType($fieldType, $groupType, $errors);
915 if ($isCustomField && !isset($errors['field_name'])) {
916 self
::formRuleCustomDataExtentColumnValue($customField, $self->_gid
, $fieldType, $errors);
921 if (in_array('Membership', $groupType) ||
in_array('Contribution', $groupType)
922 ||
in_array('Organization', $groupType) ||
in_array('Household', $groupType) ||
in_array('Activity', $groupType)
924 $errors['field_name'] = ts('Cannot add or update profile field type Participant with combination of Activity or Membership or Contribution or Household or Organization.');
927 self
::formRuleSubType($fieldType, $groupType, $errors);
932 //special case where in we allow contribution + oganization fields, for on behalf feature
933 $profileId = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup',
934 'on_behalf_organization', 'id', 'name'
937 if (in_array('Participant', $groupType) ||
in_array('Membership', $groupType)
938 ||
($profileId != $self->_gid
&& in_array('Organization', $groupType)) ||
in_array('Household', $groupType) ||
in_array('Activity', $groupType)
940 $errors['field_name'] = ts('Cannot add or update profile field type Contribution with combination of Activity or Membership or Participant or Household or Organization');
943 self
::formRuleSubType($fieldType, $groupType, $errors);
948 //special case where in we allow contribution + oganization fields, for on behalf feature
949 $profileId = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup',
950 'on_behalf_organization', 'id', 'name'
953 if (in_array('Participant', $groupType) ||
in_array('Contribution', $groupType)
954 ||
($profileId != $self->_gid
&& in_array('Organization', $groupType)) ||
in_array('Household', $groupType) ||
in_array('Activity', $groupType)
956 $errors['field_name'] = ts('Cannot add or update profile field type Membership with combination of Activity or Participant or Contribution or Household or Organization');
959 self
::formRuleSubType($fieldType, $groupType, $errors);
964 $profileType = CRM_Core_BAO_UFField
::getProfileType($fields['group_id'], TRUE, FALSE, TRUE);
965 if (CRM_Contact_BAO_ContactType
::isaSubType($fieldType)) {
966 if (CRM_Contact_BAO_ContactType
::isaSubType($profileType)) {
967 if ($fieldType != $profileType) {
968 $errors['field_name'] = ts('Cannot add or update profile field type "%1" with combination of "%2".', array(
975 $basicType = CRM_Contact_BAO_ContactType
::getBasicType($fieldType);
977 $profileType != $basicType &&
978 $profileType != 'Contact'
980 $errors['field_name'] = ts('Cannot add or update profile field type "%1" with combination of "%2".', array(
988 CRM_Utils_Array
::value(1, $fields['field_name']) == 'contact_sub_type' &&
989 !in_array($profileType, array('Individual', 'Household', 'Organization')) &&
990 !in_array($profileType, CRM_Contact_BAO_ContactType
::subTypes())
992 $errors['field_name'] = ts('Cannot add or update profile field Contact Subtype as profile type is not one of Individual, Household or Organization.');
995 return empty($errors) ?
TRUE : $errors;
999 * Set a message warning the user about putting country first to render states, if required.
1001 * @param string $fieldName
1002 * @param int $locationTypeID
1003 * @param int $weight
1004 * @param int $ufGroupID
1006 protected function setMessageIfCountryNotAboveState($fieldName, $locationTypeID, $weight, $ufGroupID) {
1007 $message = ts('For best results, the Country field should precede the State-Province field in your Profile form. You can use the up and down arrows on field listing page for this profile to change the order of these fields or manually edit weight for Country/State-Province Field.');
1009 if (in_array($fieldName, array(
1012 )) && count(CRM_Core_Config
::singleton()->countryLimit
) > 1
1014 // get state or country field weight if exists
1015 $ufFieldDAO = new CRM_Core_DAO_UFField();
1016 $ufFieldDAO->field_name
= ($fieldName == 'state_province' ?
'country' : 'state_province');
1017 $ufFieldDAO->location_type_id
= $locationTypeID;
1018 $ufFieldDAO->uf_group_id
= $ufGroupID;
1020 if ($ufFieldDAO->find(TRUE)) {
1021 if ($ufFieldDAO->field_name
== 'country' && $ufFieldDAO->weight
> $weight) {
1022 CRM_Core_Session
::setStatus($message);
1024 elseif ($ufFieldDAO->field_name
== 'state_province' && $ufFieldDAO->weight
< $weight) {
1025 CRM_Core_Session
::setStatus($message);