code cleanup
[civicrm-core.git] / CRM / Core / BAO / ConfigSetting.php
... / ...
CommitLineData
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
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-2014
33 * $Id$
34 *
35 */
36
37/**
38 * file contains functions used in civicrm configuration
39 *
40 */
41class CRM_Core_BAO_ConfigSetting {
42
43 /**
44 * Create civicrm settings. This is the same as add but it clears the cache and
45 * reloads the config object
46 *
47 * @param array $params
48 * Associated array of civicrm variables.
49 *
50 * @return void
51 */
52 public static function create($params) {
53 self::add($params);
54 $cache = CRM_Utils_Cache::singleton();
55 $cache->delete('CRM_Core_Config');
56 $cache->delete('CRM_Core_Config' . CRM_Core_Config::domainID());
57 $config = CRM_Core_Config::singleton(TRUE, TRUE);
58 }
59
60 /**
61 * Add civicrm settings
62 *
63 * @param array $params
64 * Associated array of civicrm variables.
65 *
66 * @return void
67 */
68 public static function add(&$params) {
69 self::fixParams($params);
70
71 // also set a template url so js files can use this
72 // CRM-6194
73 $params['civiRelativeURL'] = CRM_Utils_System::url('CIVI_BASE_TEMPLATE');
74 $params['civiRelativeURL']
75 = str_replace(
76 'CIVI_BASE_TEMPLATE',
77 '',
78 $params['civiRelativeURL']
79 );
80
81 // also add the version number for use by template / js etc
82 $params['civiVersion'] = CRM_Utils_System::version();
83
84 $domain = new CRM_Core_DAO_Domain();
85 $domain->id = CRM_Core_Config::domainID();
86 $domain->find(TRUE);
87 if ($domain->config_backend) {
88 $values = unserialize($domain->config_backend);
89 self::formatParams($params, $values);
90 }
91
92 // CRM-6151
93 if (isset($params['localeCustomStrings']) &&
94 is_array($params['localeCustomStrings'])
95 ) {
96 $domain->locale_custom_strings = serialize($params['localeCustomStrings']);
97 }
98
99 // unset any of the variables we read from file that should not be stored in the database
100 // the username and certpath are stored flat with _test and _live
101 // check CRM-1470
102 $skipVars = self::skipVars();
103 foreach ($skipVars as $var) {
104 unset($params[$var]);
105 }
106
107 CRM_Core_BAO_Setting::fixAndStoreDirAndURL($params);
108
109 // also skip all Dir Params, we dont need to store those in the DB!
110 foreach ($params as $name => $val) {
111 if (substr($name, -3) == 'Dir') {
112 unset($params[$name]);
113 }
114 }
115
116 //keep user preferred language upto date, CRM-7746
117 $session = CRM_Core_Session::singleton();
118 $lcMessages = CRM_Utils_Array::value('lcMessages', $params);
119 if ($lcMessages && $session->get('userID')) {
120 $languageLimit = CRM_Utils_Array::value('languageLimit', $params);
121 if (is_array($languageLimit) &&
122 !in_array($lcMessages, array_keys($languageLimit))
123 ) {
124 $lcMessages = $session->get('lcMessages');
125 }
126
127 $ufm = new CRM_Core_DAO_UFMatch();
128 $ufm->contact_id = $session->get('userID');
129 if ($lcMessages && $ufm->find(TRUE)) {
130 $ufm->language = $lcMessages;
131 $ufm->save();
132 $session->set('lcMessages', $lcMessages);
133 $params['lcMessages'] = $lcMessages;
134 }
135 }
136
137 $domain->config_backend = serialize($params);
138 $domain->save();
139 }
140
141 /**
142 * Fix civicrm setting variables
143 *
144 * @param array $params
145 * Associated array of civicrm variables.
146 *
147 * @return void
148 */
149 public static function fixParams(&$params) {
150 // in our old civicrm.settings.php we were using ISO code for country and
151 // province limit, now we have changed it to use ids
152
153 $countryIsoCodes = CRM_Core_PseudoConstant::countryIsoCode();
154
155 $specialArray = array('countryLimit', 'provinceLimit');
156
157 foreach ($params as $key => $value) {
158 if (in_array($key, $specialArray) && is_array($value)) {
159 foreach ($value as $k => $val) {
160 if (!is_numeric($val)) {
161 $params[$key][$k] = array_search($val, $countryIsoCodes);
162 }
163 }
164 }
165 elseif ($key == 'defaultContactCountry') {
166 if (!is_numeric($value)) {
167 $params[$key] = array_search($value, $countryIsoCodes);
168 }
169 }
170 }
171 }
172
173 /**
174 * Format the array containing before inserting in db
175 *
176 * @param array $params
177 * Associated array of civicrm variables(submitted).
178 * @param array $values
179 * Associated array of civicrm variables stored in db.
180 *
181 * @return void
182 */
183 public static function formatParams(&$params, &$values) {
184 if (empty($params) ||
185 !is_array($params)
186 ) {
187 $params = $values;
188 }
189 else {
190 foreach ($params as $key => $val) {
191 if (array_key_exists($key, $values)) {
192 unset($values[$key]);
193 }
194 }
195 $params = array_merge($params, $values);
196 }
197 }
198
199 /**
200 * Retrieve the settings values from db
201 *
202 * @param $defaults
203 *
204 * @return array
205 */
206 public static function retrieve(&$defaults) {
207 $domain = new CRM_Core_DAO_Domain();
208
209 //we are initializing config, really can't use, CRM-7863
210 $urlVar = 'q';
211 if (defined('CIVICRM_UF') && CIVICRM_UF == 'Joomla') {
212 $urlVar = 'task';
213 }
214
215 if (CRM_Core_Config::isUpgradeMode()) {
216 $domain->selectAdd('config_backend');
217 }
218 elseif (CRM_Utils_Array::value($urlVar, $_GET) == 'admin/modules/list/confirm') {
219 $domain->selectAdd('config_backend', 'locales');
220 }
221 else {
222 $domain->selectAdd('config_backend, locales, locale_custom_strings');
223 }
224
225 $domain->id = CRM_Core_Config::domainID();
226 $domain->find(TRUE);
227 if ($domain->config_backend) {
228 $defaults = unserialize($domain->config_backend);
229 if ($defaults === FALSE || !is_array($defaults)) {
230 $defaults = array();
231 return FALSE;
232 }
233
234 $skipVars = self::skipVars();
235 foreach ($skipVars as $skip) {
236 if (array_key_exists($skip, $defaults)) {
237 unset($defaults[$skip]);
238 }
239 }
240
241 // check if there are any locale strings
242 if ($domain->locale_custom_strings) {
243 $defaults['localeCustomStrings'] = unserialize($domain->locale_custom_strings);
244 }
245 else {
246 $defaults['localeCustomStrings'] = NULL;
247 }
248
249 // are we in a multi-language setup?
250 $multiLang = $domain->locales ? TRUE : FALSE;
251
252 // set the current language
253 $lcMessages = NULL;
254
255 $session = CRM_Core_Session::singleton();
256
257 // on multi-lang sites based on request and civicrm_uf_match
258 if ($multiLang) {
259 $lcMessagesRequest = CRM_Utils_Request::retrieve('lcMessages', 'String', $this);
260 $languageLimit = array();
261 if (array_key_exists('languageLimit', $defaults) && is_array($defaults['languageLimit'])) {
262 $languageLimit = $defaults['languageLimit'];
263 }
264
265 if (in_array($lcMessagesRequest, array_keys($languageLimit))) {
266 $lcMessages = $lcMessagesRequest;
267
268 //CRM-8559, cache navigation do not respect locale if it is changed, so reseting cache.
269 CRM_Core_BAO_Cache::deleteGroup('navigation');
270 }
271 else {
272 $lcMessagesRequest = NULL;
273 }
274
275 if (!$lcMessagesRequest) {
276 $lcMessagesSession = $session->get('lcMessages');
277 if (in_array($lcMessagesSession, array_keys($languageLimit))) {
278 $lcMessages = $lcMessagesSession;
279 }
280 else {
281 $lcMessagesSession = NULL;
282 }
283 }
284
285 if ($lcMessagesRequest) {
286 $ufm = new CRM_Core_DAO_UFMatch();
287 $ufm->contact_id = $session->get('userID');
288 if ($ufm->find(TRUE)) {
289 $ufm->language = $lcMessages;
290 $ufm->save();
291 }
292 $session->set('lcMessages', $lcMessages);
293 }
294
295 if (!$lcMessages and $session->get('userID')) {
296 $ufm = new CRM_Core_DAO_UFMatch();
297 $ufm->contact_id = $session->get('userID');
298 if ($ufm->find(TRUE) &&
299 in_array($ufm->language, array_keys($languageLimit))
300 ) {
301 $lcMessages = $ufm->language;
302 }
303 $session->set('lcMessages', $lcMessages);
304 }
305 }
306 global $dbLocale;
307
308 // try to inherit the language from the hosting CMS
309 if (!empty($defaults['inheritLocale'])) {
310 // FIXME: On multilanguage installs, CRM_Utils_System::getUFLocale() in many cases returns nothing if $dbLocale is not set
311 $dbLocale = $multiLang ? "_{$defaults['lcMessages']}" : '';
312 $lcMessages = CRM_Utils_System::getUFLocale();
313 if ($domain->locales and !in_array($lcMessages, explode(CRM_Core_DAO::VALUE_SEPARATOR,
314 $domain->locales
315 ))
316 ) {
317 $lcMessages = NULL;
318 }
319 }
320
321 if (empty($lcMessages)) {
322 //CRM-11993 - if a single-lang site, use default
323 $lcMessages = CRM_Utils_Array::value('lcMessages', $defaults);
324 }
325
326 // set suffix for table names - use views if more than one language
327 $dbLocale = $multiLang ? "_{$lcMessages}" : '';
328
329 // FIXME: an ugly hack to fix CRM-4041
330 global $tsLocale;
331 $tsLocale = $lcMessages;
332
333 // FIXME: as bad aplace as any to fix CRM-5428
334 // (to be moved to a sane location along with the above)
335 if (function_exists('mb_internal_encoding')) {
336 mb_internal_encoding('UTF-8');
337 }
338 }
339
340 // dont add if its empty
341 if (!empty($defaults)) {
342 // retrieve directory and url preferences also
343 CRM_Core_BAO_Setting::retrieveDirectoryAndURLPreferences($defaults);
344
345 // Pickup enabled-components from settings table if found.
346 $enableComponents = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'enable_components', NULL, array());
347 if (!empty($enableComponents)) {
348 $defaults['enableComponents'] = $enableComponents;
349
350 $components = CRM_Core_Component::getComponents();
351 $enabledComponentIDs = array();
352 foreach ($defaults['enableComponents'] as $name) {
353 $enabledComponentIDs[] = $components[$name]->componentID;
354 }
355 $defaults['enableComponentIDs'] = $enabledComponentIDs;
356 }
357 }
358 }
359
360 /**
361 * @return array
362 */
363 public static function getConfigSettings() {
364 $config = CRM_Core_Config::singleton();
365
366 $url = $dir = $siteName = $siteRoot = NULL;
367 if ($config->userFramework == 'Joomla') {
368 $url = preg_replace(
369 '|administrator/components/com_civicrm/civicrm/|',
370 '',
371 $config->userFrameworkResourceURL
372 );
373
374 // lets use imageUploadDir since we dont mess around with its values
375 // in the config object, lets kep it a bit generic since folks
376 // might have different values etc
377
378 //CRM-15365 - Fix preg_replace to handle backslash for Windows File Paths
379 if (DIRECTORY_SEPARATOR == '\\') {
380 $dir = preg_replace(
381 '|civicrm[/\\\\]templates_c[/\\\\].*$|',
382 '',
383 $config->templateCompileDir
384 );
385 }
386 else {
387 $dir = preg_replace(
388 '|civicrm/templates_c/.*$|',
389 '',
390 $config->templateCompileDir
391 );
392 }
393
394 $siteRoot = preg_replace(
395 '|/media/civicrm/.*$|',
396 '',
397 $config->imageUploadDir
398 );
399 }
400 elseif ($config->userFramework == 'WordPress') {
401 $url = preg_replace(
402 '|wp-content/plugins/civicrm/civicrm/|',
403 '',
404 $config->userFrameworkResourceURL
405 );
406
407 // lets use imageUploadDir since we dont mess around with its values
408 // in the config object, lets kep it a bit generic since folks
409 // might have different values etc
410
411 //CRM-15365 - Fix preg_replace to handle backslash for Windows File Paths
412 if (DIRECTORY_SEPARATOR == '\\') {
413 $dir = preg_replace(
414 '|civicrm[/\\\\]templates_c[/\\\\].*$|',
415 '',
416 $config->templateCompileDir
417 );
418 }
419 else {
420 $dir = preg_replace(
421 '|civicrm/templates_c/.*$|',
422 '',
423 $config->templateCompileDir
424 );
425 }
426
427 $siteRoot = preg_replace(
428 '|/wp-content/plugins/files/civicrm/.*$|',
429 '',
430 $config->imageUploadDir
431 );
432 }
433 else {
434 $url = preg_replace(
435 '|sites/[\w\.\-\_]+/modules/civicrm/|',
436 '',
437 $config->userFrameworkResourceURL
438 );
439
440 // lets use imageUploadDir since we dont mess around with its values
441 // in the config object, lets kep it a bit generic since folks
442 // might have different values etc
443
444 //CRM-15365 - Fix preg_replace to handle backslash for Windows File Paths
445 if (DIRECTORY_SEPARATOR == '\\') {
446 $dir = preg_replace(
447 '|[/\\\\]files[/\\\\]civicrm[/\\\\].*$|',
448 '\\\\files\\\\',
449 $config->imageUploadDir
450 );
451 }
452 else {
453 $dir = preg_replace(
454 '|/files/civicrm/.*$|',
455 '/files/',
456 $config->imageUploadDir
457 );
458 }
459
460 $matches = array();
461 if (preg_match(
462 '|/sites/([\w\.\-\_]+)/|',
463 $config->imageUploadDir,
464 $matches
465 )) {
466 $siteName = $matches[1];
467 if ($siteName) {
468 $siteName = "/sites/$siteName/";
469 $siteNamePos = strpos($dir, $siteName);
470 if ($siteNamePos !== FALSE) {
471 $siteRoot = substr($dir, 0, $siteNamePos);
472 }
473 }
474 }
475 }
476
477 return array($url, $dir, $siteName, $siteRoot);
478 }
479
480 /**
481 * Return likely default settings
482 * @return array
483 * site settings
484 * - $url
485 * - $dir Base Directory
486 * - $siteName
487 * - $siteRoot
488 */
489 public static function getBestGuessSettings() {
490 $config = CRM_Core_Config::singleton();
491
492 //CRM-15365 - Fix preg_replace to handle backslash for Windows File Paths
493 if (DIRECTORY_SEPARATOR == '\\') {
494 $needle = 'civicrm[/\\\\]templates_c[/\\\\].*$';
495 }
496 else {
497 $needle = 'civicrm/templates_c/.*$';
498 }
499
500 $dir = preg_replace(
501 "|$needle|",
502 '',
503 $config->templateCompileDir
504 );
505
506 list($url, $siteName, $siteRoot) = $config->userSystem->getDefaultSiteSettings($dir);
507 return array($url, $dir, $siteName, $siteRoot);
508 }
509
510 /**
511 * @param array $defaultValues
512 *
513 * @return string
514 * @throws Exception
515 */
516 public static function doSiteMove($defaultValues = array()) {
517 $moveStatus = ts('Beginning site move process...') . '<br />';
518 // get the current and guessed values
519 list($oldURL, $oldDir, $oldSiteName, $oldSiteRoot) = self::getConfigSettings();
520 list($newURL, $newDir, $newSiteName, $newSiteRoot) = self::getBestGuessSettings();
521
522 // retrieve these values from the argument list
523 $variables = array('URL', 'Dir', 'SiteName', 'SiteRoot', 'Val_1', 'Val_2', 'Val_3');
524 $states = array('old', 'new');
525 foreach ($variables as $varSuffix) {
526 foreach ($states as $state) {
527 $var = "{$state}{$varSuffix}";
528 if (!isset($$var)) {
529 if (isset($defaultValues[$var])) {
530 $$var = $defaultValues[$var];
531 }
532 else {
533 $$var = NULL;
534 }
535 }
536 $$var = CRM_Utils_Request::retrieve($var,
537 'String',
538 CRM_Core_DAO::$_nullArray,
539 FALSE,
540 $$var,
541 'REQUEST'
542 );
543 }
544 }
545
546 $from = $to = array();
547 foreach ($variables as $varSuffix) {
548 $oldVar = "old{$varSuffix}";
549 $newVar = "new{$varSuffix}";
550 //skip it if either is empty or both are exactly the same
551 if ($$oldVar &&
552 $$newVar &&
553 $$oldVar != $$newVar
554 ) {
555 $from[] = $$oldVar;
556 $to[] = $$newVar;
557 }
558 }
559
560 $sql = "
561SELECT config_backend
562FROM civicrm_domain
563WHERE id = %1
564";
565 $params = array(1 => array(CRM_Core_Config::domainID(), 'Integer'));
566 $configBackend = CRM_Core_DAO::singleValueQuery($sql, $params);
567 if (!$configBackend) {
568 CRM_Core_Error::fatal(ts('Returning early due to unexpected error - civicrm_domain.config_backend column value is NULL. Try visiting CiviCRM Home page.'));
569 }
570 $configBackend = unserialize($configBackend);
571
572 $configBackend = str_replace($from,
573 $to,
574 $configBackend
575 );
576
577 $configBackend = serialize($configBackend);
578 $sql = "
579UPDATE civicrm_domain
580SET config_backend = %2
581WHERE id = %1
582";
583 $params[2] = array($configBackend, 'String');
584 CRM_Core_DAO::executeQuery($sql, $params);
585
586 // Apply the changes to civicrm_option_values
587 $optionGroups = array('url_preferences', 'directory_preferences');
588 foreach ($optionGroups as $option) {
589 foreach ($variables as $varSuffix) {
590 $oldVar = "old{$varSuffix}";
591 $newVar = "new{$varSuffix}";
592
593 $from = $$oldVar;
594 $to = $$newVar;
595
596 if ($from && $to && $from != $to) {
597 $sql = '
598UPDATE civicrm_option_value
599SET value = REPLACE(value, %1, %2)
600WHERE option_group_id = (
601 SELECT id
602 FROM civicrm_option_group
603 WHERE name = %3 )
604';
605 $params = array(
606 1 => array($from, 'String'),
607 2 => array($to, 'String'),
608 3 => array($option, 'String'),
609 );
610 CRM_Core_DAO::executeQuery($sql, $params);
611 }
612 }
613 }
614
615 $moveStatus .=
616 ts('Directory and Resource URLs have been updated in the moved database to reflect current site location.') .
617 '<br />';
618
619 $config = CRM_Core_Config::singleton();
620
621 // clear the template_c and upload directory also
622 $config->cleanup(3, TRUE);
623 $moveStatus .= ts('Template cache and upload directory have been cleared.') . '<br />';
624
625 // clear all caches
626 CRM_Core_Config::clearDBCache();
627 $moveStatus .= ts('Database cache tables cleared.') . '<br />';
628
629 $resetSessionTable = CRM_Utils_Request::retrieve('resetSessionTable',
630 'Boolean',
631 CRM_Core_DAO::$_nullArray,
632 FALSE,
633 FALSE,
634 'REQUEST'
635 );
636 if ($config->userSystem->is_drupal &&
637 $resetSessionTable
638 ) {
639 db_query("DELETE FROM {sessions} WHERE 1");
640 $moveStatus .= ts('Drupal session table cleared.') . '<br />';
641 }
642 else {
643 $session = CRM_Core_Session::singleton();
644 $session->reset(2);
645 $moveStatus .= ts('Session has been reset.') . '<br />';
646 }
647
648 return $moveStatus;
649 }
650
651 /**
652 * Takes a componentName and enables it in the config
653 * Primarily used during unit testing
654 *
655 * @param string $componentName
656 * Name of the component to be enabled, needs to be valid.
657 *
658 * @return bool
659 * true if valid component name and enabling succeeds, else false
660 */
661 public static function enableComponent($componentName) {
662 $config = CRM_Core_Config::singleton();
663 if (in_array($componentName, $config->enableComponents)) {
664 // component is already enabled
665 return TRUE;
666 }
667
668 // return if component does not exist
669 if (!array_key_exists($componentName, CRM_Core_Component::getComponents())) {
670 return FALSE;
671 }
672
673 // get enabled-components from DB and add to the list
674 $enabledComponents
675 = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'enable_components', NULL, array());
676 $enabledComponents[] = $componentName;
677
678 self::setEnabledComponents($enabledComponents);
679
680 return TRUE;
681 }
682
683 public static function disableComponent($componentName) {
684 $config = CRM_Core_Config::singleton();
685 if (!in_array($componentName, $config->enableComponents) ||
686 !array_key_exists($componentName, CRM_Core_Component::getComponents())
687 ) {
688 // post-condition satisified
689 return TRUE;
690 }
691
692 // get enabled-components from DB and add to the list
693 $enabledComponents
694 = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'enable_components', NULL, array());
695 $enabledComponents = array_diff($enabledComponents, array($componentName));
696
697 self::setEnabledComponents($enabledComponents);
698
699 return TRUE;
700 }
701
702 public static function setEnabledComponents($enabledComponents) {
703 $config = CRM_Core_Config::singleton();
704 $components = CRM_Core_Component::getComponents();
705
706 $enabledComponentIDs = array();
707 foreach ($enabledComponents as $name) {
708 $enabledComponentIDs[] = $components[$name]->componentID;
709 }
710
711 // fix the config object
712 $config->enableComponents = $enabledComponents;
713 $config->enableComponentIDs = $enabledComponentIDs;
714
715 // also force reset of component array
716 CRM_Core_Component::getEnabledComponents(TRUE);
717
718 // update DB
719 CRM_Core_BAO_Setting::setItem($enabledComponents,
720 CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'enable_components');
721 }
722
723 /**
724 * @return array
725 */
726 public static function skipVars() {
727 return array(
728 'dsn',
729 'templateCompileDir',
730 'userFrameworkDSN',
731 'userFramework',
732 'userFrameworkBaseURL',
733 'userFrameworkClass',
734 'userHookClass',
735 'userPermissionClass',
736 'userFrameworkURLVar',
737 'userFrameworkVersion',
738 'newBaseURL',
739 'newBaseDir',
740 'newSiteName',
741 'configAndLogDir',
742 'qfKey',
743 'gettextResourceDir',
744 'cleanURL',
745 'locale_custom_strings',
746 'localeCustomStrings',
747 'autocompleteContactSearch',
748 'autocompleteContactReference',
749 'checksumTimeout',
750 );
751 }
752}