Skip to content

Commit

Permalink
Centralize logic for resolving settings pseudoconstants
Browse files Browse the repository at this point in the history
  • Loading branch information
colemanw committed May 17, 2019
1 parent 405192f commit 3c689f7
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 38 deletions.
8 changes: 2 additions & 6 deletions CRM/Admin/Form/SettingTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ public function getDefaultEntity() {
*/
protected function getSettingsMetaData() {
if (empty($this->settingsMetadata)) {
$allSettingMetaData = civicrm_api3('setting', 'getfields', []);
$this->settingsMetadata = array_intersect_key($allSettingMetaData['values'], $this->_settings);
$this->settingsMetadata = \Civi\Core\SettingsMetadata::getMetadata(['name' => array_keys($this->_settings)], NULL, TRUE);
// This array_merge re-orders to the key order of $this->_settings.
$this->settingsMetadata = array_merge($this->_settings, $this->settingsMetadata);
}
Expand Down Expand Up @@ -174,10 +173,7 @@ protected function addFieldsDefinedInSettingsMetadata() {
$quickFormType = $this->getQuickFormType($props);
if (isset($quickFormType)) {
$options = CRM_Utils_Array::value('options', $props);
if (isset($props['pseudoconstant'])) {
$options = civicrm_api3('Setting', 'getoptions', [
'field' => $setting,
])['values'];
if ($options) {
if ($props['html_type'] === 'Select' && isset($props['is_required']) && $props['is_required'] === FALSE && !isset($options[''])) {
// If the spec specifies the field is not required add a null option.
// Why not if empty($props['is_required']) - basically this has been added to the spec & might not be set to TRUE
Expand Down
43 changes: 34 additions & 9 deletions Civi/Core/SettingsMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class SettingsMetadata {
*
* @param array $filters
* @param int $domainID
* @param bool $loadOptions
*
* @return array
* the following information as appropriate for each setting
Expand All @@ -64,8 +65,10 @@ class SettingsMetadata {
* - is_contact
* - description
* - help_text
* - options
* - pseudoconstant
*/
public static function getMetadata($filters = [], $domainID = NULL) {
public static function getMetadata($filters = [], $domainID = NULL, $loadOptions = FALSE) {
if ($domainID === NULL) {
$domainID = \CRM_Core_Config::domainID();
}
Expand Down Expand Up @@ -95,6 +98,9 @@ public static function getMetadata($filters = [], $domainID = NULL) {
}

self::_filterSettingsSpecification($filters, $settingsMetadata);
if ($loadOptions) {
self::_loadOptions($settingsMetadata);
}

return $settingsMetadata;
}
Expand Down Expand Up @@ -145,20 +151,39 @@ protected static function loadSettingsMetadata($metaDataFolder) {
* Metadata to filter.
*/
protected static function _filterSettingsSpecification($filters, &$settingSpec) {
if (empty($filters)) {
return;
}
elseif (array_keys($filters) == ['name']) {
$settingSpec = [$filters['name'] => \CRM_Utils_Array::value($filters['name'], $settingSpec, '')];
return;
if (!empty($filters['name'])) {
$settingSpec = array_intersect_key($settingSpec, array_flip((array) $filters['name']));
unset($filters['name']);
}
else {
if (!empty($filters)) {
foreach ($settingSpec as $field => $fieldValues) {
if (array_intersect_assoc($fieldValues, $filters) != $filters) {
unset($settingSpec[$field]);
}
}
return;
}
}

/**
* Retrieve options from settings metadata
*
* @param array $settingSpec
*/
protected function _loadOptions(&$settingSpec) {
foreach ($settingSpec as &$spec) {
if (empty($spec['pseudoconstant'])) {
continue;
}
// It would be nice if we could leverage CRM_Core_PseudoConstant::get() somehow,
// but it's tightly coupled to DAO/field. However, if you really need to support
// more pseudoconstant types, then probably best to refactor it. For now, KISS.
if (!empty($spec['pseudoconstant']['callback'])) {
$spec['options'] = Resolver::singleton()->call($spec['pseudoconstant']['callback'], []);
}
elseif (!empty($spec['pseudoconstant']['optionGroupName'])) {
$keyColumn = \CRM_Utils_Array::value('keyColumn', $spec['pseudoconstant'], 'value');
$spec['options'] = \CRM_Core_OptionGroup::values($spec['pseudoconstant']['optionGroupName'], FALSE, FALSE, TRUE, NULL, 'label', TRUE, FALSE, $keyColumn);
}
}
}

Expand Down
27 changes: 4 additions & 23 deletions api/v3/Setting.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,33 +148,14 @@ function _civicrm_api3_setting_getdefaults_spec(&$params) {
* @throws \API_Exception
*/
function civicrm_api3_setting_getoptions($params) {
$specs = CRM_Core_BAO_Setting::getSettingSpecification();
$domainId = CRM_Utils_Array::value('domain_id', $params);
$specs = \Civi\Core\SettingsMetadata::getMetadata(['name' => $params['field']], $domainId, TRUE);

if (empty($specs[$params['field']]) || empty($specs[$params['field']]['pseudoconstant'])) {
if (empty($specs[$params['field']]) || !is_array(CRM_Utils_Array::value('options', $specs[$params['field']]))) {
throw new API_Exception("The field '" . $params['field'] . "' has no associated option list.");
}

$pseudoconstant = $specs[$params['field']]['pseudoconstant'];

// It would be nice if we could leverage CRM_Core_PseudoConstant::get() somehow,
// but it's tightly coupled to DAO/field. However, if you really need to support
// more pseudoconstant types, then probably best to refactor it. For now, KISS.
if (!empty($pseudoconstant['callback'])) {
$values = Civi\Core\Resolver::singleton()->call($pseudoconstant['callback'], []);
return civicrm_api3_create_success($values, $params, 'Setting', 'getoptions');
}
elseif (!empty($pseudoconstant['optionGroupName'])) {
$keyColumn = 'value';
if (!empty($pseudoconstant['keyColumn'])) {
$keyColumn = $pseudoconstant['keyColumn'];
}
return civicrm_api3_create_success(
CRM_Core_OptionGroup::values($pseudoconstant['optionGroupName'], FALSE, FALSE, TRUE, NULL, 'label', TRUE, FALSE, $keyColumn),
$params, 'Setting', 'getoptions'
);
}

throw new API_Exception("The field '" . $params['field'] . "' uses an unsupported option list.");
return civicrm_api3_create_success($specs[$params['field']]['options'], $params, 'Setting', 'getoptions');
}

/**
Expand Down

0 comments on commit 3c689f7

Please sign in to comment.