3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2016 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
34 * Read and write settings for a given domain (or contact).
36 * If the target entity does not already have a value for the setting, then
37 * the defaults will be used. If mandatory values are provided, they will
38 * override any defaults or custom settings.
40 * It's expected that the SettingsBag will have O(50-250) settings -- and that
41 * we'll load the full bag on many page requests. Consequently, we don't
42 * want the full metadata (help text and version history and HTML widgets)
43 * for all 250 settings, but we do need the default values.
45 * This class is not usually instantiated directly. Instead, use SettingsManager
46 * or Civi::settings().
48 * @see \Civi::settings()
49 * @see SettingsManagerTest
59 * Array(string $settingName => mixed $value).
65 * Array(string $settingName => mixed $value).
70 * The result of combining default values, mandatory
71 * values, and user values.
74 * Array(string $settingName => mixed $value).
84 * @param int $domainId
85 * The domain for which we want settings.
86 * @param int|NULL $contactId
87 * The contact for which we want settings. Use NULL for domain settings.
89 public function __construct($domainId, $contactId) {
90 $this->domainId
= $domainId;
91 $this->contactId
= $contactId;
92 $this->values
= array();
93 $this->combined
= NULL;
97 * Set/replace the default values.
99 * @param array $defaults
100 * Array(string $settingName => mixed $value).
101 * @return SettingsBag
103 public function loadDefaults($defaults) {
104 $this->defaults
= $defaults;
105 $this->combined
= NULL;
110 * Set/replace the mandatory values.
112 * @param array $mandatory
113 * Array(string $settingName => mixed $value).
114 * @return SettingsBag
116 public function loadMandatory($mandatory) {
117 $this->mandatory
= $mandatory;
118 $this->combined
= NULL;
123 * Load all explicit settings that apply to this domain or contact.
125 * @return SettingsBag
127 public function loadValues() {
128 // Note: Don't use DAO child classes. They require fields() which require
129 // translations -- which are keyed off settings!
131 $this->values
= array();
132 $this->combined
= NULL;
134 // Ordinarily, we just load values from `civicrm_setting`. But upgrades require care.
135 // In v4.0 and earlier, all values were stored in `civicrm_domain.config_backend`.
136 // In v4.1-v4.6, values were split between `civicrm_domain` and `civicrm_setting`.
137 // In v4.7+, all values are stored in `civicrm_setting`.
138 // Whenever a value is available in civicrm_setting, it will take precedence.
140 $isUpgradeMode = \CRM_Core_Config
::isUpgradeMode();
142 if ($isUpgradeMode && empty($this->contactId
) && \CRM_Core_DAO
::checkFieldExists('civicrm_domain', 'config_backend', FALSE)) {
143 $config_backend = \CRM_Core_DAO
::singleValueQuery('SELECT config_backend FROM civicrm_domain WHERE id = %1',
144 array(1 => array($this->domainId
, 'Positive')));
145 $oldSettings = \CRM_Upgrade_Incremental_php_FourSeven
::convertBackendToSettings($this->domainId
, $config_backend);
146 \CRM_Utils_Array
::extend($this->values
, $oldSettings);
149 // Normal case. Aside: Short-circuit prevents unnecessary query.
150 if (!$isUpgradeMode || \CRM_Core_DAO
::checkTableExists('civicrm_setting')) {
151 $dao = \CRM_Core_DAO
::executeQuery($this->createQuery()->toSQL());
152 while ($dao->fetch()) {
153 $this->values
[$dao->name
] = ($dao->value
!== NULL) ?
unserialize($dao->value
) : NULL;
161 * Add a batch of settings. Save them.
163 * @param array $settings
164 * Array(string $settingName => mixed $settingValue).
165 * @return SettingsBag
167 public function add(array $settings) {
168 foreach ($settings as $key => $value) {
169 $this->set($key, $value);
175 * Get a list of all effective settings.
178 * Array(string $settingName => mixed $settingValue).
180 public function all() {
181 if ($this->combined
=== NULL) {
182 $this->combined
= $this->combine(
183 array($this->defaults
, $this->values
, $this->mandatory
)
186 return $this->combined
;
190 * Determine the effective value.
195 public function get($key) {
197 return isset($all[$key]) ?
$all[$key] : NULL;
201 * Determine the default value of a setting.
204 * The simple name of the setting.
207 public function getDefault($key) {
208 return isset($this->defaults
[$key]) ?
$this->defaults
[$key] : NULL;
212 * Determine the explicitly designated value, regardless of
213 * any default or mandatory values.
216 * The simple name of the setting.
219 public function getExplicit($key) {
220 return (isset($this->values
[$key]) ?
$this->values
[$key] : NULL);
224 * Determine the mandatory value of a setting.
227 * The simple name of the setting.
230 public function getMandatory($key) {
231 return isset($this->mandatory
[$key]) ?
$this->mandatory
[$key] : NULL;
235 * Determine if the entity has explicitly designated a value.
237 * Note that get() may still return other values based on
238 * mandatory values or defaults.
241 * The simple name of the setting.
244 public function hasExplict($key) {
245 // NULL means no designated value.
246 return isset($this->values
[$key]);
250 * Removes any explicit settings. This restores the default.
253 * The simple name of the setting.
254 * @return SettingsBag
256 public function revert($key) {
257 // It might be better to DELETE (to avoid long-term leaks),
258 // but setting NULL is simpler for now.
259 return $this->set($key, NULL);
263 * Add a single setting. Save it.
266 * The simple name of the setting.
267 * @param mixed $value
268 * The new, explicit value of the setting.
269 * @return SettingsBag
271 public function set($key, $value) {
272 $this->setDb($key, $value);
273 $this->values
[$key] = $value;
274 $this->combined
= NULL;
279 * @return \CRM_Utils_SQL_Select
281 protected function createQuery() {
282 $select = \CRM_Utils_SQL_Select
::from('civicrm_setting')
283 ->select('id, name, value, domain_id, contact_id, is_domain, component_id, created_date, created_id')
284 ->where('domain_id = #id', array(
285 'id' => $this->domainId
,
287 if ($this->contactId
=== NULL) {
288 $select->where('is_domain = 1');
291 $select->where('contact_id = #id', array(
292 'id' => $this->contactId
,
294 $select->where('is_domain = 0');
300 * Combine a series of arrays, excluding any
301 * null values. Later values override earlier
304 * @param array $arrays
305 * List of arrays to combine.
308 protected function combine($arrays) {
310 foreach ($arrays as $array) {
311 foreach ($array as $k => $v) {
321 * Update the DB record for this setting.
323 * @param string $name
324 * The simple name of the setting.
325 * @param mixed $value
326 * The new value of the setting.
328 protected function setDb($name, $value) {
329 if (\CRM_Core_BAO_Setting
::isUpgradeFromPreFourOneAlpha1()) {
330 // civicrm_setting table is not going to be present.
335 $fieldsToSet = \CRM_Core_BAO_Setting
::validateSettingsInput(array($name => $value), $fields);
336 //We haven't traditionally validated inputs to setItem, so this breaks things.
337 //foreach ($fieldsToSet as $settingField => &$settingValue) {
338 // self::validateSetting($settingValue, $fields['values'][$settingField]);
341 $metadata = $fields['values'][$name];
343 $dao = new \
CRM_Core_DAO_Setting();
345 $dao->domain_id
= $this->domainId
;
346 if ($this->contactId
) {
347 $dao->contact_id
= $this->contactId
;
355 if (isset($metadata['on_change'])) {
356 foreach ($metadata['on_change'] as $callback) {
358 \Civi\Core\Resolver
::singleton()->get($callback),
359 unserialize($dao->value
),
367 if (!is_array($value) && \CRM_Utils_System
::isNull($value)) {
368 $dao->value
= 'null';
371 $dao->value
= serialize($value);
374 if (!isset(\Civi
::$statics[__CLASS__
]['upgradeMode'])) {
375 \Civi
::$statics[__CLASS__
]['upgradeMode'] = \CRM_Core_Config
::isUpgradeMode();
377 if (\Civi
::$statics[__CLASS__
]['upgradeMode'] && \CRM_Core_DAO
::checkFieldExists('civicrm_setting', 'group_name')) {
378 $dao->group_name
= 'placeholder';
381 $dao->created_date
= \CRM_Utils_Time
::getTime('YmdHis');
383 $session = \CRM_Core_Session
::singleton();
384 if (\CRM_Contact_BAO_Contact_Utils
::isContactId($session->get('userID'))) {
385 $dao->created_id
= $session->get('userID');
392 // Cannot use $dao->save(); in upgrade mode (eg WP + Civi 4.4=>4.7), the DAO will refuse
393 // to save the field `group_name`, which is required in older schema.
394 \CRM_Core_DAO
::executeQuery(\CRM_Utils_SQL_Insert
::dao($dao)->toSQL());