Merge pull request #23895 from colemanw/searchKitManaged
[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')) {
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 }
209 else {
210
211 // CRM-11993 - Use default when it's a single-language install.
212 $chosenLocale = $defaultLocale;
213
214 }
215
216 if (!$session->isEmpty()) {
217 // Always assign the chosen locale to the session.
218 $session->set('lcMessages', $chosenLocale);
219 }
220
221 /*
222 * Set suffix for table names in multi-language installs.
223 * Use views if more than one language.
224 */
225 $dbLocale = $multiLang && $chosenLocale ? "_{$chosenLocale}" : '';
226
227 // FIXME: an ugly hack to fix CRM-4041.
228 $tsLocale = $chosenLocale;
229
230 /*
231 * FIXME: as bad a place as any to fix CRM-5428.
232 * (to be moved to a sane location along with the above)
233 */
234 if (function_exists('mb_internal_encoding')) {
235 mb_internal_encoding('UTF-8');
236 }
237
238 }
239
240 /**
241 * @param array $defaultValues
242 *
243 * @return string
244 * @throws Exception
245 */
246 public static function doSiteMove($defaultValues = []) {
247 $moveStatus = ts('Beginning site move process...') . '<br />';
248 $settings = Civi::settings();
249
250 foreach (array_merge(self::getPathSettings(), self::getUrlSettings()) as $key) {
251 $value = $settings->get($key);
252 if ($value && $value != $settings->getDefault($key)) {
253 if ($settings->getMandatory($key) === NULL) {
254 $settings->revert($key);
255 $moveStatus .= ts("WARNING: The setting (%1) has been reverted.", [
256 1 => $key,
257 ]);
258 $moveStatus .= '<br />';
259 }
260 else {
261 $moveStatus .= ts("WARNING: The setting (%1) is overridden and could not be reverted.", [
262 1 => $key,
263 ]);
264 $moveStatus .= '<br />';
265 }
266 }
267 }
268
269 $config = CRM_Core_Config::singleton();
270
271 // clear the template_c and upload directory also
272 $config->cleanup(3, TRUE);
273 $moveStatus .= ts('Template cache and upload directory have been cleared.') . '<br />';
274
275 // clear all caches
276 CRM_Core_Config::clearDBCache();
277 Civi::cache('session')->clear();
278 $moveStatus .= ts('Database cache tables cleared.') . '<br />';
279
280 $resetSessionTable = CRM_Utils_Request::retrieve('resetSessionTable',
281 'Boolean',
282 CRM_Core_DAO::$_nullArray,
283 FALSE,
284 FALSE
285 );
286 if ($config->userSystem->is_drupal &&
287 $resetSessionTable
288 ) {
289 db_query("DELETE FROM {sessions} WHERE 1");
290 $moveStatus .= ts('Drupal session table cleared.') . '<br />';
291 }
292 else {
293 $session = CRM_Core_Session::singleton();
294 $session->reset(2);
295 $moveStatus .= ts('Session has been reset.') . '<br />';
296 }
297
298 return $moveStatus;
299 }
300
301 /**
302 * Takes a componentName and enables it in the config.
303 * Primarily used during unit testing
304 *
305 * @param string $componentName
306 * Name of the component to be enabled, needs to be valid.
307 *
308 * @return bool
309 * true if valid component name and enabling succeeds, else false
310 */
311 public static function enableComponent($componentName) {
312 $enabledComponents = Civi::settings()->get('enable_components');
313 if (in_array($componentName, $enabledComponents)) {
314 // component is already enabled
315 return TRUE;
316 }
317
318 // return if component does not exist
319 if (!array_key_exists($componentName, CRM_Core_Component::getComponents())) {
320 return FALSE;
321 }
322
323 // get enabled-components from DB and add to the list
324 $enabledComponents[] = $componentName;
325 self::setEnabledComponents($enabledComponents);
326
327 return TRUE;
328 }
329
330 /**
331 * Ensure all components are enabled
332 * @throws CRM_Core_Exception
333 */
334 public static function enableAllComponents() {
335 $allComponents = array_keys(CRM_Core_Component::getComponents());
336 if (Civi::settings()->get('enable_components') != $allComponents) {
337 self::setEnabledComponents($allComponents);
338 }
339 }
340
341 /**
342 * Disable specified component.
343 *
344 * @param string $componentName
345 *
346 * @return bool
347 */
348 public static function disableComponent($componentName) {
349 $config = CRM_Core_Config::singleton();
350 if (!in_array($componentName, $config->enableComponents) ||
351 !array_key_exists($componentName, CRM_Core_Component::getComponents())
352 ) {
353 // Post-condition is satisfied.
354 return TRUE;
355 }
356
357 // get enabled-components from DB and add to the list
358 $enabledComponents = Civi::settings()->get('enable_components');
359 $enabledComponents = array_diff($enabledComponents, [$componentName]);
360
361 self::setEnabledComponents($enabledComponents);
362
363 return TRUE;
364 }
365
366 /**
367 * Set enabled components.
368 *
369 * @param array $enabledComponents
370 */
371 public static function setEnabledComponents($enabledComponents) {
372 // The on_change trigger on this setting will trigger a cache flush
373 Civi::settings()->set('enable_components', $enabledComponents);
374 }
375
376 /**
377 * @return array
378 */
379 public static function skipVars() {
380 return [
381 'dsn',
382 'templateCompileDir',
383 'userFrameworkDSN',
384 'userFramework',
385 'userFrameworkBaseURL',
386 'userFrameworkClass',
387 'userHookClass',
388 'userPermissionClass',
389 'userPermissionTemp',
390 'userFrameworkURLVar',
391 'userFrameworkVersion',
392 'newBaseURL',
393 'newBaseDir',
394 'newSiteName',
395 'configAndLogDir',
396 'qfKey',
397 'gettextResourceDir',
398 'cleanURL',
399 'entryURL',
400 'locale_custom_strings',
401 'localeCustomStrings',
402 'autocompleteContactSearch',
403 'autocompleteContactReference',
404 'checksumTimeout',
405 'checksum_timeout',
406 ];
407 }
408
409 /**
410 * @param array $params
411 * @return array
412 */
413 public static function filterSkipVars($params) {
414 $skipVars = self::skipVars();
415 foreach ($skipVars as $var) {
416 unset($params[$var]);
417 }
418 foreach (array_keys($params) as $key) {
419 if (preg_match('/^_qf_/', $key)) {
420 unset($params[$key]);
421 }
422 }
423 return $params;
424 }
425
426 /**
427 * @return array
428 */
429 private static function getUrlSettings() {
430 return [
431 'userFrameworkResourceURL',
432 'imageUploadURL',
433 'customCSSURL',
434 'extensionsURL',
435 ];
436 }
437
438 /**
439 * @return array
440 */
441 private static function getPathSettings() {
442 return [
443 'uploadDir',
444 'imageUploadDir',
445 'customFileUploadDir',
446 'customTemplateDir',
447 'customPHPPathDir',
448 'extensionsDir',
449 ];
450 }
451
452 }