3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
19 * form to process actions on the field aspect of Custom
21 class CRM_Custom_Form_Field
extends CRM_Core_Form
{
24 * Constants for number of options for data types of multiple option.
26 const NUM_OPTION
= 11;
29 * The custom group id saved to the session for an update.
36 * The field id, used when editing the field
43 * The default custom data/input types, when editing the field
47 protected $_defaultDataType;
50 * Array of custom field values if update mode.
56 * Array for valid combinations of data_type & html_type
60 private static $_dataTypeValues = NULL;
61 private static $_dataTypeKeys = NULL;
63 private static $_dataToLabels = NULL;
66 * Used for mapping data types to html type options.
68 * Each item in this array corresponds to the same index in the dataType array
71 public static $_dataToHTML = [
76 'CheckBox' => 'CheckBox',
77 'Autocomplete-Select' => 'Autocomplete-Select',
79 ['Text' => 'Text', 'Select' => 'Select', 'Radio' => 'Radio'],
80 ['Text' => 'Text', 'Select' => 'Select', 'Radio' => 'Radio'],
81 ['Text' => 'Text', 'Select' => 'Select', 'Radio' => 'Radio'],
82 ['TextArea' => 'TextArea', 'RichTextEditor' => 'RichTextEditor'],
83 ['Date' => 'Select Date'],
85 ['StateProvince' => 'Select State/Province'],
86 ['Country' => 'Select Country'],
89 ['ContactReference' => 'Autocomplete-Select'],
93 * Set variables up before form is built.
97 public function preProcess() {
98 if (!(self
::$_dataTypeKeys)) {
99 self
::$_dataTypeKeys = array_keys(CRM_Core_BAO_CustomField
::dataType());
100 self
::$_dataTypeValues = array_values(CRM_Core_BAO_CustomField
::dataType());
104 $this->_id
= CRM_Utils_Request
::retrieve('id', 'Positive', $this);
107 //get the values form db if update.
109 $params = ['id' => $this->_id
];
110 CRM_Core_BAO_CustomField
::retrieve($params, $this->_values
);
111 // note_length is an alias for the text_length field
112 $this->_values
['note_length'] = $this->_values
['text_length'] ??
NULL;
114 $this->_gid
= $this->_values
['custom_group_id'];
118 $this->_gid
= CRM_Utils_Request
::retrieve('gid', 'Positive', $this);
121 if ($isReserved = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomGroup', $this->_gid
, 'is_reserved', 'id')) {
122 CRM_Core_Error
::statusBounce("You cannot add or edit fields in a reserved custom field-set.");
126 $url = CRM_Utils_System
::url('civicrm/admin/custom/group/field',
127 "reset=1&action=browse&gid={$this->_gid}"
130 $session = CRM_Core_Session
::singleton();
131 $session->pushUserContext($url);
134 if (self
::$_dataToLabels == NULL) {
135 self
::$_dataToLabels = [
137 'Text' => ts('Text'),
138 'Select' => ts('Select'),
139 'Radio' => ts('Radio'),
140 'CheckBox' => ts('CheckBox'),
141 'Autocomplete-Select' => ts('Autocomplete-Select'),
144 'Text' => ts('Text'),
145 'Select' => ts('Select'),
146 'Radio' => ts('Radio'),
149 'Text' => ts('Text'),
150 'Select' => ts('Select'),
151 'Radio' => ts('Radio'),
154 'Text' => ts('Text'),
155 'Select' => ts('Select'),
156 'Radio' => ts('Radio'),
158 ['TextArea' => ts('TextArea'), 'RichTextEditor' => ts('Rich Text Editor')],
159 ['Date' => ts('Select Date')],
160 ['Radio' => ts('Radio')],
161 ['StateProvince' => ts('Select State/Province')],
162 ['Country' => ts('Select Country')],
163 ['File' => ts('Select File')],
164 ['Link' => ts('Link')],
165 ['ContactReference' => ts('Autocomplete-Select')],
171 * Set default values for the form. Note that in edit/view mode
172 * the default values are retrieved from the database
175 * array of default values
177 public function setDefaultValues() {
178 $defaults = $this->_values
;
181 $this->assign('id', $this->_id
);
182 $this->_gid
= $defaults['custom_group_id'];
184 //get the value for state or country
185 if ($defaults['data_type'] == 'StateProvince' &&
186 $stateId = CRM_Utils_Array
::value('default_value', $defaults)
188 $defaults['default_value'] = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_StateProvince', $stateId);
190 elseif ($defaults['data_type'] == 'Country' &&
191 $countryId = CRM_Utils_Array
::value('default_value', $defaults)
193 $defaults['default_value'] = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_Country', $countryId);
196 if ($defaults['data_type'] == 'ContactReference' && !empty($defaults['filter'])) {
197 $contactRefFilter = 'Advance';
198 if (strpos($defaults['filter'], 'action=lookup') !== FALSE &&
199 strpos($defaults['filter'], 'group=') !== FALSE
201 $filterParts = explode('&', $defaults['filter']);
203 if (count($filterParts) == 2) {
204 $contactRefFilter = 'Group';
205 foreach ($filterParts as $part) {
206 if (strpos($part, 'group=') === FALSE) {
209 $groups = substr($part, strpos($part, '=') +
1);
210 foreach (explode(',', $groups) as $grp) {
211 if (CRM_Utils_Rule
::positiveInteger($grp)) {
212 $defaults['group_id'][] = $grp;
218 $defaults['filter_selected'] = $contactRefFilter;
221 if (!empty($defaults['data_type'])) {
222 $defaultDataType = array_search($defaults['data_type'],
225 $defaultHTMLType = array_search($defaults['html_type'],
226 self
::$_dataToHTML[$defaultDataType]
228 $defaults['data_type'] = [
229 '0' => $defaultDataType,
230 '1' => $defaultHTMLType,
232 $this->_defaultDataType
= $defaults['data_type'];
235 $defaults['option_type'] = 2;
237 $this->assign('changeFieldType', CRM_Custom_Form_ChangeFieldType
::fieldTypeTransitions($this->_values
['data_type'], $this->_values
['html_type']));
240 $defaults['is_active'] = 1;
241 $defaults['option_type'] = 1;
242 $defaults['is_search_range'] = 1;
245 // set defaults for weight.
246 for ($i = 1; $i <= self
::NUM_OPTION
; $i++
) {
247 $defaults['option_status[' . $i . ']'] = 1;
248 $defaults['option_weight[' . $i . ']'] = $i;
249 $defaults['option_value[' . $i . ']'] = $i;
252 if ($this->_action
& CRM_Core_Action
::ADD
) {
253 $fieldValues = ['custom_group_id' => $this->_gid
];
254 $defaults['weight'] = CRM_Utils_Weight
::getDefaultWeight('CRM_Core_DAO_CustomField', $fieldValues);
256 $defaults['text_length'] = 255;
257 $defaults['note_columns'] = 60;
258 $defaults['note_rows'] = 4;
259 $defaults['is_view'] = 0;
262 if (!empty($defaults['html_type'])) {
263 $dontShowLink = substr($defaults['html_type'], -14) == 'State/Province' ||
substr($defaults['html_type'], -7) == 'Country' ?
1 : 0;
266 if (isset($dontShowLink)) {
267 $this->assign('dontShowLink', $dontShowLink);
269 if ($this->_action
& CRM_Core_Action
::ADD
&&
270 CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomGroup', $this->_gid
, 'is_multiple', 'id')
272 $defaults['in_selector'] = 1;
279 * Build the form object.
283 public function buildQuickForm() {
285 $this->_title
= CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomGroup', $this->_gid
, 'title');
286 CRM_Utils_System
::setTitle($this->_title
. ' - ' . ($this->_id ?
ts('Edit Field') : ts('New Field')));
287 $this->assign('gid', $this->_gid
);
290 $this->assign('dataTypeKeys', self
::$_dataTypeKeys);
292 // lets trim all the whitespace
293 $this->applyFilter('__ALL__', 'trim');
295 $attributes = CRM_Core_DAO
::getAttribute('CRM_Core_DAO_CustomField');
301 $attributes['label'],
305 $dt = &self
::$_dataTypeValues;
307 foreach ($dt as $key => $value) {
308 $it[$key] = self
::$_dataToLabels[$key];
310 $sel = &$this->addElement('hierselect',
312 ts('Data and Input Field Type'),
315 $sel->setOptions([$dt, $it]);
317 if (CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomGroup', $this->_gid
, 'is_multiple')) {
318 $this->add('checkbox', 'in_selector', ts('Display in Table?'));
321 $optionGroupParams = [
324 'options' => ['limit' => 0, 'sort' => "title ASC"],
325 'return' => ['title'],
328 $this->add('checkbox', 'serialize', ts('Multi-Select'));
330 if ($this->_action
== CRM_Core_Action
::UPDATE
) {
331 $this->freeze('data_type');
332 if (!empty($this->_values
['option_group_id'])) {
333 // Before dev/core#155 we didn't set the is_reserved flag properly, which should be handled by the upgrade script...
334 // but it is still possible that existing installs may have optiongroups linked to custom fields that are marked reserved.
335 $optionGroupParams['id'] = $this->_values
['option_group_id'];
336 $optionGroupParams['options']['or'] = [["is_reserved", "id"]];
340 // Retrieve optiongroups for selection list
341 $optionGroupMetadata = civicrm_api3('OptionGroup', 'get', $optionGroupParams);
343 // OptionGroup selection
344 $optionTypes = ['1' => ts('Create a new set of options')];
346 if (!empty($optionGroupMetadata['values'])) {
347 $emptyOptGroup = FALSE;
348 $optionGroups = CRM_Utils_Array
::collect('title', $optionGroupMetadata['values']);
349 $optionTypes['2'] = ts('Reuse an existing set');
353 ts('Multiple Choice Option Sets'),
355 '' => ts('- select -'),
360 // No custom (non-reserved) option groups
361 $emptyOptGroup = TRUE;
364 $element = &$this->addRadio('option_type',
368 'onclick' => "showOptionSelect();",
371 // if empty option group freeze the option type.
372 if ($emptyOptGroup) {
376 $contactGroups = CRM_Core_PseudoConstant
::group();
377 asort($contactGroups);
381 ts('Limit List to Group'),
384 ['multiple' => 'multiple', 'class' => 'crm-select2']
389 ts('Advanced Filter'),
390 $attributes['filter']
393 $this->add('hidden', 'filter_selected', 'Group', ['id' => 'filter_selected']);
395 // form fields of Custom Option rows
397 $_showHide = new CRM_Core_ShowHideBlocks('', '');
398 for ($i = 1; $i <= self
::NUM_OPTION
; $i++
) {
400 //the show hide blocks
401 $showBlocks = 'optionField_' . $i;
403 $_showHide->addHide($showBlocks);
404 if ($i == self
::NUM_OPTION
) {
405 $_showHide->addHide('additionalOption');
409 $_showHide->addShow($showBlocks);
412 $optionAttributes = CRM_Core_DAO
::getAttribute('CRM_Core_DAO_OptionValue');
414 $this->add('text', 'option_label[' . $i . ']', ts('Label'),
415 $optionAttributes['label']
419 $this->add('text', 'option_value[' . $i . ']', ts('Value'),
420 $optionAttributes['value']
424 $this->add('number', "option_weight[$i]", ts('Order'),
425 $optionAttributes['weight']
429 $this->add('checkbox', "option_status[$i]", ts('Active?'));
431 $defaultOption[$i] = $this->createElement('radio', NULL, NULL, NULL, $i);
433 //for checkbox handling of default option
434 $this->add('checkbox', "default_checkbox_option[$i]", NULL);
437 //default option selection
438 $this->addGroup($defaultOption, 'default_option');
440 $_showHide->addToTemplate();
442 // text length for alpha numeric data types
445 ts('Database field length'),
446 $attributes['text_length'] +
['min' => 1],
449 $this->addRule('text_length', ts('Value should be a positive number'), 'integer');
453 ts('Dates may be up to'),
454 $attributes['start_date_years'],
459 ts('Dates may be up to'),
460 $attributes['end_date_years'],
464 $this->addRule('start_date_years', ts('Value should be a positive number'), 'integer');
465 $this->addRule('end_date_years', ts('Value should be a positive number'), 'integer');
467 $this->add('select', 'date_format', ts('Date Format'),
468 ['' => ts('- select -')] + CRM_Core_SelectValues
::getDatePluginInputFormats()
471 $this->add('select', 'time_format', ts('Time'),
472 ['' => ts('- none -')] + CRM_Core_SelectValues
::getTimeFormats()
478 ts('Width (columns)') . ' ',
479 $attributes['note_columns'],
484 ts('Height (rows)') . ' ',
485 $attributes['note_rows'],
490 ts('Maximum length') . ' ',
491 // note_length is an alias for the text-length field
492 $attributes['text_length'],
496 $this->addRule('note_columns', ts('Value should be a positive number'), 'positiveInteger');
497 $this->addRule('note_rows', ts('Value should be a positive number'), 'positiveInteger');
498 $this->addRule('note_length', ts('Value should be a positive number'), 'positiveInteger');
501 $this->add('number', 'weight', ts('Order'),
502 $attributes['weight'],
505 $this->addRule('weight', ts('is a numeric field'), 'numeric');
508 $this->add('advcheckbox', 'is_required', ts('Required?'));
510 // checkbox / radio options per line
511 $this->add('number', 'options_per_line', ts('Options Per Line'), ['min' => 0]);
512 $this->addRule('options_per_line', ts('must be a numeric value'), 'numeric');
514 // default value, help pre, help post, mask, attributes, javascript ?
515 $this->add('text', 'default_value', ts('Default Value'),
516 $attributes['default_value']
518 $this->add('textarea', 'help_pre', ts('Field Pre Help'),
519 $attributes['help_pre']
521 $this->add('textarea', 'help_post', ts('Field Post Help'),
522 $attributes['help_post']
524 $this->add('text', 'mask', ts('Mask'),
529 $this->add('advcheckbox', 'is_active', ts('Active?'));
532 $this->add('advcheckbox', 'is_view', ts('View Only?'));
535 $this->addElement('advcheckbox',
537 ts('Is this Field Searchable?')
540 // is searchable by range?
541 $this->addRadio('is_search_range', ts('Search by Range?'), [ts('No'), ts('Yes')]);
547 'name' => ts('Save'),
552 'name' => ts('Save and New'),
557 'name' => ts('Cancel'),
561 // add a form rule to check default value
562 $this->addFormRule(['CRM_Custom_Form_Field', 'formRule'], $this);
564 // if view mode pls freeze it with the done button.
565 if ($this->_action
& CRM_Core_Action
::VIEW
) {
567 $url = CRM_Utils_System
::url('civicrm/admin/custom/group/field', 'reset=1&action=browse&gid=' . $this->_gid
);
568 $this->addElement('button',
571 ['onclick' => "location.href='$url'"]
577 * Global validation rules for the form.
579 * @param array $fields
580 * Posted values of the form.
586 * if errors then list of errors to be posted back to the form,
589 public static function formRule($fields, $files, $self) {
590 $default = $fields['default_value'] ??
NULL;
594 self
::clearEmptyOptions($fields);
596 //validate field label as well as name.
597 $title = $fields['label'];
598 $name = CRM_Utils_String
::munge($title, '_', 64);
601 $query = 'select count(*) from civicrm_custom_field where ( name like %1 OR label like %2 ) and id != %3 and custom_group_id = %4';
602 $fldCnt = CRM_Core_DAO
::singleValueQuery($query, [
603 1 => [$name, 'String'],
604 2 => [$title, 'String'],
605 3 => [(int) $self->_id
, 'Integer'],
606 4 => [$gId, 'Integer'],
609 $errors['label'] = ts('Custom field \'%1\' already exists in Database.', [1 => $title]);
612 //checks the given custom field name doesnot start with digit
613 if (!empty($title)) {
614 // gives the ascii value
615 $asciiValue = ord($title[0]);
616 if ($asciiValue >= 48 && $asciiValue <= 57) {
617 $errors['label'] = ts("Name cannot not start with a digit");
621 // ensure that the label is not 'id'
622 if (strtolower($title) == 'id') {
623 $errors['label'] = ts("You cannot use 'id' as a field label.");
626 if (!isset($fields['data_type'][0]) ||
!isset($fields['data_type'][1])) {
627 $errors['_qf_default'] = ts('Please enter valid - Data and Input Field Type.');
630 $dataType = self
::$_dataTypeKeys[$fields['data_type'][0]];
632 if ($default ||
$dataType == 'ContactReference') {
635 if (!CRM_Utils_Rule
::integer($default)) {
636 $errors['default_value'] = ts('Please enter a valid integer.');
641 if (!CRM_Utils_Rule
::numeric($default)) {
642 $errors['default_value'] = ts('Please enter a valid number.');
647 if (!CRM_Utils_Rule
::money($default)) {
648 $errors['default_value'] = ts('Please enter a valid number.');
653 if (!CRM_Utils_Rule
::url($default)) {
654 $errors['default_value'] = ts('Please enter a valid link.');
659 if (!CRM_Utils_Rule
::date($default)) {
660 $errors['default_value'] = ts('Please enter a valid date as default value using YYYY-MM-DD format. Example: 2004-12-31.');
665 if ($default != '1' && $default != '0') {
666 $errors['default_value'] = ts('Please enter 1 (for Yes) or 0 (for No) if you want to set a default value.');
671 if (!empty($default)) {
672 $query = "SELECT count(*) FROM civicrm_country WHERE name = %1 OR iso_code = %1";
673 $params = [1 => [$fields['default_value'], 'String']];
674 if (CRM_Core_DAO
::singleValueQuery($query, $params) <= 0) {
675 $errors['default_value'] = ts('Invalid default value for country.');
680 case 'StateProvince':
681 if (!empty($default)) {
684 FROM civicrm_state_province
686 OR abbreviation = %1";
687 $params = [1 => [$fields['default_value'], 'String']];
688 if (CRM_Core_DAO
::singleValueQuery($query, $params) <= 0) {
689 $errors['default_value'] = ts('The invalid default value for State/Province data type');
694 case 'ContactReference':
695 if ($fields['filter_selected'] == 'Advance' && !empty($fields['filter'])) {
696 if (strpos($fields['filter'], 'entity=') !== FALSE) {
697 $errors['filter'] = ts("Please do not include entity parameter (entity is always 'contact')");
699 elseif (strpos($fields['filter'], 'action=get') === FALSE) {
700 $errors['filter'] = ts("Only 'get' action is supported.");
703 $self->setDefaults(['filter_selected', $fields['filter_selected']]);
708 if (self
::$_dataTypeKeys[$fields['data_type'][0]] == 'Date') {
709 if (!$fields['date_format']) {
710 $errors['date_format'] = ts('Please select a date format.');
714 /** Check the option values entered
715 * Appropriate values are required for the selected datatype
716 * Incomplete row checking is also required.
718 $_flagOption = $_rowError = 0;
719 $_showHide = new CRM_Core_ShowHideBlocks('', '');
720 $dataType = self
::$_dataTypeKeys[$fields['data_type'][0]];
721 if (isset($fields['data_type'][1])) {
722 $dataField = $fields['data_type'][1];
724 $optionFields = ['Select', 'CheckBox', 'Radio'];
726 if (isset($fields['option_type']) && $fields['option_type'] == 1) {
727 //capture duplicate Custom option values
728 if (!empty($fields['option_value'])) {
729 $countValue = count($fields['option_value']);
730 $uniqueCount = count(array_unique($fields['option_value']));
732 if ($countValue > $uniqueCount) {
735 while ($start < self
::NUM_OPTION
) {
736 $nextIndex = $start +
1;
737 while ($nextIndex <= self
::NUM_OPTION
) {
738 if ($fields['option_value'][$start] == $fields['option_value'][$nextIndex] &&
739 strlen($fields['option_value'][$nextIndex])
741 $errors['option_value[' . $start . ']'] = ts('Duplicate Option values');
742 $errors['option_value[' . $nextIndex . ']'] = ts('Duplicate Option values');
752 //capture duplicate Custom Option label
753 if (!empty($fields['option_label'])) {
754 $countValue = count($fields['option_label']);
755 $uniqueCount = count(array_unique($fields['option_label']));
757 if ($countValue > $uniqueCount) {
759 while ($start < self
::NUM_OPTION
) {
760 $nextIndex = $start +
1;
761 while ($nextIndex <= self
::NUM_OPTION
) {
762 if ($fields['option_label'][$start] == $fields['option_label'][$nextIndex] &&
763 !empty($fields['option_label'][$nextIndex])
765 $errors['option_label[' . $start . ']'] = ts('Duplicate Option label');
766 $errors['option_label[' . $nextIndex . ']'] = ts('Duplicate Option label');
776 for ($i = 1; $i <= self
::NUM_OPTION
; $i++
) {
777 if (!$fields['option_label'][$i]) {
778 if ($fields['option_value'][$i]) {
779 $errors['option_label[' . $i . ']'] = ts('Option label cannot be empty');
787 if (!strlen(trim($fields['option_value'][$i]))) {
788 if (!$fields['option_value'][$i]) {
789 $errors['option_value[' . $i . ']'] = ts('Option value cannot be empty');
795 if ($fields['option_value'][$i] && $dataType != 'String') {
796 if ($dataType == 'Int') {
797 if (!CRM_Utils_Rule
::integer($fields['option_value'][$i])) {
799 $errors['option_value[' . $i . ']'] = ts('Please enter a valid integer.');
802 elseif ($dataType == 'Money') {
803 if (!CRM_Utils_Rule
::money($fields['option_value'][$i])) {
805 $errors['option_value[' . $i . ']'] = ts('Please enter a valid money value.');
809 if (!CRM_Utils_Rule
::numeric($fields['option_value'][$i])) {
811 $errors['option_value[' . $i . ']'] = ts('Please enter a valid number.');
816 $showBlocks = 'optionField_' . $i;
818 $_showHide->addShow($showBlocks);
822 if (!empty($_emptyRow)) {
823 $_showHide->addHide($showBlocks);
826 $_showHide->addShow($showBlocks);
828 if ($i == self
::NUM_OPTION
) {
829 $hideBlock = 'additionalOption';
830 $_showHide->addHide($hideBlock);
833 $_flagOption = $_emptyRow = 0;
836 elseif (isset($dataField) &&
837 in_array($dataField, $optionFields) &&
838 !in_array($dataType, ['Boolean', 'Country', 'StateProvince'])
840 if (!$fields['option_group_id']) {
841 $errors['option_group_id'] = ts('You must select a Multiple Choice Option set if you chose Reuse an existing set.');
846 FROM civicrm_custom_field
847 WHERE data_type != %1
848 AND option_group_id = %2";
851 self
::$_dataTypeKeys[$fields['data_type'][0]],
854 2 => [$fields['option_group_id'], 'Integer'],
856 $count = CRM_Core_DAO
::singleValueQuery($query, $params);
858 $errors['option_group_id'] = ts('The data type of the multiple choice option set you\'ve selected does not match the data type assigned to this field.');
863 $assignError = new CRM_Core_Page();
865 $_showHide->addToTemplate();
866 $assignError->assign('optionRowError', $_rowError);
869 if (isset($fields['data_type'][1])) {
870 switch (self
::$_dataToHTML[$fields['data_type'][0]][$fields['data_type'][1]]) {
873 $assignError->assign('fieldError', $_fieldError);
878 $assignError->assign('fieldError', $_fieldError);
883 $assignError->assign('fieldError', $_fieldError);
888 $assignError->assign('fieldError', $_fieldError);
892 for ($idx = 1; $idx <= self
::NUM_OPTION
; $idx++
) {
893 $showBlocks = 'optionField_' . $idx;
894 if (!empty($fields['option_label'][$idx])) {
895 $_showHide->addShow($showBlocks);
898 $_showHide->addHide($showBlocks);
901 $_showHide->addToTemplate();
904 // we can not set require and view at the same time.
905 if (!empty($fields['is_required']) && !empty($fields['is_view'])) {
906 $errors['is_view'] = ts('Can not set this field Required and View Only at the same time.');
909 return empty($errors) ?
TRUE : $errors;
917 public function postProcess() {
918 // store the submitted values in an array
919 $params = $this->controller
->exportValues($this->_name
);
920 self
::clearEmptyOptions($params);
921 if ($this->_action
== CRM_Core_Action
::UPDATE
) {
922 $dataTypeKey = $this->_defaultDataType
[0];
923 $params['data_type'] = self
::$_dataTypeKeys[$this->_defaultDataType
[0]];
924 $params['html_type'] = self
::$_dataToHTML[$this->_defaultDataType
[0]][$this->_defaultDataType
[1]];
927 $dataTypeKey = $params['data_type'][0];
928 $params['html_type'] = self
::$_dataToHTML[$params['data_type'][0]][$params['data_type'][1]];
929 $params['data_type'] = self
::$_dataTypeKeys[$params['data_type'][0]];
932 //fix for 'is_search_range' field.
933 if (in_array($dataTypeKey, [
939 if (empty($params['is_searchable'])) {
940 $params['is_search_range'] = 0;
944 $params['is_search_range'] = 0;
947 // Serialization cannot be changed on update
949 unset($params['serialize']);
951 elseif (strpos($params['html_type'], 'Select') === 0) {
952 $params['serialize'] = $params['serialize'] ? CRM_Core_DAO
::SERIALIZE_SEPARATOR_BOOKEND
: 'null';
955 $params['serialize'] = $params['html_type'] == 'CheckBox' ? CRM_Core_DAO
::SERIALIZE_SEPARATOR_BOOKEND
: 'null';
959 if ($dataTypeKey == 11 && !empty($params['filter_selected'])) {
960 if ($params['filter_selected'] == 'Advance' && trim(CRM_Utils_Array
::value('filter', $params))) {
961 $filter = trim($params['filter']);
963 elseif ($params['filter_selected'] == 'Group' && !empty($params['group_id'])) {
965 $filter = 'action=lookup&group=' . implode(',', $params['group_id']);
968 $params['filter'] = $filter;
972 if ($this->_action
& (CRM_Core_Action
::UPDATE | CRM_Core_Action
::ADD
)) {
973 $fieldValues = ['custom_group_id' => $this->_gid
];
975 $oldWeight = $this->_values
['weight'];
977 $params['weight'] = CRM_Utils_Weight
::updateOtherWeights('CRM_Core_DAO_CustomField', $oldWeight, $params['weight'], $fieldValues);
980 $strtolower = function_exists('mb_strtolower') ?
'mb_strtolower' : 'strtolower';
982 //store the primary key for State/Province or Country as default value.
983 if (strlen(trim($params['default_value']))) {
984 switch ($params['data_type']) {
985 case 'StateProvince':
986 $fieldStateProvince = $strtolower($params['default_value']);
988 // LOWER in query below roughly translates to 'hurt my database without deriving any benefit' See CRM-19811.
991 FROM civicrm_state_province
992 WHERE LOWER(name) = '$fieldStateProvince'
993 OR abbreviation = '$fieldStateProvince'";
994 $dao = CRM_Core_DAO
::executeQuery($query);
996 $params['default_value'] = $dao->id
;
1001 $fieldCountry = $strtolower($params['default_value']);
1003 // LOWER in query below roughly translates to 'hurt my database without deriving any benefit' See CRM-19811.
1006 FROM civicrm_country
1007 WHERE LOWER(name) = '$fieldCountry'
1008 OR iso_code = '$fieldCountry'";
1009 $dao = CRM_Core_DAO
::executeQuery($query);
1010 if ($dao->fetch()) {
1011 $params['default_value'] = $dao->id
;
1017 // The text_length attribute for Memo fields is in a different input as there
1018 // are different label, help text and default value than for other type fields
1019 if ($params['data_type'] == "Memo") {
1020 $params['text_length'] = $params['note_length'];
1023 // need the FKEY - custom group id
1024 $params['custom_group_id'] = $this->_gid
;
1026 if ($this->_action
& CRM_Core_Action
::UPDATE
) {
1027 $params['id'] = $this->_id
;
1029 $customField = CRM_Core_BAO_CustomField
::create($params);
1030 $this->_id
= $customField->id
;
1033 Civi
::cache('fields')->flush();
1035 $msg = '<p>' . ts("Custom field '%1' has been saved.", [1 => $customField->label
]) . '</p>';
1037 $buttonName = $this->controller
->getButtonName();
1038 $session = CRM_Core_Session
::singleton();
1039 if ($buttonName == $this->getButtonName('next', 'new')) {
1040 $msg .= '<p>' . ts("Ready to add another.") . '</p>';
1041 $session->replaceUserContext(CRM_Utils_System
::url('civicrm/admin/custom/group/field/add',
1042 'reset=1&action=add&gid=' . $this->_gid
1046 $session->replaceUserContext(CRM_Utils_System
::url('civicrm/admin/custom/group/field',
1047 'reset=1&action=browse&gid=' . $this->_gid
1050 $session->setStatus($msg, ts('Saved'), 'success');
1052 // Add data when in ajax contect
1053 $this->ajaxResponse
['customField'] = $customField->toArray();
1057 * Removes value from fields with no label.
1059 * This allows default values to be set in the form, but ignored in post-processing.
1061 * @param array $fields
1063 public static function clearEmptyOptions(&$fields) {
1064 foreach ($fields['option_label'] as $i => $label) {
1065 if (!strlen(trim($label))) {
1066 $fields['option_value'][$i] = '';