diff --git a/CRM/Admin/Form/SettingTrait.php b/CRM/Admin/Form/SettingTrait.php index f22470803fe6..308d409e7ea5 100644 --- a/CRM/Admin/Form/SettingTrait.php +++ b/CRM/Admin/Form/SettingTrait.php @@ -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); } @@ -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 diff --git a/Civi/Core/SettingsMetadata.php b/Civi/Core/SettingsMetadata.php index 00d04d34215c..0d7509bc93b8 100644 --- a/Civi/Core/SettingsMetadata.php +++ b/Civi/Core/SettingsMetadata.php @@ -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 @@ -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(); } @@ -95,6 +98,9 @@ public static function getMetadata($filters = [], $domainID = NULL) { } self::_filterSettingsSpecification($filters, $settingsMetadata); + if ($loadOptions) { + self::loadOptions($settingsMetadata); + } return $settingsMetadata; } @@ -145,20 +151,41 @@ 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'])); + // FIXME: This is a workaround for settingsBag::setDb() called by unit tests with settings names that don't exist + $settingSpec += array_fill_keys((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 static 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); + } } } diff --git a/api/v3/Setting.php b/api/v3/Setting.php index e7d2338c254f..a7ce04b76fcd 100644 --- a/api/v3/Setting.php +++ b/api/v3/Setting.php @@ -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'); } /**