Merge pull request #16733 from eileenmcnaughton/smarty
[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 * Evaluate locale preferences and activate a chosen locale by
123 * updating session+global variables.
124 *
125 * @param \Civi\Core\SettingsBag $settings
126 * @param string $activatedLocales
127 * Imploded list of locales which are supported in the DB.
128 */
129 public static function applyLocale($settings, $activatedLocales) {
130 // are we in a multi-language setup?
131 $multiLang = (bool) $activatedLocales;
132
133 // set the current language
134 $chosenLocale = NULL;
135
136 $session = CRM_Core_Session::singleton();
137
138 $permittedLanguages = CRM_Core_I18n::uiLanguages(TRUE);
139
140 // The locale to be used can come from various places:
141 // - the request (url)
142 // - the session
143 // - civicrm_uf_match
144 // - inherited from the CMS
145 // Only look at this if there is actually a choice of permitted languages
146 if (count($permittedLanguages) >= 2) {
147 $requestLocale = CRM_Utils_Request::retrieve('lcMessages', 'String');
148 if (in_array($requestLocale, $permittedLanguages)) {
149 $chosenLocale = $requestLocale;
150
151 //CRM-8559, cache navigation do not respect locale if it is changed, so reseting cache.
152 // Ed: This doesn't sound good.
153 // Civi::cache('navigation')->flush();
154 }
155 else {
156 $requestLocale = NULL;
157 }
158
159 if (!$requestLocale) {
160 $sessionLocale = $session->get('lcMessages');
161 if (in_array($sessionLocale, $permittedLanguages)) {
162 $chosenLocale = $sessionLocale;
163 }
164 else {
165 $sessionLocale = NULL;
166 }
167 }
168
169 if ($requestLocale) {
170 $ufm = new CRM_Core_DAO_UFMatch();
171 $ufm->contact_id = $session->get('userID');
172 if ($ufm->find(TRUE)) {
173 $ufm->language = $chosenLocale;
174 $ufm->save();
175 }
176 $session->set('lcMessages', $chosenLocale);
177 }
178
179 if (!$chosenLocale and $session->get('userID')) {
180 $ufm = new CRM_Core_DAO_UFMatch();
181 $ufm->contact_id = $session->get('userID');
182 if ($ufm->find(TRUE) &&
183 in_array($ufm->language, $permittedLanguages)
184 ) {
185 $chosenLocale = $ufm->language;
186 }
187 $session->set('lcMessages', $chosenLocale);
188 }
189 }
190 global $dbLocale;
191
192 // try to inherit the language from the hosting CMS
193 if ($settings->get('inheritLocale')) {
194 // FIXME: On multilanguage installs, CRM_Utils_System::getUFLocale() in many cases returns nothing if $dbLocale is not set
195 $lcMessages = $settings->get('lcMessages');
196 $dbLocale = $multiLang && $lcMessages ? "_{$lcMessages}" : '';
197 $chosenLocale = CRM_Utils_System::getUFLocale();
198 if ($activatedLocales and !in_array($chosenLocale, explode(CRM_Core_DAO::VALUE_SEPARATOR, $activatedLocales))) {
199 $chosenLocale = NULL;
200 }
201 }
202
203 if (empty($chosenLocale)) {
204 //CRM-11993 - if a single-lang site, use default
205 $chosenLocale = $settings->get('lcMessages');
206 }
207
208 // set suffix for table names - use views if more than one language
209 $dbLocale = $multiLang && $chosenLocale ? "_{$chosenLocale}" : '';
210
211 // FIXME: an ugly hack to fix CRM-4041
212 global $tsLocale;
213 $tsLocale = $chosenLocale;
214
215 // FIXME: as bad aplace as any to fix CRM-5428
216 // (to be moved to a sane location along with the above)
217 if (function_exists('mb_internal_encoding')) {
218 mb_internal_encoding('UTF-8');
219 }
220 }
221
222 /**
223 * @param array $defaultValues
224 *
225 * @return string
226 * @throws Exception
227 */
228 public static function doSiteMove($defaultValues = []) {
229 $moveStatus = ts('Beginning site move process...') . '<br />';
230 $settings = Civi::settings();
231
232 foreach (array_merge(self::getPathSettings(), self::getUrlSettings()) as $key) {
233 $value = $settings->get($key);
234 if ($value && $value != $settings->getDefault($key)) {
235 if ($settings->getMandatory($key) === NULL) {
236 $settings->revert($key);
237 $moveStatus .= ts("WARNING: The setting (%1) has been reverted.", [
238 1 => $key,
239 ]);
240 $moveStatus .= '<br />';
241 }
242 else {
243 $moveStatus .= ts("WARNING: The setting (%1) is overridden and could not be reverted.", [
244 1 => $key,
245 ]);
246 $moveStatus .= '<br />';
247 }
248 }
249 }
250
251 $config = CRM_Core_Config::singleton();
252
253 // clear the template_c and upload directory also
254 $config->cleanup(3, TRUE);
255 $moveStatus .= ts('Template cache and upload directory have been cleared.') . '<br />';
256
257 // clear all caches
258 CRM_Core_Config::clearDBCache();
259 Civi::cache('session')->clear();
260 $moveStatus .= ts('Database cache tables cleared.') . '<br />';
261
262 $resetSessionTable = CRM_Utils_Request::retrieve('resetSessionTable',
263 'Boolean',
264 CRM_Core_DAO::$_nullArray,
265 FALSE,
266 FALSE
267 );
268 if ($config->userSystem->is_drupal &&
269 $resetSessionTable
270 ) {
271 db_query("DELETE FROM {sessions} WHERE 1");
272 $moveStatus .= ts('Drupal session table cleared.') . '<br />';
273 }
274 else {
275 $session = CRM_Core_Session::singleton();
276 $session->reset(2);
277 $moveStatus .= ts('Session has been reset.') . '<br />';
278 }
279
280 return $moveStatus;
281 }
282
283 /**
284 * Takes a componentName and enables it in the config.
285 * Primarily used during unit testing
286 *
287 * @param string $componentName
288 * Name of the component to be enabled, needs to be valid.
289 *
290 * @return bool
291 * true if valid component name and enabling succeeds, else false
292 */
293 public static function enableComponent($componentName) {
294 $config = CRM_Core_Config::singleton();
295 if (in_array($componentName, $config->enableComponents)) {
296 // component is already enabled
297 return TRUE;
298 }
299
300 // return if component does not exist
301 if (!array_key_exists($componentName, CRM_Core_Component::getComponents())) {
302 return FALSE;
303 }
304
305 // get enabled-components from DB and add to the list
306 $enabledComponents = Civi::settings()->get('enable_components');
307 $enabledComponents[] = $componentName;
308
309 self::setEnabledComponents($enabledComponents);
310
311 return TRUE;
312 }
313
314 /**
315 * Disable specified component.
316 *
317 * @param string $componentName
318 *
319 * @return bool
320 */
321 public static function disableComponent($componentName) {
322 $config = CRM_Core_Config::singleton();
323 if (!in_array($componentName, $config->enableComponents) ||
324 !array_key_exists($componentName, CRM_Core_Component::getComponents())
325 ) {
326 // Post-condition is satisfied.
327 return TRUE;
328 }
329
330 // get enabled-components from DB and add to the list
331 $enabledComponents = Civi::settings()->get('enable_components');
332 $enabledComponents = array_diff($enabledComponents, [$componentName]);
333
334 self::setEnabledComponents($enabledComponents);
335
336 return TRUE;
337 }
338
339 /**
340 * Set enabled components.
341 *
342 * @param array $enabledComponents
343 */
344 public static function setEnabledComponents($enabledComponents) {
345 // fix the config object. update db.
346 Civi::settings()->set('enable_components', $enabledComponents);
347
348 // also force reset of component array
349 CRM_Core_Component::getEnabledComponents(TRUE);
350 }
351
352 /**
353 * @return array
354 */
355 public static function skipVars() {
356 return [
357 'dsn',
358 'templateCompileDir',
359 'userFrameworkDSN',
360 'userFramework',
361 'userFrameworkBaseURL',
362 'userFrameworkClass',
363 'userHookClass',
364 'userPermissionClass',
365 'userPermissionTemp',
366 'userFrameworkURLVar',
367 'userFrameworkVersion',
368 'newBaseURL',
369 'newBaseDir',
370 'newSiteName',
371 'configAndLogDir',
372 'qfKey',
373 'gettextResourceDir',
374 'cleanURL',
375 'entryURL',
376 'locale_custom_strings',
377 'localeCustomStrings',
378 'autocompleteContactSearch',
379 'autocompleteContactReference',
380 'checksumTimeout',
381 'checksum_timeout',
382 ];
383 }
384
385 /**
386 * @param array $params
387 * @return array
388 */
389 public static function filterSkipVars($params) {
390 $skipVars = self::skipVars();
391 foreach ($skipVars as $var) {
392 unset($params[$var]);
393 }
394 foreach (array_keys($params) as $key) {
395 if (preg_match('/^_qf_/', $key)) {
396 unset($params[$key]);
397 }
398 }
399 return $params;
400 }
401
402 /**
403 * @return array
404 */
405 private static function getUrlSettings() {
406 return [
407 'userFrameworkResourceURL',
408 'imageUploadURL',
409 'customCSSURL',
410 'extensionsURL',
411 ];
412 }
413
414 /**
415 * @return array
416 */
417 private static function getPathSettings() {
418 return [
419 'uploadDir',
420 'imageUploadDir',
421 'customFileUploadDir',
422 'customTemplateDir',
423 'customPHPPathDir',
424 'extensionsDir',
425 ];
426 }
427
428 }