Settings - Remove special cases for `prefetch` and `config_only`
[civicrm-core.git] / CRM / Core / BAO / Setting.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
7e9e8871 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
e7112fa7 6 | Copyright CiviCRM LLC (c) 2004-2015 |
6a488035
TO
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
e7112fa7 31 * @copyright CiviCRM LLC (c) 2004-2015
6a488035
TO
32 */
33
34/**
35 * BAO object for civicrm_setting table. This table is used to store civicrm settings that are not used
36 * very frequently (i.e. not on every page load)
37 *
38 * The group column is used for grouping together all settings that logically belong to the same set.
39 * Thus all settings in the same group are retrieved with one DB call and then cached for future needs.
6a488035
TO
40 */
41class CRM_Core_BAO_Setting extends CRM_Core_DAO_Setting {
42
43 /**
fe482240 44 * Various predefined settings that have been migrated to the setting table.
6a488035 45 */
7da04cde 46 const
6a488035
TO
47 ADDRESS_STANDARDIZATION_PREFERENCES_NAME = 'Address Standardization Preferences',
48 CAMPAIGN_PREFERENCES_NAME = 'Campaign Preferences',
5d0140d9 49 DEVELOPER_PREFERENCES_NAME = 'Developer Preferences',
6a488035
TO
50 DIRECTORY_PREFERENCES_NAME = 'Directory Preferences',
51 EVENT_PREFERENCES_NAME = 'Event Preferences',
52 MAILING_PREFERENCES_NAME = 'Mailing Preferences',
1ec598f3 53 MAP_PREFERENCES_NAME = 'Map Preferences',
6a488035
TO
54 CONTRIBUTE_PREFERENCES_NAME = 'Contribute Preferences',
55 MEMBER_PREFERENCES_NAME = 'Member Preferences',
56 MULTISITE_PREFERENCES_NAME = 'Multi Site Preferences',
57 PERSONAL_PREFERENCES_NAME = 'Personal Preferences',
58 SYSTEM_PREFERENCES_NAME = 'CiviCRM Preferences',
59 URL_PREFERENCES_NAME = 'URL Preferences',
60 LOCALIZATION_PREFERENCES_NAME = 'Localization Preferences',
61 SEARCH_PREFERENCES_NAME = 'Search Preferences';
62 static $_cache = NULL;
63
64 /**
65 * Checks whether an item is present in the in-memory cache table
66 *
6a0b768e
TO
67 * @param string $group
68 * (required) The group name of the item.
69 * @param string $name
70 * (required) The name of the setting.
71 * @param int $componentID
72 * The optional component ID (so components can share the same name space).
73 * @param int $contactID
74 * If set, this is a contactID specific setting, else its a global setting.
77b97be7
EM
75 * @param bool|int $load if true, load from local cache (typically memcache)
76 *
100fef9d 77 * @param int $domainID
77b97be7 78 * @param bool $force
6a488035 79 *
5c766a0b 80 * @return bool
a6c01b45 81 * true if item is already in cache
6a488035 82 */
2da40d21 83 public static function inCache(
eb40b5a4 84 $group,
6a488035
TO
85 $name,
86 $componentID = NULL,
242bd179
TO
87 $contactID = NULL,
88 $load = FALSE,
eb40b5a4 89 $domainID = NULL,
90 $force = FALSE
6a488035
TO
91 ) {
92 if (!isset(self::$_cache)) {
93 self::$_cache = array();
94 }
95
96 $cacheKey = "CRM_Setting_{$group}_{$componentID}_{$contactID}_{$domainID}";
eb40b5a4 97
56cb3188
DL
98 if (
99 $load &&
eb40b5a4 100 ($force || !isset(self::$_cache[$cacheKey]))
6a488035 101 ) {
eb40b5a4 102
6a488035
TO
103 // check in civi cache if present (typically memcache)
104 $globalCache = CRM_Utils_Cache::singleton();
105 $result = $globalCache->get($cacheKey);
106 if ($result) {
eb40b5a4 107
6a488035
TO
108 self::$_cache[$cacheKey] = $result;
109 }
110 }
111
112 return isset(self::$_cache[$cacheKey]) ? $cacheKey : NULL;
113 }
353ffa53 114
eb40b5a4 115 /**
fe482240 116 * Allow key o be cleared.
353ffa53
TO
117 * @param string $cacheKey
118 */
9b873358 119 public static function flushCache($cacheKey) {
eb40b5a4 120 unset(self::$_cache[$cacheKey]);
121 $globalCache = CRM_Utils_Cache::singleton();
122 $globalCache->delete($cacheKey);
123 }
6a488035 124
b5c2afd0
EM
125 /**
126 * @param $values
127 * @param $group
100fef9d
CW
128 * @param int $componentID
129 * @param int $contactID
130 * @param int $domainID
b5c2afd0
EM
131 *
132 * @return string
133 */
2da40d21 134 public static function setCache(
f9f40af3 135 $values,
6a488035
TO
136 $group,
137 $componentID = NULL,
138 $contactID = NULL,
139 $domainID = NULL
140 ) {
141 if (!isset(self::$_cache)) {
142 self::$_cache = array();
143 }
144
145 $cacheKey = "CRM_Setting_{$group}_{$componentID}_{$contactID}_{$domainID}";
146
147 self::$_cache[$cacheKey] = $values;
148
149 $globalCache = CRM_Utils_Cache::singleton();
150 $result = $globalCache->set($cacheKey, $values);
151
152 return $cacheKey;
153 }
154
b5c2afd0
EM
155 /**
156 * @param $group
157 * @param null $name
100fef9d
CW
158 * @param int $componentID
159 * @param int $contactID
160 * @param int $domainID
b5c2afd0
EM
161 *
162 * @return CRM_Core_DAO_Domain|CRM_Core_DAO_Setting
163 */
2da40d21 164 public static function dao(
f9f40af3 165 $group,
242bd179 166 $name = NULL,
6a488035 167 $componentID = NULL,
242bd179 168 $contactID = NULL,
6a488035
TO
169 $domainID = NULL
170 ) {
2c7039ef 171 if (self::isUpgradeFromPreFourOneAlpha1()) {
03d8f8f3 172 // civicrm_setting table is not going to be present. For now we'll just
2c7039ef
DS
173 // return a dummy object
174 $dao = new CRM_Core_DAO_Domain();
175 $dao->id = -1; // so ->find() doesn't fetch any data later on
176 return $dao;
177 }
6a488035
TO
178 $dao = new CRM_Core_DAO_Setting();
179
b391b97b
TO
180 if (!empty($group)) {
181 $dao->group_name = $group;
182 }
242bd179 183 $dao->name = $name;
6a488035
TO
184 $dao->component_id = $componentID;
185 if (empty($domainID)) {
353ffa53 186 $dao->domain_id = CRM_Core_Config::domainID();
6a488035
TO
187 }
188 else {
189 $dao->domain_id = $domainID;
190 }
191
192 if ($contactID) {
193 $dao->contact_id = $contactID;
194 $dao->is_domain = 0;
195 }
196 else {
197 $dao->is_domain = 1;
198 }
199
200 return $dao;
201 }
202
203 /**
fe482240 204 * Retrieve the value of a setting from the DB table.
6a488035 205 *
6a0b768e
TO
206 * @param string $group
207 * (required) The group name of the item.
208 * @param string $name
209 * (required) The name under which this item is stored.
210 * @param int $componentID
211 * The optional component ID (so componenets can share the same name space).
212 * @param string $defaultValue
213 * The default value to return for this setting if not present in DB.
214 * @param int $contactID
215 * If set, this is a contactID specific setting, else its a global setting.
da6b46f4 216 *
100fef9d 217 * @param int $domainID
6a488035 218 *
72b3a70c
CW
219 * @return mixed
220 * The data if present in the setting table, else null
6a488035 221 */
2da40d21 222 public static function getItem(
56cb3188 223 $group,
242bd179
TO
224 $name = NULL,
225 $componentID = NULL,
6a488035 226 $defaultValue = NULL,
242bd179
TO
227 $contactID = NULL,
228 $domainID = NULL
6a488035 229 ) {
3a84c0ab
TO
230 /** @var \Civi\Core\SettingsManager $manager */
231 $manager = \Civi::service('settings_manager');
232 $settings = ($contactID === NULL) ? $manager->getBagByDomain($domainID) : $manager->getBagByContact($domainID, $contactID);
233 if (TRUE) {
234 if ($name === NULL) {
235 CRM_Core_Error::debug_log_message("Deprecated: Group='$group'. Name should be provided.\n");
bf83df95 236 }
3a84c0ab
TO
237 if ($componentID !== NULL) {
238 CRM_Core_Error::debug_log_message("Deprecated: Group='$group'. Name='$name'. Component should be omitted\n");
6a488035 239 }
3a84c0ab
TO
240 if ($defaultValue !== NULL) {
241 CRM_Core_Error::debug_log_message("Deprecated: Group='$group'. Name='$name'. Defaults should come from metadata\n");
bf83df95 242 }
6a488035 243 }
3a84c0ab 244 return $name ? $settings->get($name) : $settings->all();
6a488035
TO
245 }
246
247 /**
35823763 248 * Store multiple items in the setting table.
6a488035 249 *
6a0b768e
TO
250 * @param array $params
251 * (required) An api formatted array of keys and values.
35823763 252 * @param array $domains Array of domains to get settings for. Default is the current domain
dd244018
EM
253 * @param $settingsToReturn
254 *
35823763 255 * @return array
6a488035 256 */
00be9182 257 public static function getItems(&$params, $domains = NULL, $settingsToReturn) {
0e04f44e 258 $originalDomain = CRM_Core_Config::domainID();
6a488035 259 if (empty($domains)) {
0e04f44e 260 $domains[] = $originalDomain;
6a488035
TO
261 }
262 if (!empty($settingsToReturn) && !is_array($settingsToReturn)) {
263 $settingsToReturn = array($settingsToReturn);
264 }
0e04f44e 265 $reloadConfig = FALSE;
266
6a488035
TO
267 $fields = $result = array();
268 $fieldsToGet = self::validateSettingsInput(array_flip($settingsToReturn), $fields, FALSE);
7583c3f3 269 foreach ($domains as $domainID) {
9b873358 270 if ($domainID != CRM_Core_Config::domainID()) {
0e04f44e 271 $reloadConfig = TRUE;
7583c3f3 272 CRM_Core_BAO_Domain::setDomain($domainID);
0e04f44e 273 }
274 $config = CRM_Core_Config::singleton($reloadConfig, $reloadConfig);
7583c3f3 275 $result[$domainID] = array();
6a488035 276 foreach ($fieldsToGet as $name => $value) {
52baaadf
TO
277 $setting = CRM_Core_BAO_Setting::getItem(
278 $fields['values'][$name]['group_name'],
279 $name,
280 CRM_Utils_Array::value('component_id', $params),
281 NULL,
282 CRM_Utils_Array::value('contact_id', $params),
283 $domainID
284 );
6a488035
TO
285 if (!is_null($setting)) {
286 // we won't return if not set - helps in return all scenario - otherwise we can't indentify the missing ones
287 // e.g for revert of fill actions
7583c3f3 288 $result[$domainID][$name] = $setting;
6a488035
TO
289 }
290 }
7583c3f3 291 CRM_Core_BAO_Domain::resetDomain();
6a488035
TO
292 }
293 return $result;
294 }
295
296 /**
fe482240 297 * Store an item in the setting table.
6a488035 298 *
a57707d3
TO
299 * _setItem() is the common logic shared by setItem() and setItems().
300 *
6a0b768e
TO
301 * @param object $value
302 * (required) The value that will be serialized and stored.
303 * @param string $group
304 * (required) The group name of the item.
305 * @param string $name
306 * (required) The name of the setting.
307 * @param int $componentID
308 * The optional component ID (so componenets can share the same name space).
100fef9d 309 * @param int $contactID
6a0b768e
TO
310 * @param int $createdID
311 * An optional ID to assign the creator to. If not set, retrieved from session.
fd31fa4c 312 *
100fef9d 313 * @param int $domainID
6a488035 314 */
2da40d21 315 public static function setItem(
6a488035
TO
316 $value,
317 $group,
318 $name,
319 $componentID = NULL,
242bd179
TO
320 $contactID = NULL,
321 $createdID = NULL,
322 $domainID = NULL
a57707d3 323 ) {
3a84c0ab
TO
324 /** @var \Civi\Core\SettingsManager $manager */
325 $manager = \Civi::service('settings_manager');
326 $settings = ($contactID === NULL) ? $manager->getBagByDomain($domainID) : $manager->getBagByContact($domainID, $contactID);
327 $settings->set($name, $value);
a57707d3
TO
328 }
329
330 /**
fe482240 331 * Store an item in a setting table.
a57707d3
TO
332 *
333 * _setItem() is the common logic shared by setItem() and setItems().
334 *
6a0b768e
TO
335 * @param array $metadata
336 * Metadata describing this field.
a57707d3
TO
337 * @param $value
338 * @param $group
100fef9d
CW
339 * @param string $name
340 * @param int $componentID
341 * @param int $contactID
342 * @param int $createdID
343 * @param int $domainID
a57707d3 344 */
2da40d21 345 public static function _setItem(
a57707d3
TO
346 $metadata,
347 $value,
348 $group,
349 $name,
350 $componentID = NULL,
242bd179
TO
351 $contactID = NULL,
352 $createdID = NULL,
353 $domainID = NULL
6a488035 354 ) {
6a488035
TO
355 if (empty($domainID)) {
356 $domainID = CRM_Core_Config::domainID();
357 }
358
359 $dao = self::dao($group, $name, $componentID, $contactID, $domainID);
360 $dao->find(TRUE);
b391b97b 361 $dao->group_name = $group;
6a488035 362
a57707d3
TO
363 if (isset($metadata['on_change'])) {
364 foreach ($metadata['on_change'] as $callback) {
c8074a93
TO
365 call_user_func(
366 Civi\Core\Resolver::singleton()->get($callback),
367 unserialize($dao->value),
368 $value,
b72b5fc0
TO
369 $metadata,
370 $domainID
c8074a93 371 );
a57707d3
TO
372 }
373 }
374
6a488035
TO
375 if (CRM_Utils_System::isNull($value)) {
376 $dao->value = 'null';
377 }
378 else {
379 $dao->value = serialize($value);
380 }
381
382 $dao->created_date = date('Ymdhis');
383
384 if ($createdID) {
385 $dao->created_id = $createdID;
386 }
387 else {
388 $session = CRM_Core_Session::singleton();
389 $createdID = $session->get('userID');
390
391 if ($createdID) {
392 // ensure that this is a valid contact id (for session inconsistency rules)
393 $cid = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
394 $createdID,
395 'id',
396 'id'
397 );
398 if ($cid) {
399 $dao->created_id = $session->get('userID');
400 }
401 }
402 }
403
404 $dao->save();
405 $dao->free();
406
407 // also save in cache if needed
408 $cacheKey = self::inCache($group, $name, $componentID, $contactID, FALSE, $domainID);
409 if ($cacheKey) {
410 self::$_cache[$cacheKey][$name] = $value;
411 }
412 }
413
414 /**
415 * Store multiple items in the setting table. Note that this will also store config keys
416 * the storage is determined by the metdata and is affected by
417 * 'name' setting's name
6a488035
TO
418 * 'config_key' = the config key is different to the settings key - e.g. debug where there was a conflict
419 * 'legacy_key' = rename from config or setting with this name
420 *
a57707d3
TO
421 * _setItem() is the common logic shared by setItem() and setItems().
422 *
6a0b768e
TO
423 * @param array $params
424 * (required) An api formatted array of keys and values.
2a6da8d7
EM
425 * @param null $domains
426 *
427 * @throws api_Exception
6a488035 428 * @domains array an array of domains to get settings for. Default is the current domain
3d0d359e 429 * @return array
6a488035 430 */
00be9182 431 public static function setItems(&$params, $domains = NULL) {
3a84c0ab
TO
432 /** @var \Civi\Core\SettingsManager $manager */
433 $manager = \Civi::service('settings_manager');
434 $domains = empty($domains) ? array(CRM_Core_Config::domainID()) : $domains;
435
436 // FIXME: redundant validation
437 // FIXME: this whole thing should just be a loop to call $settings->add() on each domain.
438
7583c3f3 439 $reloadConfig = FALSE;
6a488035
TO
440 $fields = $config_keys = array();
441 $fieldsToSet = self::validateSettingsInput($params, $fields);
442
443 foreach ($fieldsToSet as $settingField => &$settingValue) {
444 self::validateSetting($settingValue, $fields['values'][$settingField]);
445 }
446
7583c3f3 447 foreach ($domains as $domainID) {
3a84c0ab 448
9b873358 449 if ($domainID != CRM_Core_Config::domainID()) {
7583c3f3 450 $reloadConfig = TRUE;
451 CRM_Core_BAO_Domain::setDomain($domainID);
452 }
453 $result[$domainID] = array();
3a84c0ab 454 $realSettingsToSet = array(); // need to separate config_backend stuff
6a488035 455 foreach ($fieldsToSet as $name => $value) {
52baaadf 456 $realSettingsToSet[$name] = $value;
7583c3f3 457 $result[$domainID][$name] = $value;
458 }
3a84c0ab 459 $manager->getBagByDomain($domainID)->add($realSettingsToSet);
9b873358 460 if ($reloadConfig) {
7583c3f3 461 CRM_Core_Config::singleton($reloadConfig, $reloadConfig);
462 }
463
9b873358 464 if (!empty($config_keys)) {
7583c3f3 465 CRM_Core_BAO_ConfigSetting::create($config_keys);
466 }
9b873358 467 if ($reloadConfig) {
7583c3f3 468 CRM_Core_BAO_Domain::resetDomain();
6a488035 469 }
6a488035
TO
470 }
471
472 return $result;
473 }
474
475 /**
100fef9d 476 * Gets metadata about the settings fields (from getfields) based on the fields being passed in
6a488035
TO
477 *
478 * This function filters on the fields like 'version' & 'debug' that are not settings
77b97be7 479 *
6a0b768e
TO
480 * @param array $params
481 * Parameters as passed into API.
482 * @param array $fields
483 * Empty array to be populated with fields metadata.
6a488035
TO
484 * @param bool $createMode
485 *
77b97be7 486 * @throws api_Exception
a6c01b45
CW
487 * @return array
488 * name => value array of the fields to be set (with extraneous removed)
6a488035 489 */
00be9182 490 public static function validateSettingsInput($params, &$fields, $createMode = TRUE) {
6a488035
TO
491 $group = CRM_Utils_Array::value('group', $params);
492
493 $ignoredParams = array(
494 'version',
495 'id',
496 'domain_id',
497 'debug',
498 'created_id',
499 'component_id',
500 'contact_id',
501 'filters',
502 'entity_id',
503 'entity_table',
504 'sequential',
505 'api.has_parent',
f704dce7 506 'IDS_request_uri',
507 'IDS_user_agent',
508 'check_permissions',
80fbde47 509 'options',
e56fd67f 510 'prettyprint',
6a488035
TO
511 );
512 $settingParams = array_diff_key($params, array_fill_keys($ignoredParams, TRUE));
513 $getFieldsParams = array('version' => 3);
d3e86119 514 if (count($settingParams) == 1) {
6a488035
TO
515 // ie we are only setting one field - we'll pass it into getfields for efficiency
516 list($name) = array_keys($settingParams);
517 $getFieldsParams['name'] = $name;
518 }
353ffa53 519 $fields = civicrm_api3('setting', 'getfields', $getFieldsParams);
6a488035
TO
520 $invalidParams = (array_diff_key($settingParams, $fields['values']));
521 if (!empty($invalidParams)) {
e56fd67f 522 throw new api_Exception(implode(',', array_keys($invalidParams)) . " not valid settings");
6a488035
TO
523 }
524 if (!empty($settingParams)) {
525 $filteredFields = array_intersect_key($settingParams, $fields['values']);
526 }
527 else {
528 // no filters so we are interested in all for get mode. In create mode this means nothing to set
529 $filteredFields = $createMode ? array() : $fields['values'];
530 }
531 return $filteredFields;
532 }
533
534 /**
535 * Validate & convert settings input
536 *
537 * @value mixed value of the setting to be set
538 * @fieldSpec array Metadata for given field (drawn from the xml)
539 */
00be9182 540 public static function validateSetting(&$value, $fieldSpec) {
9b873358 541 if ($fieldSpec['type'] == 'String' && is_array($value)) {
353ffa53 542 $value = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR, $value) . CRM_Core_DAO::VALUE_SEPARATOR;
6a488035
TO
543 }
544 if (empty($fieldSpec['validate_callback'])) {
607cb45e 545 return TRUE;
6a488035
TO
546 }
547 else {
c8074a93
TO
548 $cb = Civi\Core\Resolver::singleton()->get($fieldSpec['validate_callback']);
549 if (!call_user_func_array($cb, array(&$value, $fieldSpec))) {
ee7b49c4 550 throw new api_Exception("validation failed for {$fieldSpec['name']} = $value based on callback {$fieldSpec['validate_callback']}");
6a488035
TO
551 }
552 }
553 }
554
555 /**
556 * Validate & convert settings input - translate True False to 0 or 1
557 *
558 * @value mixed value of the setting to be set
559 * @fieldSpec array Metadata for given field (drawn from the xml)
560 */
00be9182 561 public static function validateBoolSetting(&$value, $fieldSpec) {
6a488035 562 if (!CRM_Utils_Rule::boolean($value)) {
ee7b49c4 563 throw new api_Exception("Boolean value required for {$fieldSpec['name']}");
6a488035
TO
564 }
565 if (!$value) {
566 $value = 0;
567 }
568 else {
569 $value = 1;
570 }
571 return TRUE;
572 }
573
6a488035
TO
574 /**
575 * This provides information about the setting - similar to the fields concept for DAO information.
576 * As the setting is serialized code creating validation setting input needs to know the data type
577 * This also helps move information out of the form layer into the data layer where people can interact with
578 * it via the API or other mechanisms. In order to keep this consistent it is important the form layer
579 * also leverages it.
580 *
581 * Note that this function should never be called when using the runtime getvalue function. Caching works
582 * around the expectation it will be called during setting administration
583 *
584 * Function is intended for configuration rather than runtime access to settings
585 *
586 * The following params will filter the result. If none are passed all settings will be returns
587 *
6a0b768e
TO
588 * @param int $componentID
589 * Id of relevant component.
2a6da8d7 590 * @param array $filters
c490a46a 591 * @param int $domainID
2a6da8d7
EM
592 * @param null $profile
593 *
a6c01b45
CW
594 * @return array
595 * the following information as appropriate for each setting
5c766a0b
TO
596 * - name
597 * - type
598 * - default
599 * - add (CiviCRM version added)
600 * - is_domain
601 * - is_contact
602 * - description
603 * - help_text
6a488035 604 */
2da40d21 605 public static function getSettingSpecification(
607cb45e 606 $componentID = NULL,
b597d0b1 607 $filters = array(),
607cb45e
TO
608 $domainID = NULL,
609 $profile = NULL
b597d0b1 610 ) {
c7d90a9f 611 return \Civi\Core\SettingsMetadata::getMetadata($filters, $domainID, $profile);
6a488035
TO
612 }
613
614 /**
0880a9d0 615 * Look for any missing settings and convert them from config or load default as appropriate.
6a488035
TO
616 * This should be run from GenCode & also from upgrades to add any new defaults.
617 *
618 * Multisites have often been overlooked in upgrade scripts so can be expected to be missing
619 * a number of settings
620 */
00be9182 621 public static function updateSettingsFromMetaData() {
6a488035
TO
622 $apiParams = array(
623 'version' => 3,
624 'domain_id' => 'all',
eb40b5a4 625 'filters' => array('prefetch' => 0),
6a488035
TO
626 );
627 $existing = civicrm_api('setting', 'get', $apiParams);
eb40b5a4 628
6a488035
TO
629 if (!empty($existing['values'])) {
630 $allSettings = civicrm_api('setting', 'getfields', array('version' => 3));
631 foreach ($existing['values'] as $domainID => $domainSettings) {
632 CRM_Core_BAO_Domain::setDomain($domainID);
633 $missing = array_diff_key($allSettings['values'], $domainSettings);
634 foreach ($missing as $name => $settings) {
635 self::convertConfigToSetting($name, $domainID);
636 }
637 CRM_Core_BAO_Domain::resetDomain();
638 }
639 }
640 }
641
642 /**
100fef9d 643 * Move an item from being in the config array to being stored as a setting
6a488035
TO
644 * remove from config - as appropriate based on metadata
645 *
646 * Note that where the key name is being changed the 'legacy_key' will give us the old name
647 */
00be9182 648 public static function convertConfigToSetting($name, $domainID = NULL) {
eb40b5a4 649 // we have to force this here in case more than one domain is in play.
650 // whenever there is a possibility of more than one domain we must force it
6a488035
TO
651 $config = CRM_Core_Config::singleton();
652 if (empty($domainID)) {
d3e86119 653 $domainID = CRM_Core_Config::domainID();
6a488035
TO
654 }
655 $domain = new CRM_Core_DAO_Domain();
656 $domain->id = $domainID;
657 $domain->find(TRUE);
658 if ($domain->config_backend) {
659 $values = unserialize($domain->config_backend);
0db6c3e1
TO
660 }
661 else {
6a488035
TO
662 $values = array();
663 }
607cb45e 664 $spec = self::getSettingSpecification(NULL, array('name' => $name), $domainID);
6a488035 665 $configKey = CRM_Utils_Array::value('config_key', $spec[$name], CRM_Utils_Array::value('legacy_key', $spec[$name], $name));
52baaadf
TO
666 if (!empty($values[$configKey])) {
667 civicrm_api('setting', 'create', array('version' => 3, $name => $values[$configKey], 'domain_id' => $domainID));
668 }
669 else {
670 civicrm_api('setting', 'fill', array('version' => 3, 'name' => $name, 'domain_id' => $domainID));
671 }
6a488035 672
52baaadf
TO
673 if (!empty($values[$configKey])) {
674 unset($values[$configKey]);
675 $domain->config_backend = serialize($values);
676 $domain->save();
6a488035
TO
677 }
678 }
679
b5c2afd0
EM
680 /**
681 * @param $group
100fef9d 682 * @param string $name
b5c2afd0 683 * @param bool $system
100fef9d 684 * @param int $userID
b5c2afd0
EM
685 * @param bool $localize
686 * @param string $returnField
687 * @param bool $returnNameANDLabels
688 * @param null $condition
689 *
690 * @return array
691 */
2da40d21 692 public static function valueOptions(
f9f40af3 693 $group,
6a488035 694 $name,
242bd179
TO
695 $system = TRUE,
696 $userID = NULL,
697 $localize = FALSE,
698 $returnField = 'name',
6a488035 699 $returnNameANDLabels = FALSE,
242bd179 700 $condition = NULL
6a488035
TO
701 ) {
702 $optionValue = self::getItem($group, $name);
703
704 $groupValues = CRM_Core_OptionGroup::values($name, FALSE, FALSE, $localize, $condition, $returnField);
705
706 //enabled name => label require for new contact edit form, CRM-4605
707 if ($returnNameANDLabels) {
708 $names = $labels = $nameAndLabels = array();
709 if ($returnField == 'name') {
710 $names = $groupValues;
711 $labels = CRM_Core_OptionGroup::values($name, FALSE, FALSE, $localize, $condition, 'label');
712 }
713 else {
714 $labels = $groupValues;
715 $names = CRM_Core_OptionGroup::values($name, FALSE, FALSE, $localize, $condition, 'name');
716 }
717 }
718
719 $returnValues = array();
720 foreach ($groupValues as $gn => $gv) {
721 $returnValues[$gv] = 0;
722 }
723
724 if ($optionValue && !empty($groupValues)) {
725 $dbValues = explode(CRM_Core_DAO::VALUE_SEPARATOR,
726 substr($optionValue, 1, -1)
727 );
728
729 if (!empty($dbValues)) {
730 foreach ($groupValues as $key => $val) {
731 if (in_array($key, $dbValues)) {
732 $returnValues[$val] = 1;
733 if ($returnNameANDLabels) {
734 $nameAndLabels[$names[$key]] = $labels[$key];
735 }
736 }
737 }
738 }
739 }
740 return ($returnNameANDLabels) ? $nameAndLabels : $returnValues;
741 }
742
b5c2afd0
EM
743 /**
744 * @param $group
100fef9d 745 * @param string $name
b5c2afd0
EM
746 * @param $value
747 * @param bool $system
100fef9d 748 * @param int $userID
b5c2afd0
EM
749 * @param string $keyField
750 */
2da40d21 751 public static function setValueOption(
f9f40af3 752 $group,
6a488035
TO
753 $name,
754 $value,
242bd179
TO
755 $system = TRUE,
756 $userID = NULL,
6a488035
TO
757 $keyField = 'name'
758 ) {
759 if (empty($value)) {
760 $optionValue = NULL;
761 }
762 elseif (is_array($value)) {
763 $groupValues = CRM_Core_OptionGroup::values($name, FALSE, FALSE, FALSE, NULL, $keyField);
764
765 $cbValues = array();
766 foreach ($groupValues as $key => $val) {
a7488080 767 if (!empty($value[$val])) {
6a488035
TO
768 $cbValues[$key] = 1;
769 }
770 }
771
772 if (!empty($cbValues)) {
773 $optionValue = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR,
353ffa53
TO
774 array_keys($cbValues)
775 ) . CRM_Core_DAO::VALUE_SEPARATOR;
6a488035
TO
776 }
777 else {
778 $optionValue = NULL;
779 }
780 }
781 else {
782 $optionValue = $value;
783 }
784
785 self::setItem($optionValue, $group, $name);
786 }
787
6a488035
TO
788 /**
789 * Determine what, if any, overrides have been provided
790 * for a setting.
791 *
dd244018 792 * @param $group
100fef9d 793 * @param string $name
dd244018
EM
794 * @param $default
795 *
6a488035
TO
796 * @return mixed, NULL or an overriden value
797 */
798 protected static function getOverride($group, $name, $default) {
799 global $civicrm_setting;
800 if ($group && $name && isset($civicrm_setting[$group][$name])) {
801 return $civicrm_setting[$group][$name];
802 }
58f6c272 803 elseif ($group && !isset($name) && isset($civicrm_setting[$group])) {
bf83df95 804 return $civicrm_setting[$group];
805 }
6a488035
TO
806 else {
807 return $default;
808 }
809 }
6a488035 810
2c7039ef 811 /**
100fef9d 812 * Civicrm_setting didn't exist before 4.1.alpha1 and this function helps taking decisions during upgrade
2c7039ef 813 *
5c766a0b 814 * @return bool
2c7039ef 815 */
00be9182 816 public static function isUpgradeFromPreFourOneAlpha1() {
2c7039ef
DS
817 if (CRM_Core_Config::isUpgradeMode()) {
818 $currentVer = CRM_Core_BAO_Domain::version();
819 if (version_compare($currentVer, '4.1.alpha1') < 0) {
820 return TRUE;
821 }
822 }
823 return FALSE;
824 }
96025800 825
2c7039ef 826}