['Text', 'Select', 'Radio', 'CheckBox', 'Autocomplete-Select'], 'Int' => ['Text', 'Select', 'Radio'], 'Float' => ['Text', 'Select', 'Radio'], 'Money' => ['Text', 'Select', 'Radio'], 'Memo' => ['TextArea', 'RichTextEditor'], 'Date' => ['Select Date'], 'Boolean' => ['Radio'], 'StateProvince' => ['Select'], 'Country' => ['Select'], 'File' => ['File'], 'Link' => ['Link'], 'ContactReference' => ['Autocomplete-Select'], ]; /** * Set variables up before form is built. * * @return void */ public function preProcess() { $this->_id = CRM_Utils_Request::retrieve('id', 'Positive', $this); $this->setAction($this->_id ? CRM_Core_Action::UPDATE : CRM_Core_Action::ADD); $this->assign('dataToHTML', self::$_dataToHTML); $this->_values = []; //get the values form db if update. if ($this->_id) { CRM_Core_BAO_CustomField::retrieve(['id' => $this->_id], $this->_values); // note_length is an alias for the text_length field $this->_values['note_length'] = $this->_values['text_length'] ?? NULL; // custom group id $this->_gid = $this->_values['custom_group_id']; } else { // custom group id $this->_gid = CRM_Utils_Request::retrieve('gid', 'Positive', $this); } if (CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $this->_gid, 'is_reserved')) { CRM_Core_Error::statusBounce("You cannot add or edit fields in a reserved custom field-set."); } if ($this->_gid) { $url = CRM_Utils_System::url('civicrm/admin/custom/group/field', "reset=1&gid={$this->_gid}" ); $session = CRM_Core_Session::singleton(); $session->pushUserContext($url); } } /** * Set default values for the form. Note that in edit/view mode * the default values are retrieved from the database * * @return array * array of default values */ public function setDefaultValues() { $defaults = $this->_values; // Defaults for update mode if ($this->_id) { $this->assign('id', $this->_id); $this->_gid = $defaults['custom_group_id']; $defaultValue = $defaults['default_value'] ?? NULL; if ($defaults['data_type'] == 'ContactReference' && !empty($defaults['filter'])) { $contactRefFilter = 'Advance'; if (strpos($defaults['filter'], 'action=lookup') !== FALSE && strpos($defaults['filter'], 'group=') !== FALSE ) { $filterParts = explode('&', $defaults['filter']); if (count($filterParts) == 2) { $contactRefFilter = 'Group'; foreach ($filterParts as $part) { if (strpos($part, 'group=') === FALSE) { continue; } $groups = substr($part, strpos($part, '=') + 1); foreach (explode(',', $groups) as $grp) { if (CRM_Utils_Rule::positiveInteger($grp)) { $defaults['group_id'][] = $grp; } } } } } $defaults['filter_selected'] = $contactRefFilter; } $defaults['option_type'] = 2; } // Defaults for create mode if ($this->_action & CRM_Core_Action::ADD) { $defaults['data_type'] = 'String'; $defaults['html_type'] = 'Text'; $defaults['is_active'] = 1; $defaults['option_type'] = 1; $defaults['is_search_range'] = 0; $defaults['weight'] = CRM_Utils_Weight::getDefaultWeight('CRM_Core_DAO_CustomField', ['custom_group_id' => $this->_gid]); $defaults['text_length'] = 255; $defaults['note_columns'] = 60; $defaults['note_rows'] = 4; $defaults['is_view'] = 0; if (CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $this->_gid, 'is_multiple')) { $defaults['in_selector'] = 1; } } // Set defaults for option values. for ($i = 1; $i <= self::NUM_OPTION; $i++) { $defaults['option_status[' . $i . ']'] = 1; $defaults['option_weight[' . $i . ']'] = $i; $defaults['option_value[' . $i . ']'] = $i; } return $defaults; } /** * Build the form object. * * @return void */ public function buildQuickForm() { if ($this->_gid) { $this->_title = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $this->_gid, 'title'); $this->setTitle($this->_title . ' - ' . ($this->_id ? ts('Edit Field') : ts('New Field'))); } $this->assign('gid', $this->_gid); // lets trim all the whitespace $this->applyFilter('__ALL__', 'trim'); $attributes = CRM_Core_DAO::getAttribute('CRM_Core_DAO_CustomField'); // label $this->add('text', 'label', ts('Field Label'), $attributes['label'], TRUE ); // FIXME: Switch addField to use APIv4 so we don't get those legacy options from v3 $htmlOptions = CRM_Core_BAO_CustomField::buildOptions('html_type', 'create'); $this->addField('data_type', ['class' => 'twenty'], TRUE); $this->addField('html_type', ['class' => 'twenty', 'options' => $htmlOptions], TRUE); if (CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $this->_gid, 'is_multiple')) { $this->add('checkbox', 'in_selector', ts('Display in Table?')); } $optionGroupParams = [ 'is_reserved' => 0, 'is_active' => 1, 'options' => ['limit' => 0, 'sort' => "title ASC"], 'return' => ['title'], ]; $this->add('checkbox', 'serialize', ts('Multi-Select')); if ($this->_action == CRM_Core_Action::UPDATE) { $this->freeze('data_type'); if (!empty($this->_values['option_group_id'])) { $this->assign('hasOptionGroup', in_array($this->_values['html_type'], self::$htmlTypesWithOptions)); // Before dev/core#155 we didn't set the is_reserved flag properly, which should be handled by the upgrade script... // but it is still possible that existing installs may have optiongroups linked to custom fields that are marked reserved. $optionGroupParams['id'] = $this->_values['option_group_id']; $optionGroupParams['options']['or'] = [["is_reserved", "id"]]; } $this->assign('originalHtmlType', $this->_values['html_type']); $this->assign('originalSerialize', $this->_values['serialize']); if (!empty($this->_values['serialize'])) { $this->assign('existingMultiValueCount', $this->getMultiValueCount()); } } // Retrieve optiongroups for selection list $optionGroupMetadata = civicrm_api3('OptionGroup', 'get', $optionGroupParams); // OptionGroup selection $optionTypes = ['1' => ts('Create a new set of options')]; if (!empty($optionGroupMetadata['values'])) { $emptyOptGroup = FALSE; $optionGroups = CRM_Utils_Array::collect('title', $optionGroupMetadata['values']); $optionTypes['2'] = ts('Reuse an existing set'); $this->add('select', 'option_group_id', ts('Multiple Choice Option Sets'), [ '' => ts('- select -'), ] + $optionGroups ); } else { // No custom (non-reserved) option groups $emptyOptGroup = TRUE; } $element = &$this->addRadio('option_type', ts('Option Type'), $optionTypes, [ 'onclick' => "showOptionSelect();", ], '
' ); // if empty option group freeze the option type. if ($emptyOptGroup) { $element->freeze(); } $contactGroups = CRM_Core_PseudoConstant::group(); asort($contactGroups); $this->add('select', 'group_id', ts('Limit List to Group'), $contactGroups, FALSE, ['multiple' => 'multiple', 'class' => 'crm-select2'] ); $this->add('text', 'filter', ts('Advanced Filter'), $attributes['filter'] ); $this->add('hidden', 'filter_selected', 'Group', ['id' => 'filter_selected']); // form fields of Custom Option rows $defaultOption = []; $_showHide = new CRM_Core_ShowHideBlocks(); for ($i = 1; $i <= self::NUM_OPTION; $i++) { //the show hide blocks $showBlocks = 'optionField_' . $i; if ($i > 2) { $_showHide->addHide($showBlocks); if ($i == self::NUM_OPTION) { $_showHide->addHide('additionalOption'); } } else { $_showHide->addShow($showBlocks); } $optionAttributes = CRM_Core_DAO::getAttribute('CRM_Core_DAO_OptionValue'); // label $this->add('text', 'option_label[' . $i . ']', ts('Label'), $optionAttributes['label'] ); // value $this->add('text', 'option_value[' . $i . ']', ts('Value'), $optionAttributes['value'] ); // weight $this->add('number', "option_weight[$i]", ts('Order'), $optionAttributes['weight'] ); // is active ? $this->add('checkbox', "option_status[$i]", ts('Active?')); $defaultOption[$i] = NULL; //for checkbox handling of default option $this->add('checkbox', "default_checkbox_option[$i]", NULL); } //default option selection $this->addRadio('default_option', NULL, $defaultOption); $_showHide->addToTemplate(); // text length for alpha numeric data types $this->add('number', 'text_length', ts('Database field length'), $attributes['text_length'] + ['min' => 1], FALSE ); $this->addRule('text_length', ts('Value should be a positive number'), 'integer'); $this->add('text', 'start_date_years', ts('Dates may be up to'), $attributes['start_date_years'], FALSE ); $this->add('text', 'end_date_years', ts('Dates may be up to'), $attributes['end_date_years'], FALSE ); $this->addRule('start_date_years', ts('Value should be a positive number'), 'integer'); $this->addRule('end_date_years', ts('Value should be a positive number'), 'integer'); $this->add('select', 'date_format', ts('Date Format'), ['' => ts('- select -')] + CRM_Core_SelectValues::getDatePluginInputFormats() ); $this->add('select', 'time_format', ts('Time'), ['' => ts('- none -')] + CRM_Core_SelectValues::getTimeFormats() ); // for Note field $this->add('number', 'note_columns', ts('Width (columns)') . ' ', $attributes['note_columns'], FALSE ); $this->add('number', 'note_rows', ts('Height (rows)') . ' ', $attributes['note_rows'], FALSE ); $this->add('number', 'note_length', ts('Maximum length') . ' ', // note_length is an alias for the text-length field $attributes['text_length'], FALSE ); $this->addRule('note_columns', ts('Value should be a positive number'), 'positiveInteger'); $this->addRule('note_rows', ts('Value should be a positive number'), 'positiveInteger'); $this->addRule('note_length', ts('Value should be a positive number'), 'positiveInteger'); // weight $this->add('number', 'weight', ts('Order'), $attributes['weight'], TRUE ); $this->addRule('weight', ts('is a numeric field'), 'numeric'); // is required ? $this->add('advcheckbox', 'is_required', ts('Required?')); // checkbox / radio options per line $this->add('number', 'options_per_line', ts('Options Per Line'), ['min' => 0]); $this->addRule('options_per_line', ts('must be a numeric value'), 'numeric'); // default value, help pre, help post, mask, attributes, javascript ? $this->add('text', 'default_value', ts('Default Value'), $attributes['default_value'] ); $this->add('textarea', 'help_pre', ts('Field Pre Help'), $attributes['help_pre'] ); $this->add('textarea', 'help_post', ts('Field Post Help'), $attributes['help_post'] ); $this->add('text', 'mask', ts('Mask'), $attributes['mask'] ); // is active ? $this->add('advcheckbox', 'is_active', ts('Active?')); // is active ? $this->add('advcheckbox', 'is_view', ts('View Only?')); // is searchable ? $this->addElement('advcheckbox', 'is_searchable', ts('Is this Field Searchable?') ); // is searchable by range? $this->addRadio('is_search_range', ts('Search by Range?'), [ts('No'), ts('Yes')]); $buttons = [ [ 'type' => 'done', 'name' => ts('Save'), 'isDefault' => TRUE, ], [ 'type' => 'next', 'name' => ts('Save and New'), 'subName' => 'new', ], [ 'type' => 'cancel', 'name' => ts('Cancel'), ], ]; // Save & new only applies to adding a field if ($this->_id) { unset($buttons[1]); } // add buttons $this->addButtons($buttons); // add a form rule to check default value $this->addFormRule(['CRM_Custom_Form_Field', 'formRule'], $this); // if view mode pls freeze it with the done button. if ($this->_action & CRM_Core_Action::VIEW) { $this->freeze(); $url = CRM_Utils_System::url('civicrm/admin/custom/group/field', 'reset=1&gid=' . $this->_gid); $this->addElement('xbutton', 'done', ts('Done'), [ 'type' => 'button', 'onclick' => "location.href='$url'", ] ); } } /** * Global validation rules for the form. * * @param array $fields * Posted values of the form. * * @param $files * @param self $self * * @return array * if errors then list of errors to be posted back to the form, * true otherwise */ public static function formRule($fields, $files, $self) { $default = $fields['default_value'] ?? NULL; $errors = []; self::clearEmptyOptions($fields); //validate field label as well as name. $title = $fields['label']; $name = CRM_Utils_String::munge($title, '_', 64); // CRM-7564 $gId = $self->_gid; $query = 'select count(*) from civicrm_custom_field where ( name like %1 OR label like %2 ) and id != %3 and custom_group_id = %4'; $fldCnt = CRM_Core_DAO::singleValueQuery($query, [ 1 => [$name, 'String'], 2 => [$title, 'String'], 3 => [(int) $self->_id, 'Integer'], 4 => [$gId, 'Integer'], ]); if ($fldCnt) { $errors['label'] = ts('Custom field \'%1\' already exists in Database.', [1 => $title]); } //checks the given custom field name doesnot start with digit if (!empty($title)) { // gives the ascii value $asciiValue = ord($title[0]); if ($asciiValue >= 48 && $asciiValue <= 57) { $errors['label'] = ts("Name cannot not start with a digit"); } } // ensure that the label is not 'id' if (strtolower($title) == 'id') { $errors['label'] = ts("You cannot use 'id' as a field label."); } $dataType = $fields['data_type']; if ($default || $dataType == 'ContactReference') { switch ($dataType) { case 'Int': if (!CRM_Utils_Rule::integer($default)) { $errors['default_value'] = ts('Please enter a valid integer.'); } break; case 'Float': if (!CRM_Utils_Rule::numeric($default)) { $errors['default_value'] = ts('Please enter a valid number.'); } break; case 'Money': if (!CRM_Utils_Rule::money($default)) { $errors['default_value'] = ts('Please enter a valid number.'); } break; case 'Link': if (!CRM_Utils_Rule::url($default)) { $errors['default_value'] = ts('Please enter a valid link.'); } break; case 'Date': if (!CRM_Utils_Rule::date($default)) { $errors['default_value'] = ts('Please enter a valid date as default value using YYYY-MM-DD format. Example: 2004-12-31.'); } break; case 'Boolean': if ($default != '1' && $default != '0') { $errors['default_value'] = ts('Please enter 1 (for Yes) or 0 (for No) if you want to set a default value.'); } break; case 'Country': if (!empty($default)) { $query = "SELECT count(*) FROM civicrm_country WHERE id = %1"; $params = [1 => [$fields['default_value'], 'Int']]; if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) { $errors['default_value'] = ts('Invalid default value for country.'); } } break; case 'StateProvince': if (!empty($default)) { $query = " SELECT count(*) FROM civicrm_state_province WHERE id = %1"; $params = [1 => [$fields['default_value'], 'Int']]; if (CRM_Core_DAO::singleValueQuery($query, $params) <= 0) { $errors['default_value'] = ts('The invalid default value for State/Province data type'); } } break; case 'ContactReference': if ($fields['filter_selected'] == 'Advance' && !empty($fields['filter'])) { if (strpos($fields['filter'], 'entity=') !== FALSE) { $errors['filter'] = ts("Please do not include entity parameter (entity is always 'contact')"); } elseif (strpos($fields['filter'], 'action=get') === FALSE) { $errors['filter'] = ts("Only 'get' action is supported."); } } $self->setDefaults(['filter_selected', $fields['filter_selected']]); break; } } if ($dataType == 'Date') { if (!$fields['date_format']) { $errors['date_format'] = ts('Please select a date format.'); } } /** Check the option values entered * Appropriate values are required for the selected datatype * Incomplete row checking is also required. */ $_flagOption = $_rowError = 0; $_showHide = new CRM_Core_ShowHideBlocks(); $htmlType = $fields['html_type']; if (isset($fields['option_type']) && $fields['option_type'] == 1) { //capture duplicate Custom option values if (!empty($fields['option_value'])) { $countValue = count($fields['option_value']); $uniqueCount = count(array_unique($fields['option_value'])); if ($countValue > $uniqueCount) { $start = 1; while ($start < self::NUM_OPTION) { $nextIndex = $start + 1; while ($nextIndex <= self::NUM_OPTION) { if ($fields['option_value'][$start] == $fields['option_value'][$nextIndex] && strlen($fields['option_value'][$nextIndex]) ) { $errors['option_value[' . $start . ']'] = ts('Duplicate Option values'); $errors['option_value[' . $nextIndex . ']'] = ts('Duplicate Option values'); $_flagOption = 1; } $nextIndex++; } $start++; } } } //capture duplicate Custom Option label if (!empty($fields['option_label'])) { $countValue = count($fields['option_label']); $uniqueCount = count(array_unique($fields['option_label'])); if ($countValue > $uniqueCount) { $start = 1; while ($start < self::NUM_OPTION) { $nextIndex = $start + 1; while ($nextIndex <= self::NUM_OPTION) { if ($fields['option_label'][$start] == $fields['option_label'][$nextIndex] && !empty($fields['option_label'][$nextIndex]) ) { $errors['option_label[' . $start . ']'] = ts('Duplicate Option label'); $errors['option_label[' . $nextIndex . ']'] = ts('Duplicate Option label'); $_flagOption = 1; } $nextIndex++; } $start++; } } } for ($i = 1; $i <= self::NUM_OPTION; $i++) { if (!$fields['option_label'][$i]) { if ($fields['option_value'][$i]) { $errors['option_label[' . $i . ']'] = ts('Option label cannot be empty'); $_flagOption = 1; } else { $_emptyRow = 1; } } else { if (!strlen(trim($fields['option_value'][$i]))) { if (!$fields['option_value'][$i]) { $errors['option_value[' . $i . ']'] = ts('Option value cannot be empty'); $_flagOption = 1; } } } if ($fields['option_value'][$i] && $dataType != 'String') { if ($dataType == 'Int') { if (!CRM_Utils_Rule::integer($fields['option_value'][$i])) { $_flagOption = 1; $errors['option_value[' . $i . ']'] = ts('Please enter a valid integer.'); } } elseif ($dataType == 'Money') { if (!CRM_Utils_Rule::money($fields['option_value'][$i])) { $_flagOption = 1; $errors['option_value[' . $i . ']'] = ts('Please enter a valid money value.'); } } else { if (!CRM_Utils_Rule::numeric($fields['option_value'][$i])) { $_flagOption = 1; $errors['option_value[' . $i . ']'] = ts('Please enter a valid number.'); } } } $showBlocks = 'optionField_' . $i; if ($_flagOption) { $_showHide->addShow($showBlocks); $_rowError = 1; } if (!empty($_emptyRow)) { $_showHide->addHide($showBlocks); } else { $_showHide->addShow($showBlocks); } if ($i == self::NUM_OPTION) { $hideBlock = 'additionalOption'; $_showHide->addHide($hideBlock); } $_flagOption = $_emptyRow = 0; } } elseif (in_array($htmlType, self::$htmlTypesWithOptions) && !in_array($dataType, ['Boolean', 'Country', 'StateProvince', 'ContactReference']) ) { if (!$fields['option_group_id']) { $errors['option_group_id'] = ts('You must select a Multiple Choice Option set if you chose Reuse an existing set.'); } else { $query = " SELECT count(*) FROM civicrm_custom_field WHERE data_type != %1 AND option_group_id = %2"; $params = [ 1 => [$dataType, 'String'], 2 => [$fields['option_group_id'], 'Integer'], ]; $count = CRM_Core_DAO::singleValueQuery($query, $params); if ($count > 0) { $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.'); } } } $assignError = new CRM_Core_Page(); if ($_rowError) { $_showHide->addToTemplate(); $assignError->assign('optionRowError', $_rowError); } else { if (isset($htmlType)) { switch ($htmlType) { case 'Radio': case 'CheckBox': case 'Select': $_fieldError = 1; $assignError->assign('fieldError', $_fieldError); break; default: $_fieldError = 0; $assignError->assign('fieldError', $_fieldError); } } for ($idx = 1; $idx <= self::NUM_OPTION; $idx++) { $showBlocks = 'optionField_' . $idx; if (!empty($fields['option_label'][$idx])) { $_showHide->addShow($showBlocks); } else { $_showHide->addHide($showBlocks); } } $_showHide->addToTemplate(); } // we can not set require and view at the same time. if (!empty($fields['is_required']) && !empty($fields['is_view'])) { $errors['is_view'] = ts('Can not set this field Required and View Only at the same time.'); } // If switching to a new option list, validate existing data if (empty($errors) && $self->_id && in_array($htmlType, self::$htmlTypesWithOptions)) { $oldHtmlType = $self->_values['html_type']; $oldOptionGroup = $self->_values['option_group_id']; if ($oldHtmlType === 'Text' || $oldOptionGroup != $fields['option_group_id'] || $fields['option_type'] == 1) { if ($fields['option_type'] == 2) { $optionQuery = "SELECT value FROM civicrm_option_value WHERE option_group_id = " . (int) $fields['option_group_id']; } else { $options = array_map(['CRM_Core_DAO', 'escapeString'], array_filter($fields['option_value'], 'strlen')); $optionQuery = '"' . implode('","', $options) . '"'; } $table = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $self->_gid, 'table_name'); $column = $self->_values['column_name']; $invalid = CRM_Core_DAO::singleValueQuery("SELECT COUNT(*) FROM `$table` WHERE `$column` NOT IN ($optionQuery)"); if ($invalid) { $errors['html_type'] = ts('Cannot impose option list because there is existing data which does not match the options.'); } } } return empty($errors) ? TRUE : $errors; } /** * Process the form. * * @return void */ public function postProcess() { // store the submitted values in an array $params = $this->controller->exportValues($this->_name); self::clearEmptyOptions($params); //fix for 'is_search_range' field. if (in_array($params['data_type'], ['Int', 'Float', 'Money', 'Date'])) { if (empty($params['is_searchable']) || in_array($params['html_type'], ['Radio', 'Select'])) { $params['is_search_range'] = 0; } } else { $params['is_search_range'] = 0; } $params['serialize'] = $this->determineSerializeType($params); $filter = 'null'; if ($params['data_type'] == 'ContactReference' && !empty($params['filter_selected'])) { if ($params['filter_selected'] == 'Advance' && trim(CRM_Utils_Array::value('filter', $params))) { $filter = trim($params['filter']); } elseif ($params['filter_selected'] == 'Group' && !empty($params['group_id'])) { $filter = 'action=lookup&group=' . implode(',', $params['group_id']); } } $params['filter'] = $filter; // fix for CRM-316 $oldWeight = NULL; if ($this->_action & (CRM_Core_Action::UPDATE | CRM_Core_Action::ADD)) { $fieldValues = ['custom_group_id' => $this->_gid]; if ($this->_id) { $oldWeight = $this->_values['weight']; } $params['weight'] = CRM_Utils_Weight::updateOtherWeights('CRM_Core_DAO_CustomField', $oldWeight, $params['weight'], $fieldValues); } // The text_length attribute for Memo fields is in a different input as there // are different label, help text and default value than for other type fields if ($params['data_type'] == "Memo") { $params['text_length'] = $params['note_length']; } // need the FKEY - custom group id $params['custom_group_id'] = $this->_gid; if ($this->_action & CRM_Core_Action::UPDATE) { $params['id'] = $this->_id; } $customField = CRM_Core_BAO_CustomField::create($params); $this->_id = $customField->id; // reset the cache Civi::cache('fields')->flush(); $msg = '

