From 3c689f7ee7d49d425fe6738cd23a77e19267bbdf Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Fri, 17 May 2019 13:46:03 -0400 Subject: [PATCH] Centralize logic for resolving settings pseudoconstants --- CRM/Admin/Form/SettingTrait.php | 8 ++---- Civi/Core/SettingsMetadata.php | 43 ++++++++++++++++++++++++++------- api/v3/Setting.php | 27 +++------------------ 3 files changed, 40 insertions(+), 38 deletions(-) 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..3f5b73f7fd2a 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,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); + } } } 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'); } /**