Merge pull request #17919 from seamuslee001/nfc_locale_documentation
[civicrm-core.git] / CRM / Core / BAO / ConfigSetting.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 *
15 * @package CRM
16 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 */
18
19 /**
20 * File contains functions used in civicrm configuration.
21 */
22 class CRM_Core_BAO_ConfigSetting {
23
24 /**
25 * Create civicrm settings. This is the same as add but it clears the cache and
26 * reloads the config object
27 *
28 * @param array $params
29 * Associated array of civicrm variables.
30 */
31 public static function create($params) {
32 self::add($params);
33 $cache = CRM_Utils_Cache::singleton();
34 $cache->delete('CRM_Core_Config');
35 $cache->delete('CRM_Core_Config' . CRM_Core_Config::domainID());
36 $config = CRM_Core_Config::singleton(TRUE, TRUE);
37 }
38
39 /**
40 * Add civicrm settings.
41 *
42 * @param array $params
43 * Associated array of civicrm variables.
44 * @deprecated
45 * This method was historically used to access civicrm_domain.config_backend.
46 * However, that has been fully replaced by the settings system since v4.7.
47 */
48 public static function add(&$params) {
49 $domain = new CRM_Core_DAO_Domain();
50 $domain->id = CRM_Core_Config::domainID();
51 $domain->find(TRUE);
52 if ($domain->config_backend) {
53 $params = array_merge(unserialize($domain->config_backend), $params);
54 }
55
56 $params = CRM_Core_BAO_ConfigSetting::filterSkipVars($params);
57
58 // also skip all Dir Params, we dont need to store those in the DB!
59 foreach ($params as $name => $val) {
60 if (substr($name, -3) == 'Dir') {
61 unset($params[$name]);
62 }
63 }
64
65 $domain->config_backend = serialize($params);
66 $domain->save();
67 }
68
69 /**
70 * Retrieve the settings values from db.
71 *
72 * @param $defaults
73 *
74 * @return array
75 * @deprecated
76 * This method was historically used to access civicrm_domain.config_backend.
77 * However, that has been fully replaced by the settings system since v4.7.
78 */
79 public static function retrieve(&$defaults) {
80 $domain = new CRM_Core_DAO_Domain();
81 $isUpgrade = CRM_Core_Config::isUpgradeMode();
82
83 //we are initializing config, really can't use, CRM-7863
84 $urlVar = 'q';
85 if (defined('CIVICRM_UF') && CIVICRM_UF == 'Joomla') {
86 $urlVar = 'task';
87 }
88
89 $hasBackend = CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_domain', 'config_backend');
90 if ($isUpgrade && $hasBackend) {
91 $domain->selectAdd('config_backend');
92 }
93 else {
94 $domain->selectAdd('locales');
95 }
96
97 $domain->id = CRM_Core_Config::domainID();
98 $domain->find(TRUE);
99 if ($hasBackend && $domain->config_backend) {
100 // This whole branch can probably be removed; the transitional loading
101 // is in SettingBag::loadValues(). Moreover, since 4.7.alpha1 dropped
102 // the column, anyone calling ::retrieve() has likely not gotten any data.
103 $defaults = unserialize($domain->config_backend);
104 if ($defaults === FALSE || !is_array($defaults)) {
105 $defaults = [];
106 return FALSE;
107 }
108
109 $skipVars = self::skipVars();
110 foreach ($skipVars as $skip) {
111 if (array_key_exists($skip, $defaults)) {
112 unset($defaults[$skip]);
113 }
114 }
115 }
116 if (!$isUpgrade) {
117 CRM_Core_BAO_ConfigSetting::applyLocale(Civi::settings($domain->id), $domain->locales);
118 }
119 }
120
121 /**
122 * Activate a chosen locale.
123 *
124 * The locale is set by updating the session and global variables.
125 *
126 * When there is a choice of permitted languages (set on the "Administer" ->
127 * "Localisation" -> "Languages, Currency, Locations" screen) the locale to
128 * be applied can come from a variety of sources. The list below is the order
129 * of priority for deciding which of the sources "wins":
130 *
131 * - The request - when the "lcMessages" query variable is present in the URL.
132 * - The session - when the "lcMessages" session variable has been set.
133 * - Inherited from the CMS - when the "inheritLocale" setting is set.
134 * - CiviCRM settings - the fallback when none of the above set the locale.
135 *
136 * Single-language installs skip this and always set the default locale.
137 *
138 * @param \Civi\Core\SettingsBag $settings
139 * @param string $activatedLocales
140 * Imploded list of locales which are supported in the DB.
141 */
142 public static function applyLocale($settings, $activatedLocales) {
143
144 // Declare access to locale globals.
145 global $dbLocale, $tsLocale;
146
147 // Grab session reference.
148 $session = CRM_Core_Session::singleton();
149
150 // Set flag for multi-language setup.
151 $multiLang = (bool) $activatedLocales;
152
153 // Initialise the default and chosen locales.
154 $defaultLocale = $settings->get('lcMessages');
155 $chosenLocale = NULL;
156
157 // When there is a choice of permitted languages.
158 $permittedLanguages = CRM_Core_I18n::uiLanguages(TRUE);
159 if (count($permittedLanguages) >= 2) {
160
161 // Is the "lcMessages" query variable present in the URL?
162 $requestLocale = CRM_Utils_Request::retrieve('lcMessages', 'String');
163 if (in_array($requestLocale, $permittedLanguages)) {
164 $chosenLocale = $requestLocale;
165 }
166
167 // Check the session if the chosen locale hasn't been set yet.
168 if (empty($chosenLocale)) {
169 $sessionLocale = $session->get('lcMessages');
170 if (in_array($sessionLocale, $permittedLanguages)) {
171 $chosenLocale = $sessionLocale;
172 }
173 }
174
175 /*
176 * Maybe inherit the language from the CMS.
177 *
178 * If the language is specified via "lcMessages" we skip this, since the
179 * intention of the URL query var is to override all other sources.
180 */
181 if ($settings->get('inheritLocale') && empty($chosenLocale)) {
182
183 /*
184 * FIXME: On multi-language installs, CRM_Utils_System::getUFLocale() in
185 * many cases returns nothing if $dbLocale is not set, so set it to the
186 * default - even if it's overridden later.
187 */
188 $dbLocale = $multiLang && $defaultLocale ? "_{$defaultLocale}" : '';
189
190 // Retrieve locale as reported by CMS.
191 $cmsLocale = CRM_Utils_System::getUFLocale();
192 if (in_array($cmsLocale, $permittedLanguages)) {
193 $chosenLocale = $cmsLocale;
194 }
195
196 // Clear chosen locale if not activated in multi-language CiviCRM.
197 if ($activatedLocales && !in_array($chosenLocale, explode(CRM_Core_DAO::VALUE_SEPARATOR, $activatedLocales))) {
198 $chosenLocale = NULL;
199 }
200
201 }
202
203 // Assign the system default if the chosen locale hasn't been set.
204 if (empty($chosenLocale)) {
205 $chosenLocale = $defaultLocale;
206 }
207
208 // Always assign the chosen locale to the session.
209 $session->set('lcMessages', $chosenLocale);
210
211 }
212 else {
213
214 // CRM-11993 - Use default when it's a single-language install.
215 $chosenLocale = $defaultLocale;
216
217 }
218
219 /*
220 * Set suffix for table names in multi-language installs.
221 * Use views if more than one language.
222 */
223 $dbLocale = $multiLang && $chosenLocale ? "_{$chosenLocale}" : '';
224
225 // FIXME: an ugly hack to fix CRM-4041.
226 $tsLocale = $chosenLocale;
227
228 /*
229 * FIXME: as bad a place as any to fix CRM-5428.
230 * (to be moved to a sane location along with the above)
231 */
232 if (function_exists('mb_internal_encoding')) {
233 mb_internal_encoding('UTF-8');
234 }
235
236 }
237
238 /**
239 * @param array $defaultValues
240 *
241 * @return string
242 * @throws Exception
243 */
244 public static function doSiteMove($defaultValues = []) {
245 $moveStatus = ts('Beginning site move process...') . '<br />';
246 $settings = Civi::settings();
247
248 foreach (array_merge(self::getPathSettings(), self::getUrlSettings()) as $key) {
249 $value = $settings->get($key);
250 if ($value && $value != $settings->getDefault($key)) {
251 if ($settings->getMandatory($key) === NULL) {
252 $settings->revert($key);
253 $moveStatus .= ts("WARNING: The setting (%1) has been reverted.", [
254 1 => $key,
255 ]);
256 $moveStatus .= '<br />';
257 }
258 else {
259 $moveStatus .= ts("WARNING: The setting (%1) is overridden and could not be reverted.", [
260 1 => $key,
261 ]);
262 $moveStatus .= '<br />';
263 }
264 }
265 }
266
267 $config = CRM_Core_Config::singleton();
268
269 // clear the template_c and upload directory also
270 $config->cleanup(3, TRUE);
271 $moveStatus .= ts('Template cache and upload directory have been cleared.') . '<br />';
272
273 // clear all caches
274 CRM_Core_Config::clearDBCache();
275 Civi::cache('session')->clear();
276 $moveStatus .= ts('Database cache tables cleared.') . '<br />';
277
278 $resetSessionTable = CRM_Utils_Request::retrieve('resetSessionTable',
279 'Boolean',
280 CRM_Core_DAO::$_nullArray,
281 FALSE,
282 FALSE
283 );
284 if ($config->userSystem->is_drupal &&
285 $resetSessionTable
286 ) {
287 db_query("DELETE FROM {sessions} WHERE 1");
288 $moveStatus .= ts('Drupal session table cleared.') . '<br />';
289 }
290 else {
291 $session = CRM_Core_Session::singleton();
292 $session->reset(2);
293 $moveStatus .= ts('Session has been reset.') . '<br />';
294 }
295
296 return $moveStatus;
297 }
298
299 /**
300 * Takes a componentName and enables it in the config.
301 * Primarily used during unit testing
302 *
303 * @param string $componentName
304 * Name of the component to be enabled, needs to be valid.
305 *
306 * @return bool
307 * true if valid component name and enabling succeeds, else false
308 */
309 public static function enableComponent($componentName) {
310 $config = CRM_Core_Config::singleton();
311 if (in_array($componentName, $config->enableComponents)) {
312 // component is already enabled
313 return TRUE;
314 }
315
316 // return if component does not exist
317 if (!array_key_exists($componentName, CRM_Core_Component::getComponents())) {
318 return FALSE;
319 }
320
321 // get enabled-components from DB and add to the list
322 $enabledComponents = Civi::settings()->get('enable_components');
323 $enabledComponents[] = $componentName;
324
325 self::setEnabledComponents($enabledComponents);
326
327 return TRUE;
328 }
329
330 /**
331 * Disable specified component.
332 *
333 * @param string $componentName
334 *
335 * @return bool
336 */
337 public static function disableComponent($componentName) {
338 $config = CRM_Core_Config::singleton();
339 if (!in_array($componentName, $config->enableComponents) ||
340 !array_key_exists($componentName, CRM_Core_Component::getComponents())
341 ) {
342 // Post-condition is satisfied.
343 return TRUE;
344 }
345
346 // get enabled-components from DB and add to the list
347 $enabledComponents = Civi::settings()->get('enable_components');
348 $enabledComponents = array_diff($enabledComponents, [$componentName]);
349
350 self::setEnabledComponents($enabledComponents);
351
352 return TRUE;
353 }
354
355 /**
356 * Set enabled components.
357 *
358 * @param array $enabledComponents
359 */
360 public static function setEnabledComponents($enabledComponents) {
361 // fix the config object. update db.
362 Civi::settings()->set('enable_components', $enabledComponents);
363
364 // also force reset of component array
365 CRM_Core_Component::getEnabledComponents(TRUE);
366 }
367
368 /**
369 * @return array
370 */
371 public static function skipVars() {
372 return [
373 'dsn',
374 'templateCompileDir',
375 'userFrameworkDSN',
376 'userFramework',
377 'userFrameworkBaseURL',
378 'userFrameworkClass',
379 'userHookClass',
380 'userPermissionClass',
381 'userPermissionTemp',
382 'userFrameworkURLVar',
383 'userFrameworkVersion',
384 'newBaseURL',
385 'newBaseDir',
386 'newSiteName',
387 'configAndLogDir',
388 'qfKey',
389 'gettextResourceDir',
390 'cleanURL',
391 'entryURL',
392 'locale_custom_strings',
393 'localeCustomStrings',
394 'autocompleteContactSearch',
395 'autocompleteContactReference',
396 'checksumTimeout',
397 'checksum_timeout',
398 ];
399 }
400
401 /**
402 * @param array $params
403 * @return array
404 */
405 public static function filterSkipVars($params) {
406 $skipVars = self::skipVars();
407 foreach ($skipVars as $var) {
408 unset($params[$var]);
409 }
410 foreach (array_keys($params) as $key) {
411 if (preg_match('/^_qf_/', $key)) {
412 unset($params[$key]);
413 }
414 }
415 return $params;
416 }
417
418 /**
419 * @return array
420 */
421 private static function getUrlSettings() {
422 return [
423 'userFrameworkResourceURL',
424 'imageUploadURL',
425 'customCSSURL',
426 'extensionsURL',
427 ];
428 }
429
430 /**
431 * @return array
432 */
433 private static function getPathSettings() {
434 return [
435 'uploadDir',
436 'imageUploadDir',
437 'customFileUploadDir',
438 'customTemplateDir',
439 'customPHPPathDir',
440 'extensionsDir',
441 ];
442 }
443
444 }