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