// make sure all values are present in the object for further processing
$customField->find(TRUE);
+ $triggerRebuild = CRM_Utils_Array::value('triggerRebuild', $params, TRUE);
//create/drop the index when we toggle the is_searchable flag
if (!empty($params['id'])) {
- self::createField($customField, 'modify', $indexExist);
+ self::createField($customField, 'modify', $indexExist, $triggerRebuild);
}
else {
if (!isset($origParams['column_name'])) {
// make sure all values are present in the object
$customField->find(TRUE);
- self::createField($customField, 'add');
+ $indexExist = FALSE;
+ self::createField($customField, 'add', $indexExist, $triggerRebuild);
}
// complete transaction
}
}
- if ($customDataSubType && !is_array($customDataSubType)) {
- $customDataSubType = explode(CRM_Core_DAO::VALUE_SEPARATOR,
- trim($customDataSubType, CRM_Core_DAO::VALUE_SEPARATOR)
- );
- }
+ $customDataSubType = CRM_Utils_Array::explodePadded($customDataSubType);
if (is_array($customDataType)) {
$cacheKey = implode('_', $customDataType);
'import' => 1,
'custom_field_id' => $id,
'options_per_line' => CRM_Utils_Array::value('options_per_line', $values),
+ 'text_length' => CRM_Utils_Array::value('text_length', $values, 255),
'data_type' => CRM_Utils_Array::value('data_type', $values),
'html_type' => CRM_Utils_Array::value('html_type', $values),
'is_search_range' => CRM_Utils_Array::value('is_search_range', $values),
);
}
}
- return $all ? array(
- NULL, NULL) : NULL;
+ return $all ? array(NULL, NULL) : NULL;
}
/**
* @param CRM_Core_Form $qf form object (reference)
* @param string $elementName name of the custom field
* @param $fieldId
- * @param boolean $inactiveNeeded
+ * @param boolean $inactiveNeeded -deprecated
* @param bool $useRequired
* @param boolean $search true if used for search else false
* @param string $label label for custom field
$label = NULL
) {
$field = self::getFieldObject($fieldId);
+ $widget = $field->html_type;
// Custom field HTML should indicate group+field name
$groupName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $field->custom_group_id);
$field->attributes .= $dataCrmCustomAttr;
// Fixed for Issue CRM-2183
- if ($field->html_type == 'TextArea' && $search) {
- $field->html_type = 'Text';
+ if ($widget == 'TextArea' && $search) {
+ $widget = 'Text';
}
$placeholder = $search ? ts('- any -') : ($useRequired ? ts('- select -') : ts('- none -'));
// FIXME: Why are select state/country separate widget types?
- if (in_array($field->html_type, array('Select', 'Multi-Select', 'Select State/Province', 'Multi-Select State/Province', 'Select Country', 'Multi-Select Country'))) {
+ $isSelect = (in_array($widget, array('Select', 'Multi-Select', 'Select State/Province', 'Multi-Select State/Province', 'Select Country', 'Multi-Select Country', 'AdvMulti-Select', 'CheckBox', 'Radio')));
+
+ if ($isSelect) {
+ $options = CRM_Utils_Array::value('values', civicrm_api3('contact', 'getoptions', array('field' => "custom_$fieldId", 'context' => $search ? 'search' : 'create'), array()));
+
+ // Consolidate widget types to simplify the below switch statement
+ if ($search || ($widget !== 'AdvMulti-Select' && strpos($widget, 'Select') !== FALSE)) {
+ $widget = 'Select';
+ }
$selectAttributes = array(
'data-crm-custom' => $dataCrmCustomVal,
'class' => 'crm-select2',
);
- if (strpos($field->html_type, 'Multi') === 0) {
+ // Search field is always multi-select
+ if ($search || strpos($field->html_type, 'Multi') !== FALSE) {
+ $selectAttributes['class'] .= ' huge';
$selectAttributes['multiple'] = 'multiple';
+ $selectAttributes['placeholder'] = $placeholder;
+ }
+ // Add data for popup link. Normally this is handled by CRM_Core_Form->addSelect
+ if ($field->option_group_id && !$search && $widget == 'Select' && CRM_Core_Permission::check('administer CiviCRM')) {
+ $selectAttributes += array(
+ 'data-api-entity' => 'contact', // FIXME: This works because the getoptions api isn't picky about custom fields, but it's WRONG
+ 'data-api-field' => 'custom_' . $field->id,
+ 'data-option-edit-path' => 'civicrm/admin/options/' . CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', $field->option_group_id),
+ );
}
- }
- // Add data so popup link. Normally this is handled by CRM_Core_Form->addSelect
- if ($field->option_group_id && !$search && in_array($field->html_type, array('Select', 'Multi-Select')) && CRM_Core_Permission::check('administer CiviCRM')) {
- $selectAttributes += array(
- 'data-api-entity' => 'contact', // FIXME: This works because the getoptions api isn't picky about custom fields, but it's WRONG
- 'data-api-field' => 'custom_' . $field->id,
- 'data-option-edit-path' => 'civicrm/admin/options/' . CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', $field->option_group_id),
- );
}
if (!isset($label)) {
* at some point in time we might want to split the below into small functions
**/
- switch ($field->html_type) {
+ switch ($widget) {
case 'Text':
+ case 'Link':
if ($field->is_search_range && $search) {
$qf->add('text', $elementName . '_from', $label . ' ' . ts('From'), $field->attributes);
$qf->add('text', $elementName . '_to', ts('To'), $field->attributes);
}
else {
- $element = &$qf->add(strtolower($field->html_type), $elementName, $label,
+ $element = &$qf->add('text', $elementName, $label,
$field->attributes,
$useRequired && !$search
);
if ($field->text_length) {
$attributes .= ' maxlength=' . $field->text_length;
}
- $element = &$qf->add(strtolower($field->html_type),
+ $element = &$qf->add('textarea',
$elementName,
$label,
$attributes,
case 'Radio':
$choice = array();
- if ($field->data_type != 'Boolean') {
- $customOption = CRM_Core_BAO_CustomOption::valuesByID($field->id,
- $field->option_group_id
- );
- foreach ($customOption as $v => $l) {
- $choice[] = $qf->createElement('radio', NULL, '', $l, (string)$v, $field->attributes);
- }
- $group = $qf->addGroup($choice, $elementName, $label);
- }
- else {
- $choice[] = $qf->createElement('radio', NULL, '', ts('Yes'), '1', $field->attributes);
- $choice[] = $qf->createElement('radio', NULL, '', ts('No'), '0', $field->attributes);
- $group = $qf->addGroup($choice, $elementName, $label);
+ foreach ($options as $v => $l) {
+ $choice[] = $qf->createElement('radio', NULL, '', $l, (string)$v, $field->attributes);
}
+ $group = $qf->addGroup($choice, $elementName, $label);
if ($useRequired && !$search) {
$qf->addRule($elementName, ts('%1 is a required field.', array(1 => $label)), 'required');
}
}
break;
+ // For all select elements
case 'Select':
- $selectOption = CRM_Core_BAO_CustomOption::valuesByID($field->id,
- $field->option_group_id
- );
-
- $qf->add('select', $elementName, $label,
- array('' => $placeholder) + $selectOption,
- $useRequired && !$search,
- $selectAttributes
- );
- break;
+ if (empty($selectAttributes['multiple'])) {
+ $options = array('' => $placeholder) + $options;
+ }
+ $qf->add('select', $elementName, $label, $options, $useRequired && !$search, $selectAttributes);
- //added for select multiple
+ // Add and/or option for fields that store multiple values
+ if ($search && self::isSerialized($field)) {
- case 'AdvMulti-Select':
- $selectOption = CRM_Core_BAO_CustomOption::valuesByID($field->id,
- $field->option_group_id
- );
- if ($search &&
- count($selectOption) > 1
- ) {
- $selectOption['CiviCRM_OP_OR'] = ts('Select to match ANY; unselect to match ALL');
+ $operators = array(
+ $qf->createElement('radio', NULL, '', ts('Any'), 'or', array('title' => ts('Results may contain any of the selected options'))),
+ $qf->createElement('radio', NULL, '', ts('All'), 'and', array('title' => ts('Results must have all of the selected options'))),
+ );
+ $qf->addGroup($operators, $elementName . '_operator');
+ $qf->setDefaults(array($elementName . '_operator' => 'or'));
}
+ break;
+ case 'AdvMulti-Select':
$include =& $qf->addElement(
'advmultiselect',
$elementName,
- $label, $selectOption,
+ $label, $options,
array(
'size' => 5,
'style' => '',
}
break;
- case 'Multi-Select':
- $selectOption = CRM_Core_BAO_CustomOption::valuesByID($field->id,
- $field->option_group_id
- );
- if ($search &&
- count($selectOption) > 1
- ) {
- $selectOption['CiviCRM_OP_OR'] = ts('Select to match ANY; unselect to match ALL');
- }
- $qf->addElement('select', $elementName, $label, $selectOption, $selectAttributes);
-
- if ($useRequired && !$search) {
- $qf->addRule($elementName, ts('%1 is a required field.', array(1 => $label)), 'required');
- }
- break;
-
case 'CheckBox':
- $customOption = CRM_Core_BAO_CustomOption::valuesByID($field->id,
- $field->option_group_id
- );
$check = array();
- foreach ($customOption as $v => $l) {
+ foreach ($options as $v => $l) {
$check[] = &$qf->addElement('advcheckbox', $v, NULL, $l, array('data-crm-custom' => $dataCrmCustomVal));
}
- if ($search &&
- count($check) > 1
- ) {
- $check[] = &$qf->addElement('advcheckbox', 'CiviCRM_OP_OR', NULL, ts('Check to match ANY; uncheck to match ALL'), array('data-crm-custom' => $dataCrmCustomVal));
- }
$qf->addGroup($check, $elementName, $label);
if ($useRequired && !$search) {
$qf->addRule($elementName, ts('%1 is a required field.', array(1 => $label)), 'required');
$qf->addUploadElement($elementName);
break;
- case 'Select State/Province':
- //Add State
- $stateOption = array('' => $placeholder) + CRM_Core_PseudoConstant::stateProvince();
- $qf->add('select', $elementName, $label, $stateOption,
- $useRequired && !$search,
- $selectAttributes
- );
- $qf->_stateCountryMap['state_province'][] = $elementName;
- break;
-
- case 'Multi-Select State/Province':
- //Add Multi-select State/Province
- $stateOption = CRM_Core_PseudoConstant::stateProvince();
-
- $qf->addElement('select', $elementName, $label, $stateOption, $selectAttributes);
- if ($useRequired && !$search) {
- $qf->addRule($elementName, ts('%1 is a required field.', array(1 => $label)), 'required');
- }
- break;
-
- case 'Select Country':
- //Add Country
- $countryOption = array('' => $placeholder) + CRM_Core_PseudoConstant::country();
- $qf->add('select', $elementName, $label, $countryOption,
- $useRequired && !$search,
- $selectAttributes
- );
- $qf->_stateCountryMap['country'][] = $elementName;
- break;
-
- case 'Multi-Select Country':
- //Add Country
- $countryOption = CRM_Core_PseudoConstant::country();
- $qf->addElement('select', $elementName, $label, $countryOption, $selectAttributes);
- if ($useRequired && !$search) {
- $qf->addRule($elementName, ts('%1 is a required field.', array(1 => $label)), 'required');
- }
- break;
-
case 'RichTextEditor':
$attributes = array('rows' => $field->note_rows, 'cols' => $field->note_columns, 'data-crm-custom' => $dataCrmCustomVal);
if ($field->text_length) {
$attributes += array(
'entity' => 'option_value',
'placeholder' => $placeholder,
+ 'multiple' => $search,
'api' => array(
'params' => array('option_group_id' => $field->option_group_id),
),
$qf->addRule($elementName . '_from', ts('%1 From must be an integer (whole number).', array(1 => $label)), 'integer');
$qf->addRule($elementName . '_to', ts('%1 To must be an integer (whole number).', array(1 => $label)), 'integer');
}
- else {
+ elseif ($widget == 'Text') {
$qf->addRule($elementName, ts('%1 must be an integer (whole number).', array(1 => $label)), 'integer');
}
break;
$qf->addRule($elementName . '_from', ts('%1 From must be a number (with or without decimal point).', array(1 => $label)), 'numeric');
$qf->addRule($elementName . '_to', ts('%1 To must be a number (with or without decimal point).', array(1 => $label)), 'numeric');
}
- else {
+ elseif ($widget == 'Text') {
$qf->addRule($elementName, ts('%1 must be a number (with or without decimal point).', array(1 => $label)), 'numeric');
}
break;
$qf->addRule($elementName . '_from', ts('%1 From must in proper money format. (decimal point/comma/space is allowed).', array(1 => $label)), 'money');
$qf->addRule($elementName . '_to', ts('%1 To must in proper money format. (decimal point/comma/space is allowed).', array(1 => $label)), 'money');
}
- else {
+ elseif ($widget == 'Text') {
$qf->addRule($elementName, ts('%1 must be in proper money format. (decimal point/comma/space is allowed).', array(1 => $label)), 'money');
}
break;
case 'Link':
- $qf->add(
- 'text',
- $elementName,
- $label,
- array(
- 'onfocus' => "if (!this.value) { this.value='http://';} else return false",
- 'onblur' => "if ( this.value == 'http://') { this.value='';} else return false",
- 'data-crm-custom' => $dataCrmCustomVal,
- ),
- $useRequired && !$search
- );
+ $element->setAttribute('onfocus', "if (!this.value) {this.value='http://';}");
+ $element->setAttribute('onblur', "if (this.value == 'http://') {this.value='';}");
+ $element->setAttribute('class', "url");
$qf->addRule($elementName, ts('Enter a valid Website.'), 'wikiURL');
break;
}
$v = array();
$p = array();
foreach ($checkedData as $key => $val) {
- if ($key === 'CiviCRM_OP_OR') {
- continue;
- }
-
if ($html_type == 'CheckBox') {
if ($val) {
$p[] = $key;
*
* @return array
*/
- static function getFileURL($contactID, $cfID, $fileID = NULL, $absolute = FALSE) {
+ static function getFileURL($contactID, $cfID, $fileID = NULL, $absolute = FALSE, $multiRecordWhereClause = NULL) {
if ($contactID) {
if (!$fileID) {
$params = array('id' => $cfID);
);
//query to fetch id from civicrm_file
- $query = "SELECT {$columnName} FROM {$tableName} where entity_id = {$contactID}";
+ if ($multiRecordWhereClause) {
+ $query = "SELECT {$columnName} FROM {$tableName} where entity_id = {$contactID} AND {$multiRecordWhereClause}";
+ }
+ else {
+ $query = "SELECT {$columnName} FROM {$tableName} where entity_id = {$contactID}";
+ }
$fileID = CRM_Core_DAO::singleValueQuery($query);
}
* @param int $entityId entity id (contribution, membership...)
* @param boolean $inline consider inline custom groups only
* @param boolean $checkPermission if false, do not include permissioning clause
+ * @param boolean $includeViewOnly if true, fields marked 'View Only' are included. Required for APIv3.
*
* @return array $customFormatted formatted custom field array
* @static
$customFieldExtend, $customValueId = NULL,
$entityId = NULL,
$inline = FALSE,
- $checkPermission = TRUE
+ $checkPermission = TRUE,
+ $includeViewOnly = false
) {
//get the custom fields for the entity
//subtype and basic type
}
// return if field is a 'code' field
- if (!empty($customFields[$customFieldId]['is_view'])) {
+ if (!$includeViewOnly && !empty($customFields[$customFieldId]['is_view'])) {
return;
}
return $isMultipleWithGid;
}
+
+ /**
+ * Does this field store a serialized string?
+ * @param CRM_Core_DAO_CustomField|array $field
+ * @return bool
+ */
+ static function isSerialized($field) {
+ // Fields retrieved via api are an array, or from the dao are an object. We'll accept either.
+ $field = (array) $field;
+ // FIXME: Currently the only way to know if data is serialized is by looking at the html_type. It would be cleaner to decouple this.
+ return ($field['html_type'] == 'CheckBox' || strpos($field['html_type'], 'Multi') !== FALSE);
+ }
}