' . ts("Custom field '%1' has been saved.", [1 => $customField->label]) . '

'; $buttonName = $this->controller->getButtonName(); $session = CRM_Core_Session::singleton(); if ($buttonName == $this->getButtonName('next', 'new')) { $msg .= '

' . ts("Ready to add another.") . '

'; $session->replaceUserContext(CRM_Utils_System::url('civicrm/admin/custom/group/field/add', 'reset=1&gid=' . $this->_gid )); } else { $session->replaceUserContext(CRM_Utils_System::url('civicrm/admin/custom/group/field', 'reset=1&gid=' . $this->_gid )); } $session->setStatus($msg, ts('Saved'), 'success'); // Add data when in ajax contect $this->ajaxResponse['customField'] = $customField->toArray(); } /** * Removes value from fields with no label. * * This allows default values to be set in the form, but ignored in post-processing. * * @param array $fields */ public static function clearEmptyOptions(&$fields) { foreach ($fields['option_label'] as $i => $label) { if (!strlen(trim($label))) { $fields['option_value'][$i] = ''; } } } /** * Get number of existing records for this field that contain more than one serialized value. * * @return int * @throws CRM_Core_Exception */ public function getMultiValueCount() { $table = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $this->_gid, 'table_name'); $column = $this->_values['column_name']; $sp = CRM_Core_DAO::VALUE_SEPARATOR; $sql = "SELECT COUNT(*) FROM `$table` WHERE `$column` LIKE '{$sp}%{$sp}%{$sp}'"; return (int) CRM_Core_DAO::singleValueQuery($sql); } /** * @return string */ public function getDefaultContext() { return 'create'; } /** * @return string */ public function getDefaultEntity() { return 'CustomField'; } /** * Determine the serialize type based on form values. * @param array $params The submitted form values. * @return int * The serialize type - CRM_Core_DAO::SERIALIZE_XXX or 0 */ public function determineSerializeType($params) { if ($params['html_type'] === 'Select' || $params['html_type'] === 'Autocomplete-Select') { return !empty($params['serialize']) ? CRM_Core_DAO::SERIALIZE_SEPARATOR_BOOKEND : 0; } else { return $params['html_type'] == 'CheckBox' ? CRM_Core_DAO::SERIALIZE_SEPARATOR_BOOKEND : 0; } } }