| 1 | <?php |
| 2 | /* |
| 3 | +--------------------------------------------------------------------+ |
| 4 | | CiviCRM version 5 | |
| 5 | +--------------------------------------------------------------------+ |
| 6 | | Copyright CiviCRM LLC (c) 2004-2018 | |
| 7 | +--------------------------------------------------------------------+ |
| 8 | | This file is a part of CiviCRM. | |
| 9 | | | |
| 10 | | CiviCRM is free software; you can copy, modify, and distribute it | |
| 11 | | under the terms of the GNU Affero General Public License | |
| 12 | | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | |
| 13 | | | |
| 14 | | CiviCRM is distributed in the hope that it will be useful, but | |
| 15 | | WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
| 17 | | See the GNU Affero General Public License for more details. | |
| 18 | | | |
| 19 | | You should have received a copy of the GNU Affero General Public | |
| 20 | | License and the CiviCRM Licensing Exception along | |
| 21 | | with this program; if not, contact CiviCRM LLC | |
| 22 | | at info[AT]civicrm[DOT]org. If you have questions about the | |
| 23 | | GNU Affero General Public License or the licensing of CiviCRM, | |
| 24 | | see the CiviCRM license FAQ at http://civicrm.org/licensing | |
| 25 | +--------------------------------------------------------------------+ |
| 26 | */ |
| 27 | |
| 28 | /** |
| 29 | * |
| 30 | * @package CRM |
| 31 | * @copyright CiviCRM LLC (c) 2004-2018 |
| 32 | */ |
| 33 | |
| 34 | /** |
| 35 | * This trait allows us to consolidate Preferences & Settings forms. |
| 36 | * |
| 37 | * It is intended mostly as part of a refactoring process to get rid of having 2. |
| 38 | */ |
| 39 | trait CRM_Admin_Form_SettingTrait { |
| 40 | |
| 41 | /** |
| 42 | * @var array |
| 43 | */ |
| 44 | protected $settingsMetadata; |
| 45 | |
| 46 | /** |
| 47 | * Get default entity. |
| 48 | * |
| 49 | * @return string |
| 50 | */ |
| 51 | public function getDefaultEntity() { |
| 52 | return 'Setting'; |
| 53 | } |
| 54 | |
| 55 | /** |
| 56 | * Get the metadata relating to the settings on the form, ordered by the keys in $this->_settings. |
| 57 | * |
| 58 | * @return array |
| 59 | */ |
| 60 | protected function getSettingsMetaData() { |
| 61 | if (empty($this->settingsMetadata)) { |
| 62 | $allSettingMetaData = civicrm_api3('setting', 'getfields', []); |
| 63 | $this->settingsMetadata = array_intersect_key($allSettingMetaData['values'], $this->_settings); |
| 64 | // This array_merge re-orders to the key order of $this->_settings. |
| 65 | $this->settingsMetadata = array_merge($this->_settings, $this->settingsMetadata); |
| 66 | } |
| 67 | return $this->settingsMetadata; |
| 68 | } |
| 69 | |
| 70 | /** |
| 71 | * Get the settings which can be stored based on metadata. |
| 72 | * |
| 73 | * @param array $params |
| 74 | * @return array |
| 75 | */ |
| 76 | protected function getSettingsToSetByMetadata($params) { |
| 77 | return array_intersect_key($params, $this->_settings); |
| 78 | } |
| 79 | |
| 80 | /** |
| 81 | * @param $params |
| 82 | */ |
| 83 | protected function filterParamsSetByMetadata(&$params) { |
| 84 | foreach ($this->getSettingsToSetByMetadata($params) as $setting => $settingGroup) { |
| 85 | //@todo array_diff this |
| 86 | unset($params[$setting]); |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | /** |
| 91 | * Get the metadata for a particular field. |
| 92 | * |
| 93 | * @param $setting |
| 94 | * @return mixed |
| 95 | */ |
| 96 | protected function getSettingMetadata($setting) { |
| 97 | return $this->getSettingsMetaData()[$setting]; |
| 98 | } |
| 99 | |
| 100 | /** |
| 101 | * Get the metadata for a particular field for a particular item. |
| 102 | * |
| 103 | * e.g get 'serialize' key, if exists, for a field. |
| 104 | * |
| 105 | * @param $setting |
| 106 | * @return mixed |
| 107 | */ |
| 108 | protected function getSettingMetadataItem($setting, $item) { |
| 109 | return CRM_Utils_Array::value($item, $this->getSettingsMetaData()[$setting]); |
| 110 | } |
| 111 | |
| 112 | /** |
| 113 | * Add fields in the metadata to the template. |
| 114 | */ |
| 115 | protected function addFieldsDefinedInSettingsMetadata() { |
| 116 | $settingMetaData = $this->getSettingsMetaData(); |
| 117 | $descriptions = []; |
| 118 | foreach ($settingMetaData as $setting => $props) { |
| 119 | $quickFormType = $this->getQuickFormType($props); |
| 120 | if (isset($quickFormType)) { |
| 121 | $options = NULL; |
| 122 | if (isset($props['pseudoconstant'])) { |
| 123 | $options = civicrm_api3('Setting', 'getoptions', [ |
| 124 | 'field' => $setting, |
| 125 | ])['values']; |
| 126 | } |
| 127 | if ($props['type'] === 'Boolean') { |
| 128 | $options = [$props['title'] => $props['name']]; |
| 129 | } |
| 130 | |
| 131 | //Load input as readonly whose values are overridden in civicrm.settings.php. |
| 132 | if (Civi::settings()->getMandatory($setting)) { |
| 133 | $props['html_attributes']['readonly'] = TRUE; |
| 134 | $this->includesReadOnlyFields = TRUE; |
| 135 | } |
| 136 | |
| 137 | $add = 'add' . $quickFormType; |
| 138 | if ($add == 'addElement') { |
| 139 | $this->$add( |
| 140 | $props['html_type'], |
| 141 | $setting, |
| 142 | ts($props['title']), |
| 143 | ($options !== NULL) ? $options : CRM_Utils_Array::value('html_attributes', $props, []), |
| 144 | ($options !== NULL) ? CRM_Utils_Array::value('html_attributes', $props, []) : NULL |
| 145 | ); |
| 146 | } |
| 147 | elseif ($add == 'addSelect') { |
| 148 | $this->addElement('select', $setting, ts($props['title']), $options, CRM_Utils_Array::value('html_attributes', $props)); |
| 149 | } |
| 150 | elseif ($add == 'addCheckBox') { |
| 151 | $this->addCheckBox($setting, ts($props['title']), $options, NULL, CRM_Utils_Array::value('html_attributes', $props), NULL, NULL, [' ']); |
| 152 | } |
| 153 | elseif ($add == 'addCheckBoxes') { |
| 154 | $options = array_flip($options); |
| 155 | $newOptions = []; |
| 156 | foreach ($options as $key => $val) { |
| 157 | $newOptions[$key] = $val; |
| 158 | } |
| 159 | $this->addCheckBox($setting, |
| 160 | $props['title'], |
| 161 | $newOptions, |
| 162 | NULL, NULL, NULL, NULL, |
| 163 | [' ', ' ', '<br/>'] |
| 164 | ); |
| 165 | } |
| 166 | elseif ($add == 'addChainSelect') { |
| 167 | $this->addChainSelect($setting, [ |
| 168 | 'label' => ts($props['title']), |
| 169 | ]); |
| 170 | } |
| 171 | elseif ($add == 'addMonthDay') { |
| 172 | $this->add('date', $setting, ts($props['title']), CRM_Core_SelectValues::date(NULL, 'M d')); |
| 173 | } |
| 174 | else { |
| 175 | $this->$add($setting, ts($props['title']), $options); |
| 176 | } |
| 177 | // Migrate to using an array as easier in smart... |
| 178 | $descriptions[$setting] = ts($props['description']); |
| 179 | $this->assign("{$setting}_description", ts($props['description'])); |
| 180 | if ($setting == 'max_attachments') { |
| 181 | //temp hack @todo fix to get from metadata |
| 182 | $this->addRule('max_attachments', ts('Value should be a positive number'), 'positiveInteger'); |
| 183 | } |
| 184 | if ($setting == 'maxFileSize') { |
| 185 | //temp hack |
| 186 | $this->addRule('maxFileSize', ts('Value should be a positive number'), 'positiveInteger'); |
| 187 | } |
| 188 | |
| 189 | } |
| 190 | } |
| 191 | // setting_description should be deprecated - see Mail.tpl for metadata based tpl. |
| 192 | $this->assign('setting_descriptions', $descriptions); |
| 193 | $this->assign('settings_fields', $settingMetaData); |
| 194 | $this->assign('fields', $settingMetaData); |
| 195 | } |
| 196 | |
| 197 | /** |
| 198 | * Get the quickform type for the given html type. |
| 199 | * |
| 200 | * @param array $spec |
| 201 | * |
| 202 | * @return string |
| 203 | */ |
| 204 | protected function getQuickFormType($spec) { |
| 205 | if (isset($spec['quick_form_type']) && |
| 206 | !($spec['quick_form_type'] === 'Element' && !empty($spec['html_type']))) { |
| 207 | return $spec['quick_form_type']; |
| 208 | } |
| 209 | $mapping = [ |
| 210 | 'checkboxes' => 'CheckBoxes', |
| 211 | 'checkbox' => 'CheckBox', |
| 212 | 'radio' => 'Radio', |
| 213 | 'select' => 'Select', |
| 214 | 'textarea' => 'Element', |
| 215 | ]; |
| 216 | return $mapping[$spec['html_type']]; |
| 217 | } |
| 218 | /** |
| 219 | * Get the defaults for all fields defined in the metadata. |
| 220 | * |
| 221 | * All others are pending conversion. |
| 222 | */ |
| 223 | protected function setDefaultsForMetadataDefinedFields() { |
| 224 | CRM_Core_BAO_ConfigSetting::retrieve($this->_defaults); |
| 225 | foreach (array_keys($this->_settings) as $setting) { |
| 226 | $this->_defaults[$setting] = civicrm_api3('setting', 'getvalue', ['name' => $setting]); |
| 227 | $spec = $this->getSettingsMetadata()[$setting]; |
| 228 | if (!empty($spec['serialize'])) { |
| 229 | $this->_defaults[$setting] = CRM_Core_DAO::unSerializeField($this->_defaults[$setting], $spec['serialize']); |
| 230 | } |
| 231 | if ($this->getQuickFormType($spec) === 'CheckBoxes') { |
| 232 | $this->_defaults[$setting] = array_fill_keys($this->_defaults[$setting], 1); |
| 233 | } |
| 234 | } |
| 235 | } |
| 236 | |
| 237 | /** |
| 238 | * @param $params |
| 239 | * |
| 240 | */ |
| 241 | protected function saveMetadataDefinedSettings($params) { |
| 242 | $settings = $this->getSettingsToSetByMetadata($params); |
| 243 | foreach ($settings as $setting => $settingValue) { |
| 244 | if ($this->getQuickFormType($this->getSettingMetadata($setting)) === 'CheckBoxes') { |
| 245 | $settings[$setting] = array_keys($settingValue); |
| 246 | } |
| 247 | } |
| 248 | civicrm_api3('setting', 'create', $settings); |
| 249 | } |
| 250 | |
| 251 | } |