3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2018 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
29 * Config handles all the run time configuration changes that the system needs to deal with.
31 * Typically we'll have different values for a user's sandbox, a qa sandbox and a production area.
32 * The default values in general, should reflect production values (minimizes chances of screwing up)
35 * @copyright CiviCRM LLC (c) 2004-2018
38 require_once 'Log.php';
39 require_once 'Mail.php';
41 require_once 'api/api.php';
44 * Class CRM_Core_Config
46 * @property CRM_Utils_System_Base $userSystem
47 * @property CRM_Core_Permission_Base $userPermissionClass
48 * @property array $enableComponents
49 * @property array $languageLimit
50 * @property bool $debug
51 * @property bool $doNotResetCache
52 * @property string $maxFileSize
53 * @property string $defaultCurrency
54 * @property string $defaultCurrencySymbol
55 * @property string $lcMessages
56 * @property string $fieldSeparator
57 * @property string $userFramework
58 * @property string $verpSeparator
59 * @property string $dateFormatFull
60 * @property string $resourceBase
61 * @property string $dsn
62 * @property string $customTemplateDir
63 * @property string $defaultContactCountry
64 * @property string $defaultContactStateProvince
65 * @property string $monetaryDecimalPoint
66 * @property string $monetaryThousandSeparator
67 * @property array fiscalYearStart
69 class CRM_Core_Config
extends CRM_Core_Config_MagicMerge
{
72 * The handle to the log that we are using
75 private static $_log = NULL;
78 * We only need one instance of this object. So we use the singleton
79 * pattern and cache the instance in this variable
81 * @var CRM_Core_Config
83 private static $_singleton = NULL;
86 * The constructor. Sets domain id if defined, otherwise assumes
87 * single instance installation.
89 public function __construct() {
90 parent
::__construct();
94 * Singleton function used to manage this object.
96 * @param bool $loadFromDB
97 * whether to load from the database.
99 * whether to force a reconstruction.
101 * @return CRM_Core_Config
103 public static function &singleton($loadFromDB = TRUE, $force = FALSE) {
104 if (self
::$_singleton === NULL ||
$force) {
105 $GLOBALS['civicrm_default_error_scope'] = CRM_Core_TemporaryErrorScope
::create(array('CRM_Core_Error', 'handle'));
106 $errorScope = CRM_Core_TemporaryErrorScope
::create(array('CRM_Core_Error', 'simpleHandler'));
108 if (defined('E_DEPRECATED')) {
109 error_reporting(error_reporting() & ~E_DEPRECATED
);
112 self
::$_singleton = new CRM_Core_Config();
113 \Civi\Core\Container
::boot($loadFromDB);
114 if ($loadFromDB && self
::$_singleton->dsn
) {
115 $domain = \CRM_Core_BAO_Domain
::getDomain();
116 \CRM_Core_BAO_ConfigSetting
::applyLocale(\Civi
::settings($domain->id
), $domain->locales
);
120 CRM_Utils_Hook
::config(self
::$_singleton);
121 self
::$_singleton->authenticate();
123 // Extreme backward compat: $config binds to active domain at moment of setup.
124 self
::$_singleton->getSettings();
126 Civi
::service('settings_manager')->useDefaults();
128 self
::$_singleton->handleFirstRun();
131 return self
::$_singleton;
135 * Returns the singleton logger for the application.
141 static public function &getLog() {
142 if (!isset(self
::$_log)) {
143 self
::$_log = Log
::singleton('display');
150 * Retrieve a mailer to send any mail from the application.
154 * @see Civi::service()
156 public static function getMailer() {
157 return Civi
::service('pear_mail');
161 * Deletes the web server writable directories.
164 * 1: clean templates_c, 2: clean upload, 3: clean both
167 public function cleanup($value, $rmdir = TRUE) {
168 $value = (int ) $value;
172 CRM_Utils_File
::cleanDir($this->templateCompileDir
, $rmdir);
173 CRM_Utils_File
::createDir($this->templateCompileDir
);
177 CRM_Utils_File
::cleanDir($this->uploadDir
);
178 CRM_Utils_File
::createDir($this->uploadDir
);
181 // Whether we delete/create or simply preserve directories, we should
182 // certainly make sure the restrictions are enforced.
184 $this->templateCompileDir
,
186 $this->configAndLogDir
,
187 $this->customFileUploadDir
,
189 if ($dir && is_dir($dir)) {
190 CRM_Utils_File
::restrictAccess($dir);
196 * Verify that the needed parameters are not null in the config.
198 * @param CRM_Core_Config $config (reference) the system config object
199 * @param array $required (reference) the parameters that need a value
203 public static function check(&$config, &$required) {
204 foreach ($required as $name) {
205 if (CRM_Utils_System
::isNull($config->$name)) {
213 * Reset the serialized array and recompute.
216 public function reset() {
217 $query = "UPDATE civicrm_domain SET config_backend = null";
218 CRM_Core_DAO
::executeQuery($query);
222 * This method should initialize auth sources.
224 public function authenticate() {
225 // make sure session is always initialised
226 $session = CRM_Core_Session
::singleton();
228 // for logging purposes, pass the userID to the db
229 $userID = $session->get('userID');
231 CRM_Core_DAO
::executeQuery('SET @civicrm_user_id = %1',
232 array(1 => array($userID, 'Integer'))
236 if ($session->get('userID') && !$session->get('authSrc')) {
237 $session->set('authSrc', CRM_Core_Permission
::AUTH_SRC_LOGIN
);
241 CRM_Contact_BAO_Contact_Permission
::initChecksumAuthSrc();
245 * One function to get domain ID.
247 * @param int $domainID
252 public static function domainID($domainID = NULL, $reset = FALSE) {
257 if ($reset ||
empty($domain)) {
258 $domain = defined('CIVICRM_DOMAIN_ID') ? CIVICRM_DOMAIN_ID
: 1;
265 * Function to get environment.
272 public static function environment($env = NULL, $reset = FALSE) {
277 if ($reset ||
empty($environment)) {
278 $environment = Civi
::settings()->get('environment');
281 $environment = 'Production';
287 * Do general cleanup of caches, temp directories and temp tables
290 * @param bool $sessionReset
292 public function cleanupCaches($sessionReset = TRUE) {
293 // cleanup templates_c directory
294 $this->cleanup(1, FALSE);
297 self
::clearDBCache();
298 Civi
::cache('session')->clear();
299 CRM_Utils_System
::flushCache();
302 $session = CRM_Core_Session
::singleton();
308 * Do general cleanup of module permissions.
310 public function cleanupPermissions() {
311 $module_files = CRM_Extension_System
::singleton()->getMapper()->getActiveModuleFiles();
312 if ($this->userPermissionClass
->isModulePermissionSupported()) {
313 // Can store permissions -- so do it!
314 $this->userPermissionClass
->upgradePermissions(
315 CRM_Core_Permission
::basicPermissions()
319 // Cannot store permissions -- warn if any modules require them
320 $modules_with_perms = array();
321 foreach ($module_files as $module_file) {
322 $perms = $this->userPermissionClass
->getModulePermissions($module_file['prefix']);
323 if (!empty($perms)) {
324 $modules_with_perms[] = $module_file['prefix'];
327 if (!empty($modules_with_perms)) {
328 CRM_Core_Session
::setStatus(
329 ts('Some modules define permissions, but the CMS cannot store them: %1', array(1 => implode(', ', $modules_with_perms))),
330 ts('Permission Error'),
338 * Flush information about loaded modules.
340 public function clearModuleList() {
341 CRM_Extension_System
::singleton()->getCache()->flush();
342 CRM_Utils_Hook
::singleton(TRUE);
343 CRM_Core_PseudoConstant
::getModuleExtensions(TRUE);
344 CRM_Core_Module
::getAll(TRUE);
350 public static function clearDBCache() {
352 'TRUNCATE TABLE civicrm_acl_cache',
353 'TRUNCATE TABLE civicrm_acl_contact_cache',
354 'TRUNCATE TABLE civicrm_cache',
355 'TRUNCATE TABLE civicrm_prevnext_cache',
356 'UPDATE civicrm_group SET cache_date = NULL',
357 'TRUNCATE TABLE civicrm_group_contact_cache',
358 'TRUNCATE TABLE civicrm_menu',
359 'UPDATE civicrm_setting SET value = NULL WHERE name="navigation" AND contact_id IS NOT NULL',
362 foreach ($queries as $query) {
363 CRM_Core_DAO
::executeQuery($query);
366 // also delete all the import and export temp tables
367 self
::clearTempTables();
371 * Clear leftover temporary tables.
373 * This is called on upgrade, during tests and site move, from the cron and via clear caches in the UI.
375 * Currently the UI clear caches does not pass a time interval - which may need review as it does risk
376 * ripping the tables out from underneath a current action. This was considered but
377 * out-of-scope for CRM-16167
379 * @param string|bool $timeInterval
380 * Optional time interval for mysql date function.g '2 day'. This can be used to prevent
381 * tables created recently from being deleted.
383 public static function clearTempTables($timeInterval = FALSE) {
385 $dao = new CRM_Core_DAO();
387 SELECT TABLE_NAME as tableName
388 FROM INFORMATION_SCHEMA.TABLES
389 WHERE TABLE_SCHEMA = %1
391 TABLE_NAME LIKE 'civicrm_import_job_%'
392 OR TABLE_NAME LIKE 'civicrm_report_temp%'
393 OR TABLE_NAME LIKE 'civicrm_tmp_d%'
396 // NOTE: Cannot find use-cases where "civicrm_report_temp" would be durable. Could probably remove.
399 $query .= " AND CREATE_TIME < DATE_SUB(NOW(), INTERVAL {$timeInterval})";
402 $tableDAO = CRM_Core_DAO
::executeQuery($query, array(1 => array($dao->database(), 'String')));
404 while ($tableDAO->fetch()) {
405 $tables[] = $tableDAO->tableName
;
407 if (!empty($tables)) {
408 $table = implode(',', $tables);
409 // drop leftover temporary tables
410 CRM_Core_DAO
::executeQuery("DROP TABLE $table");
415 * Check if running in upgrade mode.
417 * @param string $path
421 public static function isUpgradeMode($path = NULL) {
422 if (defined('CIVICRM_UPGRADE_ACTIVE')) {
427 // note: do not re-initialize config here, since this function is part of
428 // config initialization itself
430 if (defined('CIVICRM_UF') && CIVICRM_UF
== 'Joomla') {
434 $path = CRM_Utils_Array
::value($urlVar, $_GET);
437 if ($path && preg_match('/^civicrm\/upgrade(\/.*)?$/', $path)) {
441 if ($path && preg_match('/^civicrm\/ajax\/l10n-js/', $path)
442 && !empty($_SERVER['HTTP_REFERER'])
444 $ref = parse_url($_SERVER['HTTP_REFERER']);
446 (!empty($ref['path']) && preg_match('/civicrm\/upgrade/', $ref['path'])) ||
447 (!empty($ref['query']) && preg_match('/civicrm\/upgrade/', urldecode($ref['query'])))
457 * Is back office credit card processing enabled for this site - ie are there any installed processors that support
459 * This function is used for determining whether to show the submit credit card link, not for determining which processors to show, hence
463 public static function isEnabledBackOfficeCreditCardPayments() {
464 return CRM_Financial_BAO_PaymentProcessor
::hasPaymentProcessorSupporting(array('BackOffice'));
470 public function addressSequence() {
471 return CRM_Utils_Address
::sequence(Civi
::settings()->get('address_format'));
477 public function defaultContactCountry() {
478 return CRM_Core_BAO_Country
::defaultContactCountry();
484 public function defaultContactCountryName() {
485 return CRM_Core_BAO_Country
::defaultContactCountryName();
491 * @param string $defaultCurrency
495 public function defaultCurrencySymbol($defaultCurrency = NULL) {
496 return CRM_Core_BAO_Country
::defaultCurrencySymbol($defaultCurrency);
500 * Resets the singleton, so that the next call to CRM_Core_Config::singleton()
501 * reloads completely.
503 * While normally we could call the singleton function with $force = TRUE,
504 * this function addresses a very specific use-case in the CiviCRM installer,
505 * where we cannot yet force a reload, but we want to make sure that the next
506 * call to this object gets a fresh start (ex: to initialize the DAO).
508 public function free() {
509 self
::$_singleton = NULL;
513 * Conditionally fire an event during the first page run.
515 * The install system is currently implemented several times, so it's hard to add
516 * new installation logic. We use a makeshift method to detect the first run.
518 * Situations to test:
520 * - Upgrade from an old version (predating first-run tracker)
521 * - Upgrade from an old version (with first-run tracking)
523 public function handleFirstRun() {
524 // Ordinarily, we prefetch settings en masse and find that the system is already installed.
525 // No extra SQL queries required.
526 if (Civi
::settings()->get('installed')) {
530 // Q: How should this behave during testing?
531 if (defined('CIVICRM_TEST')) {
535 // If schema hasn't been loaded yet, then do nothing. Don't want to interfere
536 // with the existing installers. NOTE: If we change the installer pageflow,
537 // then we may want to modify this behavior.
538 if (!CRM_Core_DAO
::checkTableExists('civicrm_domain')) {
542 // If we're handling an upgrade, then the system has already been used, so this
543 // is not the first run.
544 if (CRM_Core_Config
::isUpgradeMode()) {
547 $dao = CRM_Core_DAO
::executeQuery('SELECT version FROM civicrm_domain');
548 while ($dao->fetch()) {
549 if ($dao->version
&& version_compare($dao->version
, CRM_Utils_System
::version(), '<')) {
554 // The installation flag is stored in civicrm_setting, which is domain-aware. The
555 // flag could have been stored under a different domain.
556 $dao = CRM_Core_DAO
::executeQuery('
557 SELECT domain_id, value FROM civicrm_setting
558 WHERE is_domain = 1 AND name = "installed"
560 while ($dao->fetch()) {
561 $value = unserialize($dao->value
);
562 if (!empty($value)) {
563 Civi
::settings()->set('installed', 1);
568 // OK, this looks new.
569 Civi
::service('dispatcher')->dispatch(\Civi\Core\Event\SystemInstallEvent
::EVENT_NAME
, new \Civi\Core\Event\
SystemInstallEvent());
570 Civi
::settings()->set('installed', 1);
574 * Is the system permitted to flush caches at the moment.
576 static public function isPermitCacheFlushMode() {
577 return !CRM_Core_Config
::singleton()->doNotResetCache
;
581 * Set cache clearing to enabled or disabled.
583 * This might be enabled at the start of a long running process
584 * such as an import in order to delay clearing caches until the end.
586 * @param bool $enabled
587 * If true then caches can be cleared at this time.
589 static public function setPermitCacheFlushMode($enabled) {
590 CRM_Core_Config
::singleton()->doNotResetCache
= $enabled ?
0 : 1;