Merge pull request #13603 from pradpnayak/AdvMailin
[civicrm-core.git] / CRM / Core / Config.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
6b83d5bd 6 | Copyright CiviCRM LLC (c) 2004-2019 |
6a488035
TO
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 * Config handles all the run time configuration changes that the system needs to deal with.
8eedd10a 30 *
6a488035
TO
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)
33 *
34 * @package CRM
6b83d5bd 35 * @copyright CiviCRM LLC (c) 2004-2019
6a488035
TO
36 */
37
6a488035
TO
38require_once 'Mail.php';
39
40require_once 'api/api.php';
72536736 41
28518c90
EM
42/**
43 * Class CRM_Core_Config
e367c7b0
CW
44 *
45 * @property CRM_Utils_System_Base $userSystem
6d054a8e 46 * @property CRM_Core_Permission_Base $userPermissionClass
6b070fc0
CW
47 * @property array $enableComponents
48 * @property array $languageLimit
49 * @property bool $debug
50 * @property bool $doNotResetCache
51 * @property string $maxFileSize
52 * @property string $defaultCurrency
53 * @property string $defaultCurrencySymbol
54 * @property string $lcMessages
55 * @property string $fieldSeparator
56 * @property string $userFramework
57 * @property string $verpSeparator
58 * @property string $dateFormatFull
59 * @property string $resourceBase
60 * @property string $dsn
61 * @property string $customTemplateDir
62 * @property string $defaultContactCountry
63 * @property string $defaultContactStateProvince
64 * @property string $monetaryDecimalPoint
65 * @property string $monetaryThousandSeparator
81716ddb 66 * @property array fiscalYearStart
28518c90 67 */
c0a1f187 68class CRM_Core_Config extends CRM_Core_Config_MagicMerge {
4d66768d 69
6a488035
TO
70 /**
71 * The handle to the log that we are using
72 * @var object
73 */
74 private static $_log = NULL;
75
6a488035
TO
76 /**
77 * We only need one instance of this object. So we use the singleton
78 * pattern and cache the instance in this variable
72536736
AH
79 *
80 * @var CRM_Core_Config
6a488035
TO
81 */
82 private static $_singleton = NULL;
83
6a488035
TO
84 /**
85 * The constructor. Sets domain id if defined, otherwise assumes
86 * single instance installation.
6a488035 87 */
0acb7f15 88 public function __construct() {
c0a1f187 89 parent::__construct();
6a488035
TO
90 }
91
92 /**
93 * Singleton function used to manage this object.
94 *
5a4f6742
CW
95 * @param bool $loadFromDB
96 * whether to load from the database.
97 * @param bool $force
98 * whether to force a reconstruction.
6a488035 99 *
5af8c999 100 * @return CRM_Core_Config
6a488035 101 */
00be9182 102 public static function &singleton($loadFromDB = TRUE, $force = FALSE) {
6a488035 103 if (self::$_singleton === NULL || $force) {
ca32aecc
TO
104 $GLOBALS['civicrm_default_error_scope'] = CRM_Core_TemporaryErrorScope::create(array('CRM_Core_Error', 'handle'));
105 $errorScope = CRM_Core_TemporaryErrorScope::create(array('CRM_Core_Error', 'simpleHandler'));
6a488035 106
6a488035
TO
107 if (defined('E_DEPRECATED')) {
108 error_reporting(error_reporting() & ~E_DEPRECATED);
109 }
110
fc50f470 111 self::$_singleton = new CRM_Core_Config();
7f835399
TO
112 \Civi\Core\Container::boot($loadFromDB);
113 if ($loadFromDB && self::$_singleton->dsn) {
c0a1f187
TO
114 $domain = \CRM_Core_BAO_Domain::getDomain();
115 \CRM_Core_BAO_ConfigSetting::applyLocale(\Civi::settings($domain->id), $domain->locales);
6a488035 116
fc50f470 117 unset($errorScope);
6a488035 118
fc50f470
TO
119 CRM_Utils_Hook::config(self::$_singleton);
120 self::$_singleton->authenticate();
23bb9c85 121
fc50f470
TO
122 // Extreme backward compat: $config binds to active domain at moment of setup.
123 self::$_singleton->getSettings();
23bb9c85 124
fc50f470 125 Civi::service('settings_manager')->useDefaults();
0085db83
C
126
127 self::$_singleton->handleFirstRun();
fc50f470 128 }
6a488035
TO
129 }
130 return self::$_singleton;
131 }
132
6a488035 133 /**
d09edf64 134 * Returns the singleton logger for the application.
6a488035 135 *
c0a1f187 136 * @deprecated
6a488035 137 * @return object
c0a1f187 138 * @see Civi::log()
6a488035
TO
139 */
140 static public function &getLog() {
141 if (!isset(self::$_log)) {
142 self::$_log = Log::singleton('display');
143 }
144
145 return self::$_log;
146 }
147
6a488035 148 /**
d09edf64 149 * Retrieve a mailer to send any mail from the application.
6a488035 150 *
247eb841
TO
151 * @return Mail
152 * @deprecated
c0a1f187 153 * @see Civi::service()
6a488035 154 */
247eb841 155 public static function getMailer() {
048222df 156 return Civi::service('pear_mail');
72ad6c1b
TO
157 }
158
6a488035 159 /**
d09edf64 160 * Deletes the web server writable directories.
6a488035 161 *
72536736
AH
162 * @param int $value
163 * 1: clean templates_c, 2: clean upload, 3: clean both
164 * @param bool $rmdir
6a488035
TO
165 */
166 public function cleanup($value, $rmdir = TRUE) {
167 $value = (int ) $value;
168
169 if ($value & 1) {
170 // clean templates_c
171 CRM_Utils_File::cleanDir($this->templateCompileDir, $rmdir);
172 CRM_Utils_File::createDir($this->templateCompileDir);
173 }
174 if ($value & 2) {
175 // clean upload dir
176 CRM_Utils_File::cleanDir($this->uploadDir);
177 CRM_Utils_File::createDir($this->uploadDir);
fea6131e
TO
178 }
179
180 // Whether we delete/create or simply preserve directories, we should
181 // certainly make sure the restrictions are enforced.
353ffa53
TO
182 foreach (array(
183 $this->templateCompileDir,
184 $this->uploadDir,
185 $this->configAndLogDir,
8d7a9d07 186 $this->customFileUploadDir,
353ffa53 187 ) as $dir) {
fea6131e
TO
188 if ($dir && is_dir($dir)) {
189 CRM_Utils_File::restrictAccess($dir);
190 }
6a488035
TO
191 }
192 }
193
194 /**
0880a9d0 195 * Verify that the needed parameters are not null in the config.
6a488035 196 *
8d7a9d07
CB
197 * @param CRM_Core_Config $config (reference) the system config object
198 * @param array $required (reference) the parameters that need a value
6a488035 199 *
8d7a9d07 200 * @return bool
6a488035 201 */
00be9182 202 public static function check(&$config, &$required) {
6a488035
TO
203 foreach ($required as $name) {
204 if (CRM_Utils_System::isNull($config->$name)) {
205 return FALSE;
206 }
207 }
208 return TRUE;
209 }
210
211 /**
0880a9d0 212 * Reset the serialized array and recompute.
6a488035
TO
213 * use with care
214 */
00be9182 215 public function reset() {
6a488035
TO
216 $query = "UPDATE civicrm_domain SET config_backend = null";
217 CRM_Core_DAO::executeQuery($query);
218 }
219
546b78fa 220 /**
0880a9d0 221 * This method should initialize auth sources.
546b78fa 222 */
635f0b86
TO
223 public function authenticate() {
224 // make sure session is always initialised
e8f14831 225 $session = CRM_Core_Session::singleton();
635f0b86
TO
226
227 // for logging purposes, pass the userID to the db
228 $userID = $session->get('userID');
229 if ($userID) {
230 CRM_Core_DAO::executeQuery('SET @civicrm_user_id = %1',
231 array(1 => array($userID, 'Integer'))
232 );
233 }
234
e8f14831
DS
235 if ($session->get('userID') && !$session->get('authSrc')) {
236 $session->set('authSrc', CRM_Core_Permission::AUTH_SRC_LOGIN);
237 }
238
239 // checksum source
240 CRM_Contact_BAO_Contact_Permission::initChecksumAuthSrc();
241 }
242
6a488035 243 /**
0880a9d0 244 * One function to get domain ID.
ad37ac8e 245 *
246 * @param int $domainID
247 * @param bool $reset
248 *
249 * @return int|null
6a488035 250 */
00be9182 251 public static function domainID($domainID = NULL, $reset = FALSE) {
6a488035
TO
252 static $domain;
253 if ($domainID) {
254 $domain = $domainID;
255 }
256 if ($reset || empty($domain)) {
257 $domain = defined('CIVICRM_DOMAIN_ID') ? CIVICRM_DOMAIN_ID : 1;
258 }
259
260 return $domain;
261 }
262
f008885c
E
263 /**
264 * Function to get environment.
265 *
266 * @param string $env
267 * @param bool $reset
268 *
269 * @return string
270 */
271 public static function environment($env = NULL, $reset = FALSE) {
f008885c
E
272 if ($env) {
273 $environment = $env;
274 }
275 if ($reset || empty($environment)) {
8a078f99 276 $environment = Civi::settings()->get('environment');
f008885c
E
277 }
278 if (!$environment) {
279 $environment = 'Production';
280 }
281 return $environment;
282 }
283
6a488035 284 /**
100fef9d 285 * Do general cleanup of caches, temp directories and temp tables
6a488035 286 * CRM-8739
ea3ddccf 287 *
288 * @param bool $sessionReset
6a488035 289 */
00be9182 290 public function cleanupCaches($sessionReset = TRUE) {
6a488035
TO
291 // cleanup templates_c directory
292 $this->cleanup(1, FALSE);
293
1b50807d 294 // clear all caches
6a488035 295 self::clearDBCache();
0a12cd4a 296 Civi::cache('session')->clear();
1b50807d 297 CRM_Utils_System::flushCache();
6a488035
TO
298
299 if ($sessionReset) {
300 $session = CRM_Core_Session::singleton();
301 $session->reset(2);
302 }
303 }
304
305 /**
306 * Do general cleanup of module permissions.
307 */
00be9182 308 public function cleanupPermissions() {
6a488035 309 $module_files = CRM_Extension_System::singleton()->getMapper()->getActiveModuleFiles();
7fccad46
TO
310 if ($this->userPermissionClass->isModulePermissionSupported()) {
311 // Can store permissions -- so do it!
0d8fc497
TO
312 $this->userPermissionClass->upgradePermissions(
313 CRM_Core_Permission::basicPermissions()
314 );
0db6c3e1
TO
315 }
316 else {
7fccad46
TO
317 // Cannot store permissions -- warn if any modules require them
318 $modules_with_perms = array();
319 foreach ($module_files as $module_file) {
320 $perms = $this->userPermissionClass->getModulePermissions($module_file['prefix']);
321 if (!empty($perms)) {
322 $modules_with_perms[] = $module_file['prefix'];
323 }
324 }
325 if (!empty($modules_with_perms)) {
326 CRM_Core_Session::setStatus(
10a5be27 327 ts('Some modules define permissions, but the CMS cannot store them: %1', array(1 => implode(', ', $modules_with_perms))),
7fccad46
TO
328 ts('Permission Error'),
329 'error'
330 );
331 }
6a488035
TO
332 }
333 }
334
335 /**
0880a9d0 336 * Flush information about loaded modules.
6a488035 337 */
00be9182 338 public function clearModuleList() {
6a488035
TO
339 CRM_Extension_System::singleton()->getCache()->flush();
340 CRM_Utils_Hook::singleton(TRUE);
341 CRM_Core_PseudoConstant::getModuleExtensions(TRUE);
342 CRM_Core_Module::getAll(TRUE);
343 }
344
345 /**
0880a9d0 346 * Clear db cache.
6a488035
TO
347 */
348 public static function clearDBCache() {
349 $queries = array(
350 'TRUNCATE TABLE civicrm_acl_cache',
351 'TRUNCATE TABLE civicrm_acl_contact_cache',
352 'TRUNCATE TABLE civicrm_cache',
353 'TRUNCATE TABLE civicrm_prevnext_cache',
354 'UPDATE civicrm_group SET cache_date = NULL',
355 'TRUNCATE TABLE civicrm_group_contact_cache',
356 'TRUNCATE TABLE civicrm_menu',
357 'UPDATE civicrm_setting SET value = NULL WHERE name="navigation" AND contact_id IS NOT NULL',
6a488035
TO
358 );
359
360 foreach ($queries as $query) {
361 CRM_Core_DAO::executeQuery($query);
362 }
363
5a302bbc
TO
364 if ($adapter = CRM_Utils_Constant::value('CIVICRM_BAO_CACHE_ADAPTER')) {
365 return $adapter::clearDBCache();
366 }
367
6a488035
TO
368 // also delete all the import and export temp tables
369 self::clearTempTables();
370 }
371
372 /**
0880a9d0 373 * Clear leftover temporary tables.
0383ef73
EM
374 *
375 * This is called on upgrade, during tests and site move, from the cron and via clear caches in the UI.
376 *
377 * Currently the UI clear caches does not pass a time interval - which may need review as it does risk
378 * ripping the tables out from underneath a current action. This was considered but
379 * out-of-scope for CRM-16167
380 *
381 * @param string|bool $timeInterval
382 * Optional time interval for mysql date function.g '2 day'. This can be used to prevent
383 * tables created recently from being deleted.
6a488035 384 */
0383ef73
EM
385 public static function clearTempTables($timeInterval = FALSE) {
386
387 $dao = new CRM_Core_DAO();
6a488035 388 $query = "
0383ef73
EM
389 SELECT TABLE_NAME as tableName
390 FROM INFORMATION_SCHEMA.TABLES
391 WHERE TABLE_SCHEMA = %1
392 AND (
393 TABLE_NAME LIKE 'civicrm_import_job_%'
0383ef73 394 OR TABLE_NAME LIKE 'civicrm_report_temp%'
40c8b829 395 OR TABLE_NAME LIKE 'civicrm_tmp_d%'
0383ef73
EM
396 )
397 ";
f7e48bad
TO
398 // NOTE: Cannot find use-cases where "civicrm_report_temp" would be durable. Could probably remove.
399
0383ef73
EM
400 if ($timeInterval) {
401 $query .= " AND CREATE_TIME < DATE_SUB(NOW(), INTERVAL {$timeInterval})";
402 }
403
404 $tableDAO = CRM_Core_DAO::executeQuery($query, array(1 => array($dao->database(), 'String')));
6a488035
TO
405 $tables = array();
406 while ($tableDAO->fetch()) {
407 $tables[] = $tableDAO->tableName;
408 }
409 if (!empty($tables)) {
410 $table = implode(',', $tables);
411 // drop leftover temporary tables
412 CRM_Core_DAO::executeQuery("DROP TABLE $table");
413 }
414 }
415
416 /**
0880a9d0 417 * Check if running in upgrade mode.
54957108 418 *
419 * @param string $path
420 *
421 * @return bool
6a488035 422 */
00be9182 423 public static function isUpgradeMode($path = NULL) {
6a488035
TO
424 if (defined('CIVICRM_UPGRADE_ACTIVE')) {
425 return TRUE;
426 }
427
428 if (!$path) {
429 // note: do not re-initialize config here, since this function is part of
430 // config initialization itself
431 $urlVar = 'q';
432 if (defined('CIVICRM_UF') && CIVICRM_UF == 'Joomla') {
433 $urlVar = 'task';
434 }
435
436 $path = CRM_Utils_Array::value($urlVar, $_GET);
437 }
438
439 if ($path && preg_match('/^civicrm\/upgrade(\/.*)?$/', $path)) {
440 return TRUE;
441 }
442
867a532b
TO
443 if ($path && preg_match('/^civicrm\/ajax\/l10n-js/', $path)
444 && !empty($_SERVER['HTTP_REFERER'])
445 ) {
446 $ref = parse_url($_SERVER['HTTP_REFERER']);
8b15d2e9
CW
447 if (
448 (!empty($ref['path']) && preg_match('/civicrm\/upgrade/', $ref['path'])) ||
449 (!empty($ref['query']) && preg_match('/civicrm\/upgrade/', urldecode($ref['query'])))
450 ) {
867a532b
TO
451 return TRUE;
452 }
453 }
454
6a488035
TO
455 return FALSE;
456 }
457
9be1374d
EM
458 /**
459 * Is back office credit card processing enabled for this site - ie are there any installed processors that support
fbcb6fba 460 * it?
52767de0
EM
461 * This function is used for determining whether to show the submit credit card link, not for determining which processors to show, hence
462 * it is a config var
9be1374d
EM
463 * @return bool
464 */
00be9182 465 public static function isEnabledBackOfficeCreditCardPayments() {
44b6505d 466 return CRM_Financial_BAO_PaymentProcessor::hasPaymentProcessorSupporting(array('BackOffice'));
9be1374d 467 }
96025800 468
0acb7f15
TO
469 /**
470 * @deprecated
471 */
472 public function addressSequence() {
473 return CRM_Utils_Address::sequence(Civi::settings()->get('address_format'));
474 }
475
476 /**
477 * @deprecated
478 */
479 public function defaultContactCountry() {
480 return CRM_Core_BAO_Country::defaultContactCountry();
481 }
482
483 /**
484 * @deprecated
485 */
486 public function defaultContactCountryName() {
487 return CRM_Core_BAO_Country::defaultContactCountryName();
488 }
489
490 /**
491 * @deprecated
ea3ddccf 492 *
493 * @param string $defaultCurrency
494 *
495 * @return string
0acb7f15
TO
496 */
497 public function defaultCurrencySymbol($defaultCurrency = NULL) {
498 return CRM_Core_BAO_Country::defaultCurrencySymbol($defaultCurrency);
499 }
500
97b8e6b2 501 /**
502 * Resets the singleton, so that the next call to CRM_Core_Config::singleton()
503 * reloads completely.
504 *
505 * While normally we could call the singleton function with $force = TRUE,
506 * this function addresses a very specific use-case in the CiviCRM installer,
507 * where we cannot yet force a reload, but we want to make sure that the next
508 * call to this object gets a fresh start (ex: to initialize the DAO).
509 */
510 public function free() {
511 self::$_singleton = NULL;
512 }
c8ab0a65 513
0085db83
C
514 /**
515 * Conditionally fire an event during the first page run.
516 *
517 * The install system is currently implemented several times, so it's hard to add
e047612e 518 * new installation logic. We use a makeshift method to detect the first run.
0085db83
C
519 *
520 * Situations to test:
521 * - New installation
522 * - Upgrade from an old version (predating first-run tracker)
523 * - Upgrade from an old version (with first-run tracking)
524 */
525 public function handleFirstRun() {
526 // Ordinarily, we prefetch settings en masse and find that the system is already installed.
527 // No extra SQL queries required.
528 if (Civi::settings()->get('installed')) {
529 return;
530 }
531
532 // Q: How should this behave during testing?
533 if (defined('CIVICRM_TEST')) {
534 return;
535 }
536
537 // If schema hasn't been loaded yet, then do nothing. Don't want to interfere
538 // with the existing installers. NOTE: If we change the installer pageflow,
539 // then we may want to modify this behavior.
540 if (!CRM_Core_DAO::checkTableExists('civicrm_domain')) {
541 return;
542 }
543
544 // If we're handling an upgrade, then the system has already been used, so this
545 // is not the first run.
546 if (CRM_Core_Config::isUpgradeMode()) {
547 return;
548 }
549 $dao = CRM_Core_DAO::executeQuery('SELECT version FROM civicrm_domain');
550 while ($dao->fetch()) {
551 if ($dao->version && version_compare($dao->version, CRM_Utils_System::version(), '<')) {
552 return;
553 }
554 }
555
556 // The installation flag is stored in civicrm_setting, which is domain-aware. The
557 // flag could have been stored under a different domain.
558 $dao = CRM_Core_DAO::executeQuery('
559 SELECT domain_id, value FROM civicrm_setting
560 WHERE is_domain = 1 AND name = "installed"
561 ');
562 while ($dao->fetch()) {
563 $value = unserialize($dao->value);
564 if (!empty($value)) {
565 Civi::settings()->set('installed', 1);
566 return;
567 }
568 }
569
570 // OK, this looks new.
571 Civi::service('dispatcher')->dispatch(\Civi\Core\Event\SystemInstallEvent::EVENT_NAME, new \Civi\Core\Event\SystemInstallEvent());
572 Civi::settings()->set('installed', 1);
573 }
574
0626851e 575 /**
576 * Is the system permitted to flush caches at the moment.
577 */
578 static public function isPermitCacheFlushMode() {
579 return !CRM_Core_Config::singleton()->doNotResetCache;
580 }
581
582 /**
583 * Set cache clearing to enabled or disabled.
584 *
585 * This might be enabled at the start of a long running process
586 * such as an import in order to delay clearing caches until the end.
587 *
588 * @param bool $enabled
589 * If true then caches can be cleared at this time.
590 */
591 static public function setPermitCacheFlushMode($enabled) {
592 CRM_Core_Config::singleton()->doNotResetCache = $enabled ? 0 : 1;
593 }
594
6a488035 595}