3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
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-2014
37 * form to process actions on the field aspect of Custom
39 class CRM_UF_Form_Field
extends CRM_Core_Form
{
42 * the uf group id saved to the session for an update
50 * The field id, used when editing the field
58 * The set of fields that we can view/edit in the user field framework
74 * The set of fields sent to the select element
79 protected $_selectFields;
82 * to store fields with if locationtype exits status
87 protected $_hasLocationTypes;
90 * is this profile has searchable field
91 * or is any field having in selector true.
96 protected $_hasSearchableORInSelector;
99 * Function to set variables up before form is built
104 public function preProcess() {
105 $this->_gid
= CRM_Utils_Request
::retrieve('gid', 'Positive', $this);
106 $this->_id
= CRM_Utils_Request
::retrieve('id', 'Positive', $this);
108 $this->_title
= CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup', $this->_gid
, 'title');
110 $this->setPageTitle(ts('Profile Field'));
112 $url = CRM_Utils_System
::url('civicrm/admin/uf/group/field',
113 "reset=1&action=browse&gid={$this->_gid}"
116 $session = CRM_Core_Session
::singleton();
117 $session->pushUserContext($url);
118 $breadCrumb = array(array('title' => ts('CiviCRM Profile Fields'),
121 CRM_Utils_System
::appendBreadCrumb($breadCrumb);
124 $showBestResult = CRM_Utils_Request
::retrieve('sbr', 'Positive', CRM_Core_DAO
::$_nullArray);
125 if ($showBestResult) {
126 $this->assign('showBestResult', $showBestResult);
129 $this->_fields
= CRM_Contact_BAO_Contact
::importableFields('All', TRUE, TRUE, TRUE, TRUE, TRUE);
130 $this->_fields
= array_merge(CRM_Activity_BAO_Activity
::exportableFields('Activity'), $this->_fields
);
132 //unset campaign related fields.
133 if (isset($this->_fields
['activity_campaign_id'])) {
134 $this->_fields
['activity_campaign_id']['title'] = ts('Campaign');
135 if (isset($this->_fields
['activity_campaign'])) {
136 unset($this->_fields
['activity_campaign']);
140 if (CRM_Core_Permission
::access('CiviContribute')) {
141 $this->_fields
= array_merge(CRM_Contribute_BAO_Contribution
::getContributionFields(FALSE), $this->_fields
);
142 $this->_fields
= array_merge(CRM_Core_BAO_UFField
::getContribBatchEntryFields(), $this->_fields
);
145 if (CRM_Core_Permission
::access('CiviMember')) {
146 $this->_fields
= array_merge(CRM_Member_BAO_Membership
::getMembershipFields(), $this->_fields
);
149 if (CRM_Core_Permission
::access('CiviEvent')) {
150 $this->_fields
= array_merge(CRM_Event_BAO_Query
::getParticipantFields(), $this->_fields
);
153 if (CRM_Core_Permission
::access('CiviCase')) {
154 $this->_fields
= array_merge(CRM_Case_BAO_Query
::getFields(), $this->_fields
);
157 $this->_fields
= array_merge($this->_fields
, CRM_Contact_BAO_Query_Hook
::singleton()->getFields());
159 $this->_selectFields
= array();
160 foreach ($this->_fields
as $name => $field) {
161 // lets skip note for now since we dont support it
162 if ($name == 'note') {
165 $this->_selectFields
[$name] = $field['title'];
166 $this->_hasLocationTypes
[$name] = CRM_Utils_Array
::value('hasLocationType', $field);
169 // lets add group, tag and current_employer to this list
170 $this->_selectFields
['group'] = ts('Group(s)');
171 $this->_selectFields
['tag'] = ts('Tag(s)');
172 $this->_selectFields
['current_employer'] = ts('Current Employer');
173 $this->_selectFields
['phone_and_ext'] = ts('Phone and Extension');
175 //CRM-4363 check for in selector or searchable fields.
176 $this->_hasSearchableORInSelector
= CRM_Core_BAO_UFField
::checkSearchableORInSelector($this->_gid
);
178 $this->assign('fieldId', $this->_id
);
180 $fieldTitle = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFField', $this->_id
, 'label');
181 $this->assign('fieldTitle', $fieldTitle);
186 * Function to actually build the form
191 public function buildQuickForm() {
192 if ($this->_action
& CRM_Core_Action
::DELETE
) {
193 $this->addButtons(array(
196 'name' => ts('Delete Profile Field'),
197 'spacing' => ' ',
202 'name' => ts('Cancel'),
209 if (isset($this->_id
)) {
210 $params = array('id' => $this->_id
);
211 CRM_Core_BAO_UFField
::retrieve($params, $defaults);
213 // set it to null if so (avoids crappy E_NOTICE errors below
214 $defaults['location_type_id'] = CRM_Utils_Array
::value('location_type_id', $defaults);
216 $specialFields = CRM_Core_BAO_UFGroup
::getLocationFields();
218 if (!$defaults['location_type_id'] &&
219 $defaults["field_type"] != "Formatting" &&
220 in_array($defaults['field_name'], $specialFields)
222 $defaults['location_type_id'] = 0;
225 $defaults['field_name'] = array(
226 $defaults['field_type'],
227 ($defaults['field_type'] == "Formatting" ?
"" : $defaults['field_name']),
228 ($defaults['field_name'] == "url") ?
$defaults['website_type_id'] : $defaults['location_type_id'],
229 CRM_Utils_Array
::value('phone_type_id', $defaults),
231 $this->_gid
= $defaults['uf_group_id'];
234 $defaults['is_active'] = 1;
237 $otherModules = array_values(CRM_Core_BAO_UFGroup
::getUFJoinRecord($this->_gid
));
238 $this->assign('otherModules', $otherModules);
240 if ($this->_action
& CRM_Core_Action
::ADD
) {
241 $fieldValues = array('uf_group_id' => $this->_gid
);
242 $defaults['weight'] = CRM_Utils_Weight
::getDefaultWeight('CRM_Core_DAO_UFField', $fieldValues);
245 // lets trim all the whitespace
246 $this->applyFilter('__ALL__', 'trim');
248 //hidden field to catch the group id in profile
249 $this->add('hidden', 'group_id', $this->_gid
);
251 //hidden field to catch the field id in profile
252 $this->add('hidden', 'field_id', $this->_id
);
254 $fields = CRM_Core_BAO_UFField
::getAvailableFields($this->_gid
, $defaults);
256 $noSearchable = $hasWebsiteTypes = array();
257 $addressCustomFields = array_keys(CRM_Core_BAO_CustomField
::getFieldsForImport('Address'));
259 foreach ($fields as $key => $value) {
260 foreach ($value as $key1 => $value1) {
261 //CRM-2676, replacing the conflict for same custom field name from different custom group.
262 if ($customFieldId = CRM_Core_BAO_CustomField
::getKeyID($key1)) {
263 $customGroupId = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomField', $customFieldId, 'custom_group_id');
264 $customGroupName = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomGroup', $customGroupId, 'title');
265 $this->_mapperFields
[$key][$key1] = $value1['title'] . ' :: ' . $customGroupName;
266 if (in_array($key1, $addressCustomFields)) {
267 $noSearchable[] = $value1['title'] . ' :: ' . $customGroupName;
271 $this->_mapperFields
[$key][$key1] = $value1['title'];
273 $hasLocationTypes[$key][$key1] = CRM_Utils_Array
::value('hasLocationType', $value1);
274 $hasWebsiteTypes[$key][$key1] = CRM_Utils_Array
::value('hasWebsiteType', $value1);
275 // hide the 'is searchable' field for 'File' custom data
276 if (isset($value1['data_type']) &&
277 isset($value1['html_type']) &&
278 (($value1['data_type'] == 'File' && $value1['html_type'] == 'File')
279 ||
($value1['data_type'] == 'Link' && $value1['html_type'] == 'Link')
282 if (!in_array($value1['title'], $noSearchable)) {
283 $noSearchable[] = $value1['title'];
288 $this->assign('noSearchable', $noSearchable);
290 $this->_location_types
= CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Address', 'location_type_id');
291 $defaultLocationType = CRM_Core_BAO_LocationType
::getDefault();
292 $this->_website_types
= CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Website', 'website_type_id');
295 * FIXME: dirty hack to make the default option show up first. This
296 * avoids a mozilla browser bug with defaults on dynamically constructed
299 if ($defaultLocationType) {
300 $defaultLocation = $this->_location_types
[$defaultLocationType->id
];
301 unset($this->_location_types
[$defaultLocationType->id
]);
302 $this->_location_types
= array(
303 $defaultLocationType->id
=> $defaultLocation) +
$this->_location_types
;
306 $this->_location_types
= array('Primary') +
$this->_location_types
;
308 // since we need a hierarchical list to display contact types & subtypes,
309 // this is what we going to display in first selector
310 $contactTypes = CRM_Contact_BAO_ContactType
::getSelectElements(FALSE, FALSE);
311 unset($contactTypes['']);
313 $contactTypes = !empty($contactTypes) ?
array('Contact' => 'Contacts') +
$contactTypes : array();
314 $sel1 = array('' => '- select -') +
$contactTypes;
316 if (!empty($fields['Activity'])) {
317 $sel1['Activity'] = 'Activity';
320 if (CRM_Core_Permission
::access('CiviEvent')) {
321 $sel1['Participant'] = 'Participants';
324 if (!empty($fields['Contribution'])) {
325 $sel1['Contribution'] = 'Contributions';
328 if (!empty($fields['Membership'])) {
329 $sel1['Membership'] = 'Membership';
332 if (!empty($fields['Case'])) {
333 $sel1['Case'] = 'Case';
336 if (!empty($fields['Formatting'])) {
337 $sel1['Formatting'] = 'Formatting';
340 foreach ($sel1 as $key => $sel) {
342 $sel2[$key] = $this->_mapperFields
[$key];
346 $phoneTypes = CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Phone', 'phone_type_id');
349 foreach ($sel1 as $k => $sel) {
351 foreach ($this->_location_types
as $key => $value) {
352 $sel4[$k]['phone'][$key] = &$phoneTypes;
353 $sel4[$k]['phone_and_ext'][$key] = &$phoneTypes;
358 foreach ($sel1 as $k => $sel) {
360 if (is_array($this->_mapperFields
[$k])) {
361 foreach ($this->_mapperFields
[$k] as $key => $value) {
362 if ($hasLocationTypes[$k][$key]) {
363 $sel3[$k][$key] = $this->_location_types
;
365 elseif ($hasWebsiteTypes[$k][$key]) {
366 $sel3[$k][$key] = $this->_website_types
;
376 $this->_defaults
= array();
377 $js = "<script type='text/javascript'>\n";
378 $formName = "document.{$this->_name}";
380 $alreadyMixProfile = FALSE;
381 if (CRM_Core_BAO_UFField
::checkProfileType($this->_gid
)) {
382 $alreadyMixProfile = TRUE;
384 $this->assign('alreadyMixProfile', $alreadyMixProfile);
386 $sel = &$this->addElement('hierselect', 'field_name', ts('Field Name'));
388 $formValues = $this->exportValues();
390 if (empty($formValues)) {
391 for ($k = 1; $k < 4; $k++
) {
392 if (!isset($defaults['field_name'][$k])) {
393 $js .= "{$formName}['field_name[$k]'].style.display = 'none';\n";
398 if (!empty($formValues['field_name'])) {
399 for ($key = 1; $key < 4; $key++
) {
400 if (!isset($formValues['field_name'][$key])) {
401 $js .= "{$formName}['field_name[$key]'].style.display = 'none';\n";
404 $js .= "{$formName}['field_name[$key]'].style.display = '';\n";
409 for ($k = 1; $k < 4; $k++
) {
410 if (!isset($defaults['field_name'][$k])) {
411 $js .= "{$formName}['field_name[$k]'].style.display = 'none';\n";
417 foreach ($sel2 as $k => $v) {
418 if (is_array($sel2[$k])) {
423 // CRM_Core_Error::debug(array($sel1, $sel2, $sel3, $sel4));
424 $sel->setOptions(array($sel1, $sel2, $sel3, $sel4));
426 // proper interpretation of spec in CRM-8732
427 if (!isset($this->_id
) && in_array('Search Profile', $otherModules)) {
428 $defaults['visibility'] = 'Public Pages and Listings';
431 $js .= "</script>\n";
432 $this->assign('initHideBoxes', $js);
437 CRM_Core_SelectValues
::ufVisibility(),
439 array('onChange' => "showHideSeletorSearch(this.value);")
443 $js = array('onChange' => "mixProfile();");
444 // should the field appear in selectors (as a column)?
445 $this->add('checkbox', 'in_selector', ts('Results Column?'), NULL, NULL, $js);
446 $this->add('checkbox', 'is_searchable', ts('Searchable?'), NULL, NULL, $js);
448 $attributes = CRM_Core_DAO
::getAttribute('CRM_Core_DAO_UFField');
451 $this->add('text', 'weight', ts('Order'), $attributes['weight'], TRUE);
452 $this->addRule('weight', ts('is a numeric field'), 'numeric');
454 $this->add('textarea', 'help_pre', ts('Field Pre Help'), $attributes['help_pre']);
455 $this->add('textarea', 'help_post', ts('Field Post Help'), $attributes['help_post']);
457 $this->add('checkbox', 'is_required', ts('Required?'));
459 $this->add('checkbox', 'is_multi_summary', ts('Include in multi-record listing?'));
460 $this->add('checkbox', 'is_active', ts('Active?'));
461 $this->add('checkbox', 'is_view', ts('View Only?'));
463 // $this->add( 'checkbox', 'is_registration', ts( 'Display in Registration Form?' ) );
464 //$this->add( 'checkbox', 'is_match' , ts( 'Key to Match Contacts?' ) );
466 $this->add('text', 'label', ts('Field Label'), $attributes['label']);
469 if ($this->_hasSearchableORInSelector
) {
470 $js = array('onclick' => "return verify( );");
474 $this->addButtons(array(
477 'name' => ts('Save'),
483 'name' => ts('Save and New'),
489 'name' => ts('Cancel'),
494 $this->addFormRule(array('CRM_UF_Form_Field', 'formRule'), $this);
496 // if view mode pls freeze it with the done button.
497 if ($this->_action
& CRM_Core_Action
::VIEW
) {
499 $this->addElement('button', 'done', ts('Done'),
500 array('onclick' => "location.href='civicrm/admin/uf/group/field?reset=1&action=browse&gid=" . $this->_gid
. "'")
504 $this->setDefaults($defaults);
513 public function postProcess() {
514 $ids = array('uf_group' => $this->_gid
);
515 if ($this->_action
& CRM_Core_Action
::DELETE
) {
516 $fieldValues = array('uf_group_id' => $this->_gid
);
517 CRM_Utils_Weight
::delWeight('CRM_Core_DAO_UFField', $this->_id
, $fieldValues);
518 $deleted = CRM_Core_BAO_UFField
::del($this->_id
);
520 //update group_type every time. CRM-3608
521 if ($this->_gid
&& $deleted) {
522 //get the profile type.
523 $fieldsType = CRM_Core_BAO_UFGroup
::calculateGroupType($this->_gid
, TRUE);
524 CRM_Core_BAO_UFGroup
::updateGroupTypes($this->_gid
, $fieldsType);
527 CRM_Core_Session
::setStatus(ts('Selected Profile Field has been deleted.'), ts('Profile Field Deleted'), 'success');
531 // store the submitted values in an array
532 $params = $this->controller
->exportValues('Field');
533 if ($params['visibility'] == 'User and User Admin Only') {
534 $params['is_searchable'] = $params['in_selector'] = 0;
537 if ($this->_action
& CRM_Core_Action
::UPDATE
) {
538 $ids['uf_field'] = $this->_id
;
543 if (isset($params['field_name'][1]) && isset($this->_selectFields
[$params['field_name'][1]])) {
544 // we dont get a name for a html formatting element
545 $name = $this->_selectFields
[$params['field_name'][1]];
548 //Hack for Formatting Field Name
549 if ($params['field_name'][0] == 'Formatting') {
550 $params['field_name'][1] = 'formatting_' . rand(1000, 9999);
553 //check for duplicate fields
554 if ($params["field_name"][0] != "Formatting" && CRM_Core_BAO_UFField
::duplicateField($params, $ids)) {
555 CRM_Core_Session
::setStatus(ts('The selected field already exists in this profile.'), ts('Field Not Added'), 'error');
559 $params['weight'] = CRM_Core_BAO_UFField
::autoWeight($params);
560 $ufField = CRM_Core_BAO_UFField
::add($params, $ids);
562 //reset other field is searchable and in selector settings, CRM-4363
563 if ($this->_hasSearchableORInSelector
&&
564 in_array($ufField->field_type
, array('Participant', 'Contribution', 'Membership', 'Activity', 'Case'))
566 CRM_Core_BAO_UFField
::resetInSelectorANDSearchable($this->_gid
);
569 $config = CRM_Core_Config
::singleton();
570 $showBestResult = FALSE;
571 if (in_array($ufField->field_name
, array(
572 'country', 'state_province')) && count($config->countryLimit
) > 1) {
573 // get state or country field weight if exists
574 $field = 'state_province';
575 if ($ufField->field_name
== 'state_province') {
578 $ufFieldDAO = new CRM_Core_DAO_UFField();
579 $ufFieldDAO->field_name
= $field;
580 $ufFieldDAO->location_type_id
= $ufField->location_type_id
;
581 $ufFieldDAO->uf_group_id
= $ufField->uf_group_id
;
583 if ($ufFieldDAO->find(TRUE)) {
584 if ($field == 'country' && $ufFieldDAO->weight
> $ufField->weight
) {
585 $showBestResult = TRUE;
587 elseif ($field == 'state_province' && $ufFieldDAO->weight
< $ufField->weight
) {
588 $showBestResult = TRUE;
593 //update group_type every time. CRM-3608
594 if ($this->_gid
&& is_a($ufField, 'CRM_Core_DAO_UFField')) {
595 // get the profile type.
596 $fieldsType = CRM_Core_BAO_UFGroup
::calculateGroupType($this->_gid
, TRUE);
597 CRM_Core_BAO_UFGroup
::updateGroupTypes($this->_gid
, $fieldsType);
599 CRM_Core_Session
::setStatus(ts('Your CiviCRM Profile Field \'%1\' has been saved to \'%2\'.',
600 array(1 => $name, 2 => $this->_title
)
601 ), ts('Profile Field Saved'), 'success');
603 $buttonName = $this->controller
->getButtonName();
605 $session = CRM_Core_Session
::singleton();
606 if ($buttonName == $this->getButtonName('next', 'new')) {
607 CRM_Core_Session
::setStatus(ts(' You can add another profile field.'), '', 'info');
608 $session->replaceUserContext(CRM_Utils_System
::url('civicrm/admin/uf/group/field/add',
609 "reset=1&action=add&gid={$this->_gid}&sbr={$showBestResult}"
613 $session->replaceUserContext(CRM_Utils_System
::url('civicrm/admin/uf/group/field',
614 "reset=1&action=browse&gid={$this->_gid}"
616 $session->set('showBestResult', $showBestResult);
621 * validation rule for subtype.
623 * @param array $groupType contains all groupTypes.
625 * @param string $fieldType type of field.
627 * @param array $errors
629 * @return array list of errors to be posted back to the form
633 static function formRuleSubType($fieldType, $groupType, $errors) {
634 if (in_array($fieldType, array(
635 'Participant', 'Contribution', 'Membership', 'Activity'))) {
636 $individualSubTypes = CRM_Contact_BAO_ContactType
::subTypes('Individual');
637 foreach ($groupType as $value) {
638 if (!in_array($value, $individualSubTypes) &&
639 !in_array($value, array(
640 'Participant', 'Contribution', 'Membership',
641 'Individual', 'Contact', 'Activity',
644 $errors['field_name'] = ts('Cannot add or update profile field "%1" with combination of Household or Organization or any subtypes of Household or Organisation.', array(1 => $fieldType));
650 $basicType = CRM_Contact_BAO_ContactType
::getBasicType($groupType);
652 if (!is_array($basicType)) {
653 $basicType = array($basicType);
655 if (!in_array($fieldType, $basicType)) {
656 $errors['field_name'] = ts('Cannot add or update profile field type "%1" with combination of subtype other than "%1".',
657 array(1 => $fieldType)
665 * validation rule for custom data extends entity column values.
667 * @param Object $customField Custom field
668 * @param Integer $gid Group Id.
669 * @param String $fieldType Group type of the field
670 * @param Array $errors Collect errors
672 * @return Array list of errors to be posted back to the form
676 static function formRuleCustomDataExtentColumnValue($customField, $gid, $fieldType, &$errors) {
677 // fix me : check object $customField
678 if (in_array($fieldType, array(
679 'Participant', 'Contribution', 'Membership', 'Activity', 'Case'))) {
680 $params = array('id' => $customField->custom_group_id
);
681 $customGroup = array();
682 CRM_Core_BAO_CustomGroup
::retrieve($params, $customGroup);
683 if (($fieldType != CRM_Utils_Array
::value('extends', $customGroup)) ||
empty($customGroup['extends_entity_column_value'])) {
687 $extendsColumnValues = array();
688 foreach (explode(CRM_Core_DAO
::VALUE_SEPARATOR
, $customGroup['extends_entity_column_value']) as $val) {
690 $extendsColumnValues[] = $val;
694 if (empty($extendsColumnValues)) {
698 $fieldTypeValues = CRM_Core_BAO_UFGroup
::groupTypeValues($gid, $fieldType);
699 if (empty($fieldTypeValues[$fieldType])) {
703 $disallowedTypes = array_diff($extendsColumnValues, $fieldTypeValues[$fieldType]);
704 if (!empty($disallowedTypes)) {
705 $errors['field_name'] = ts('Profile is already having custom fields extending different group types, you can not add or update this custom field.');
711 * Validation rule to prevent multiple fields of primary location type within the same communication type.
713 * @param Array $fields Submitted fields
714 * @param String $profileFieldName Group Id.
715 * @param Array $groupFields List of fields already in the group
716 * @param Array $errors Collect errors
721 static function formRulePrimaryCheck($fields, $profileFieldName, $groupFields, &$errors) {
722 //FIXME: This may need to also apply to website fields if they are refactored to allow more than one per profile
723 $checkPrimary = array('phone' => 'civicrm_phone.phone', 'phone_and_ext' => 'civicrm_phone.phone');
725 $primaryOfSameTypeFound = NULL;
726 $fieldID = empty($fields['field_id']) ?
0 : $fields['field_id'];
727 // Is this a primary location type field of interest
728 if (array_key_exists($profileFieldName, $checkPrimary)) {
729 $whereCheck = $checkPrimary[$profileFieldName];
731 $potentialLocationType = CRM_Utils_Array
::value(2, $fields['field_name']);
733 if ($whereCheck && $potentialLocationType == 0) {
734 $primaryOfSameTypeFound = '';
736 foreach ($groupFields as $groupField) {
738 if ($groupField['where'] == $whereCheck && is_null($groupField['location_type_id']) && $groupField['field_id'] != $fieldID) {
739 $primaryOfSameTypeFound = $groupField['title'];
743 if ($primaryOfSameTypeFound) {
744 $errors['field_name'] = ts('You have already added a primary location field of this type: %1', $primaryOfSameTypeFound);
750 * global validation rules for the form
752 * @param array $fields posted values of the form
757 * @return array list of errors to be posted back to the form
761 static function formRule($fields, $files, $self) {
762 $is_required = CRM_Utils_Array
::value('is_required', $fields, FALSE);
763 $is_registration = CRM_Utils_Array
::value('is_registration', $fields, FALSE);
764 $is_view = CRM_Utils_Array
::value('is_view', $fields, FALSE);
765 $in_selector = CRM_Utils_Array
::value('in_selector', $fields, FALSE);
766 $is_active = CRM_Utils_Array
::value('is_active', $fields, FALSE);
769 if ($is_view && $is_registration) {
770 $errors['is_registration'] = ts('View Only cannot be selected if this field is to be included on the registration form');
772 if ($is_view && $is_required) {
773 $errors['is_view'] = ts('A View Only field cannot be required');
776 $entityName = $fields['field_name'][0];
778 $errors['field_name'] = ts('Please select a field name');
781 if ($in_selector && in_array($entityName, array(
782 'Contribution', 'Participant', 'Membership', 'Activity'))) {
783 $errors['in_selector'] = ts("'In Selector' cannot be checked for %1 fields.", array(1 => $entityName));
786 $isCustomField = FALSE;
787 $profileFieldName = CRM_Utils_Array
::value(1, $fields['field_name']);
788 if ($profileFieldName) {
789 //get custom field id
790 $customFieldId = explode('_', $profileFieldName);
791 if ($customFieldId[0] == 'custom') {
792 $customField = new CRM_Core_DAO_CustomField();
793 $customField->id
= $customFieldId[1];
794 $customField->find(TRUE);
795 $isCustomField = TRUE;
796 if (!empty($fields['field_id']) && !$customField->is_active
&& $is_active) {
797 $errors['field_name'] = ts('Cannot set this field "Active" since the selected custom field is disabled.');
800 //check if profile already has a different multi-record custom set field configured
801 $customGroupId = CRM_Core_BAO_CustomField
::isMultiRecordField($profileFieldName);
802 if ($customGroupId) {
803 if ($profileMultiRecordCustomGid = CRM_Core_BAO_UFField
::checkMultiRecordFieldExists($self->_gid
)) {
804 if ($customGroupId != $profileMultiRecordCustomGid) {
805 $errors['field_name'] = ts("You cannot configure multi-record custom fields belonging to different custom sets in one profile");
812 // Get list of fields already in the group
813 $groupFields = CRM_Core_BAO_UFGroup
::getFields($fields['group_id'], FALSE, NULL, NULL, NULL, TRUE, NULL, TRUE);
814 // Check if we already added a primary field of the same communication type
815 self
::formRulePrimaryCheck($fields, $profileFieldName, $groupFields, $errors);
817 //check profile is configured for double option process
818 //adding group field, email field should be present in the group
819 //fixed for issue CRM-2861 & CRM-4153
820 if (CRM_Core_BAO_UFGroup
::isProfileDoubleOptin()) {
821 if (CRM_Utils_Array
::value(1, $fields['field_name']) == 'group') {
822 $dao = new CRM_Core_BAO_UFField();
823 $dao->uf_group_id
= $fields['group_id'];
826 while ($dao->fetch()) {
827 //check email field is present in the group
828 if ($dao->field_name
== 'email') {
835 $disableSettingURL = CRM_Utils_System
::url(
836 'civicrm/admin/setting/preferences/mailing',
840 $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));
846 $fieldType = $fields['field_name'][0];
848 //get the group type.
849 $groupType = CRM_Core_BAO_UFGroup
::calculateGroupType($self->_gid
, FALSE, CRM_Utils_Array
::value('field_id', $fields));
851 switch ($fieldType) {
853 self
::formRuleSubType($fieldType, $groupType, $errors);
857 if (in_array('Activity', $groupType) ||
858 in_array('Household', $groupType) ||
859 in_array('Organization', $groupType)
862 //CRM-7603 - need to support activity + individual.
863 //$errors['field_name'] =
864 //ts( 'Cannot add or update profile field type Individual with combination of Household or Organization or Activity' );
865 if (in_array('Household', $groupType) ||
866 in_array('Organization', $groupType)
868 $errors['field_name'] = ts('Cannot add or update profile field type Individual with combination of Household or Organization');
872 self
::formRuleSubType($fieldType, $groupType, $errors);
877 if (in_array('Activity', $groupType) ||
in_array('Individual', $groupType) ||
in_array('Organization', $groupType)) {
878 $errors['field_name'] = ts('Cannot add or update profile field type Household with combination of Individual or Organization or Activity');
881 self
::formRuleSubType($fieldType, $groupType, $errors);
886 if (in_array('Activity', $groupType) ||
in_array('Household', $groupType) ||
in_array('Individual', $groupType)) {
887 $errors['field_name'] = ts('Cannot add or update profile field type Organization with combination of Household or Individual or Activity');
890 self
::formRuleSubType($fieldType, $groupType, $errors);
895 if (in_array('Individual', $groupType) ||
896 in_array('Membership', $groupType) ||
897 in_array('Contribution', $groupType) ||
898 in_array('Organization', $groupType) ||
899 in_array('Household', $groupType) ||
900 in_array('Participant', $groupType)
903 //CRM-7603 - need to support activity + contact type.
904 //$errors['field_name'] =
905 //ts( 'Cannot add or update profile field type Activity with combination Participant or Membership or Contribution or Household or Organization or Individual' );
906 if (in_array('Membership', $groupType) ||
907 in_array('Contribution', $groupType) ||
908 in_array('Participant', $groupType)
910 $errors['field_name'] = ts('Cannot add or update profile field type Activity with combination Participant or Membership or Contribution');
914 self
::formRuleSubType($fieldType, $groupType, $errors);
917 if ($isCustomField && !isset($errors['field_name'])) {
918 self
::formRuleCustomDataExtentColumnValue($customField, $self->_gid
, $fieldType, $errors);
923 if (in_array('Membership', $groupType) ||
in_array('Contribution', $groupType)
924 ||
in_array('Organization', $groupType) ||
in_array('Household', $groupType) ||
in_array('Activity', $groupType)
926 $errors['field_name'] = ts('Cannot add or update profile field type Participant with combination of Activity or Membership or Contribution or Household or Organization.');
929 self
::formRuleSubType($fieldType, $groupType, $errors);
934 //special case where in we allow contribution + oganization fields, for on behalf feature
935 $profileId = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup',
936 'on_behalf_organization', 'id', 'name'
939 if (in_array('Participant', $groupType) ||
in_array('Membership', $groupType)
940 ||
($profileId != $self->_gid
&& in_array('Organization', $groupType)) ||
in_array('Household', $groupType) ||
in_array('Activity', $groupType)
942 $errors['field_name'] = ts('Cannot add or update profile field type Contribution with combination of Activity or Membership or Participant or Household or Organization');
945 self
::formRuleSubType($fieldType, $groupType, $errors);
950 //special case where in we allow contribution + oganization fields, for on behalf feature
951 $profileId = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_UFGroup',
952 'on_behalf_organization', 'id', 'name'
955 if (in_array('Participant', $groupType) ||
in_array('Contribution', $groupType)
956 ||
($profileId != $self->_gid
&& in_array('Organization', $groupType)) ||
in_array('Household', $groupType) ||
in_array('Activity', $groupType)
958 $errors['field_name'] = ts('Cannot add or update profile field type Membership with combination of Activity or Participant or Contribution or Household or Organization');
961 self
::formRuleSubType($fieldType, $groupType, $errors);
966 $profileType = CRM_Core_BAO_UFField
::getProfileType($fields['group_id'], TRUE, FALSE, TRUE);
967 if (CRM_Contact_BAO_ContactType
::isaSubType($fieldType)) {
968 if (CRM_Contact_BAO_ContactType
::isaSubType($profileType)) {
969 if ($fieldType != $profileType) {
970 $errors['field_name'] = ts('Cannot add or update profile field type "%1" with combination of "%2".', array(1 => $fieldType, 2 => $profileType));
974 $basicType = CRM_Contact_BAO_ContactType
::getBasicType($fieldType);
976 $profileType != $basicType &&
977 $profileType != 'Contact'
979 $errors['field_name'] = ts('Cannot add or update profile field type "%1" with combination of "%2".', array(1 => $fieldType, 2 => $profileType));
984 CRM_Utils_Array
::value(1, $fields['field_name']) == 'contact_sub_type' &&
985 !in_array($profileType, array('Individual', 'Household', 'Organization')) &&
986 !in_array($profileType, CRM_Contact_BAO_ContactType
::subTypes())
988 $errors['field_name'] = ts('Cannot add or update profile field Contact Subtype as profile type is not one of Individual, Household or Organization.');
991 return empty($errors) ?
TRUE : $errors;