Merge pull request #6523 from eileenmcnaughton/CRM-16955
[civicrm-core.git] / CRM / Core / Config.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
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 * Config handles all the run time configuration changes that the system needs to deal with.
30 * Typically we'll have different values for a user's sandbox, a qa sandbox and a production area.
31 * The default values in general, should reflect production values (minimizes chances of screwing up)
32 *
33 * @package CRM
34 * @copyright CiviCRM LLC (c) 2004-2015
35 * $Id$
36 *
37 */
38
39 require_once 'Log.php';
40 require_once 'Mail.php';
41
42 require_once 'api/api.php';
43
44 /**
45 * Class CRM_Core_Config
46 */
47 class CRM_Core_Config extends CRM_Core_Config_Variables {
48 ///
49 /// BASE SYSTEM PROPERTIES (CIVICRM.SETTINGS.PHP)
50 ///
51
52 /**
53 * The dsn of the database connection
54 *
55 * @var string
56 */
57 public $dsn;
58
59 /**
60 * The name of user framework
61 *
62 * @var string
63 */
64 public $userFramework = 'Drupal';
65
66 /**
67 * The name of user framework url variable name
68 *
69 * @var string
70 */
71 public $userFrameworkURLVar = 'q';
72
73 /**
74 * The dsn of the database connection for user framework
75 *
76 * @var string
77 */
78 public $userFrameworkDSN = NULL;
79
80 /**
81 * The connector module for the CMS/UF
82 * @todo Introduce an interface.
83 *
84 * @var CRM_Utils_System_Base
85 */
86 public $userSystem = NULL;
87
88 /**
89 * @var CRM_Core_Permission_Base
90 */
91 public $userPermissionClass;
92
93 /**
94 * The root directory where Smarty should store compiled files.
95 *
96 * @var string
97 */
98 public $templateCompileDir = './templates_c/en_US/';
99
100 /**
101 * @var string
102 */
103 public $configAndLogDir = NULL;
104
105 // END: BASE SYSTEM PROPERTIES (CIVICRM.SETTINGS.PHP)
106
107 ///
108 /// BEGIN HELPER CLASS PROPERTIES
109 ///
110
111 /**
112 * Are we initialized and in a proper state
113 *
114 * @var string
115 */
116 public $initialized = 0;
117
118 /**
119 * @var string
120 */
121 public $customPHPPathDir;
122
123 /**
124 * The factory class used to instantiate our DB objects
125 *
126 * @var string
127 */
128 private $DAOFactoryClass = 'CRM_Contact_DAO_Factory';
129
130 /**
131 * The handle to the log that we are using
132 * @var object
133 */
134 private static $_log = NULL;
135
136 /**
137 * We only need one instance of this object. So we use the singleton
138 * pattern and cache the instance in this variable
139 *
140 * @var CRM_Core_Config
141 */
142 private static $_singleton = NULL;
143
144 /**
145 * @var CRM_Core_Component
146 */
147 public $componentRegistry = NULL;
148
149 ///
150 /// END HELPER CLASS PROPERTIES
151 ///
152
153 ///
154 /// RUNTIME SET CLASS PROPERTIES
155 ///
156
157 /**
158 * @var bool
159 * TRUE, if the call is CiviCRM.
160 * FALSE, if the call is from the CMS.
161 */
162 public $inCiviCRM = FALSE;
163
164 ///
165 /// END: RUNTIME SET CLASS PROPERTIES
166 ///
167
168 /**
169 * @var string
170 */
171 public $recaptchaPublicKey;
172
173 /**
174 * The constructor. Sets domain id if defined, otherwise assumes
175 * single instance installation.
176 */
177 private function __construct() {
178 }
179
180 /**
181 * Singleton function used to manage this object.
182 *
183 * @param bool $loadFromDB
184 * whether to load from the database.
185 * @param bool $force
186 * whether to force a reconstruction.
187 *
188 * @return CRM_Core_Config
189 */
190 public static function &singleton($loadFromDB = TRUE, $force = FALSE) {
191 if (self::$_singleton === NULL || $force) {
192 // goto a simple error handler
193 $GLOBALS['civicrm_default_error_scope'] = CRM_Core_TemporaryErrorScope::create(array('CRM_Core_Error', 'handle'));
194 $errorScope = CRM_Core_TemporaryErrorScope::create(array('CRM_Core_Error', 'simpleHandler'));
195
196 // lets ensure we set E_DEPRECATED to minimize errors
197 // CRM-6327
198 if (defined('E_DEPRECATED')) {
199 error_reporting(error_reporting() & ~E_DEPRECATED);
200 }
201
202 // first, attempt to get configuration object from cache
203 $cache = CRM_Utils_Cache::singleton();
204 self::$_singleton = $cache->get('CRM_Core_Config' . CRM_Core_Config::domainID());
205 // if not in cache, fire off config construction
206 if (!self::$_singleton) {
207 self::$_singleton = new CRM_Core_Config();
208 self::$_singleton->_initialize($loadFromDB);
209
210 //initialize variables. for gencode we cannot load from the
211 //db since the db might not be initialized
212 if ($loadFromDB) {
213 // initialize stuff from the settings file
214 self::$_singleton->setCoreVariables();
215
216 self::$_singleton->_initVariables();
217
218 // I don't think we need to do this twice
219 // however just keeping this commented for now in 4.4
220 // in case we hit any issues - CRM-13064
221 // We can safely delete this once we release 4.4.4
222 // self::$_singleton->setCoreVariables();
223 }
224 $cache->set('CRM_Core_Config' . CRM_Core_Config::domainID(), self::$_singleton);
225 }
226 else {
227 // we retrieve the object from memcache, so we now initialize the objects
228 self::$_singleton->_initialize($loadFromDB);
229
230 // CRM-9803, NYSS-4822
231 // this causes various settings to be reset and hence we should
232 // only use the config object that we retrieved from memcache
233 }
234
235 self::$_singleton->initialized = 1;
236
237 if (isset(self::$_singleton->customPHPPathDir) &&
238 self::$_singleton->customPHPPathDir
239 ) {
240 $include_path = self::$_singleton->customPHPPathDir . PATH_SEPARATOR . get_include_path();
241 set_include_path($include_path);
242 }
243
244 // set the callback at the very very end, to avoid an infinite loop
245 // set the error callback
246 unset($errorScope);
247
248 // call the hook so other modules can add to the config
249 // again doing this at the very very end
250 CRM_Utils_Hook::config(self::$_singleton);
251
252 // make sure session is always initialised
253 $session = CRM_Core_Session::singleton();
254
255 // for logging purposes, pass the userID to the db
256 $userID = $session->get('userID');
257 if ($userID) {
258 CRM_Core_DAO::executeQuery('SET @civicrm_user_id = %1',
259 array(1 => array($userID, 'Integer'))
260 );
261 }
262
263 // initialize authentication source
264 self::$_singleton->initAuthSrc();
265 }
266 return self::$_singleton;
267 }
268
269 /**
270 * @param string $userFramework
271 * One of 'Drupal', 'Joomla', etc.
272 */
273 private function _setUserFrameworkConfig($userFramework) {
274
275 $this->userFrameworkClass = 'CRM_Utils_System_' . $userFramework;
276 $this->userHookClass = 'CRM_Utils_Hook_' . $userFramework;
277 $userPermissionClass = 'CRM_Core_Permission_' . $userFramework;
278 $this->userPermissionClass = new $userPermissionClass();
279
280 $class = $this->userFrameworkClass;
281 // redundant with _initVariables
282 $this->userSystem = new $class();
283
284 if ($userFramework == 'Joomla') {
285 $this->userFrameworkURLVar = 'task';
286 }
287
288 if (defined('CIVICRM_UF_BASEURL')) {
289 $this->userFrameworkBaseURL = CRM_Utils_File::addTrailingSlash(CIVICRM_UF_BASEURL, '/');
290
291 //format url for language negotiation, CRM-7803
292 $this->userFrameworkBaseURL = CRM_Utils_System::languageNegotiationURL($this->userFrameworkBaseURL);
293
294 if (CRM_Utils_System::isSSL()) {
295 $this->userFrameworkBaseURL = str_replace('http://', 'https://',
296 $this->userFrameworkBaseURL
297 );
298 }
299 }
300
301 if (defined('CIVICRM_UF_DSN')) {
302 $this->userFrameworkDSN = CIVICRM_UF_DSN;
303 }
304
305 // this is dynamically figured out in the civicrm.settings.php file
306 if (defined('CIVICRM_CLEANURL')) {
307 $this->cleanURL = CIVICRM_CLEANURL;
308 }
309 else {
310 $this->cleanURL = 0;
311 }
312
313 $this->userFrameworkVersion = $this->userSystem->getVersion();
314
315 if ($userFramework == 'Joomla') {
316 /** @var object|null $mainframe */
317 global $mainframe;
318 $dbprefix = $mainframe ? $mainframe->getCfg('dbprefix') : 'jos_';
319 $this->userFrameworkUsersTableName = $dbprefix . 'users';
320 }
321 elseif ($userFramework == 'WordPress') {
322 global $wpdb;
323 $dbprefix = $wpdb ? $wpdb->prefix : '';
324 $this->userFrameworkUsersTableName = $dbprefix . 'users';
325 }
326 }
327
328 /**
329 * Initializes the entire application.
330 * Reads constants defined in civicrm.settings.php and
331 * stores them in config properties.
332 *
333 * @param bool $loadFromDB
334 */
335 private function _initialize($loadFromDB = TRUE) {
336
337 // following variables should be set in CiviCRM settings and
338 // as crucial ones, are defined upon initialisation
339 // instead of in CRM_Core_Config_Defaults
340 if (defined('CIVICRM_DSN')) {
341 $this->dsn = CIVICRM_DSN;
342 }
343 elseif ($loadFromDB) {
344 // bypass when calling from gencode
345 echo 'You need to define CIVICRM_DSN in civicrm.settings.php';
346 exit();
347 }
348
349 if (defined('CIVICRM_TEMPLATE_COMPILEDIR')) {
350 $this->templateCompileDir = CRM_Utils_File::addTrailingSlash(CIVICRM_TEMPLATE_COMPILEDIR);
351
352 // also make sure we create the config directory within this directory
353 // the below statement will create both the templates directory and the config and log directory
354 $this->configAndLogDir
355 = CRM_Utils_File::baseFilePath($this->templateCompileDir) .
356 'ConfigAndLog' . DIRECTORY_SEPARATOR;
357 CRM_Utils_File::createDir($this->configAndLogDir);
358 CRM_Utils_File::restrictAccess($this->configAndLogDir);
359
360 // we're automatically prefixing compiled templates directories with country/language code
361 global $tsLocale;
362 if (!empty($tsLocale)) {
363 $this->templateCompileDir .= CRM_Utils_File::addTrailingSlash($tsLocale);
364 }
365 elseif (!empty($this->lcMessages)) {
366 $this->templateCompileDir .= CRM_Utils_File::addTrailingSlash($this->lcMessages);
367 }
368
369 CRM_Utils_File::createDir($this->templateCompileDir);
370 CRM_Utils_File::restrictAccess($this->templateCompileDir);
371 }
372 elseif ($loadFromDB) {
373 echo 'You need to define CIVICRM_TEMPLATE_COMPILEDIR in civicrm.settings.php';
374 exit();
375 }
376
377 $this->_initDAO();
378
379 if (defined('CIVICRM_UF')) {
380 $this->userFramework = CIVICRM_UF;
381 $this->_setUserFrameworkConfig($this->userFramework);
382 }
383 else {
384 echo 'You need to define CIVICRM_UF in civicrm.settings.php';
385 exit();
386 }
387
388 // also initialize the logger
389 self::$_log = Log::singleton('display');
390
391 // initialize component registry early to avoid "race"
392 // between CRM_Core_Config and CRM_Core_Component (they
393 // are co-dependant)
394 $this->componentRegistry = new CRM_Core_Component();
395 }
396
397 /**
398 * Initialize the DataObject framework.
399 */
400 private function _initDAO() {
401 CRM_Core_DAO::init($this->dsn);
402
403 $factoryClass = $this->DAOFactoryClass;
404 require_once str_replace('_', DIRECTORY_SEPARATOR, $factoryClass) . '.php';
405 CRM_Core_DAO::setFactory(new $factoryClass());
406 if (CRM_Utils_Constant::value('CIVICRM_MYSQL_STRICT', CRM_Utils_System::isDevelopment())) {
407 CRM_Core_DAO::executeQuery('SET SESSION sql_mode = STRICT_TRANS_TABLES');
408 }
409 }
410
411 /**
412 * Returns the singleton logger for the application.
413 *
414 * @return object
415 */
416 static public function &getLog() {
417 if (!isset(self::$_log)) {
418 self::$_log = Log::singleton('display');
419 }
420
421 return self::$_log;
422 }
423
424 /**
425 * Initialize the config variables.
426 *
427 * @return void
428 */
429 private function _initVariables() {
430 // retrieve serialised settings
431 $variables = array();
432 CRM_Core_BAO_ConfigSetting::retrieve($variables);
433
434 // if settings are not available, go down the full path
435 if (empty($variables)) {
436 // Step 1. get system variables with their hardcoded defaults
437 $variables = get_object_vars($this);
438
439 // Step 2. get default values (with settings file overrides if
440 // available - handled in CRM_Core_Config_Defaults)
441 CRM_Core_Config_Defaults::setValues($variables);
442
443 // retrieve directory and url preferences also
444 CRM_Core_BAO_Setting::retrieveDirectoryAndURLPreferences($variables);
445
446 // add component specific settings
447 $this->componentRegistry->addConfig($this);
448
449 // serialise settings
450 $settings = $variables;
451 CRM_Core_BAO_ConfigSetting::add($settings);
452 }
453
454 $urlArray = array('userFrameworkResourceURL', 'imageUploadURL');
455 $dirArray = array('uploadDir', 'customFileUploadDir');
456
457 foreach ($variables as $key => $value) {
458 if (in_array($key, $urlArray)) {
459 $value = CRM_Utils_File::addTrailingSlash($value, '/');
460 }
461 elseif (in_array($key, $dirArray)) {
462 if ($value) {
463 $value = CRM_Utils_File::addTrailingSlash($value);
464 }
465 if (empty($value) || (CRM_Utils_File::createDir($value, FALSE) === FALSE)) {
466 // seems like we could not create the directories
467 // settings might have changed, lets suppress a message for now
468 // so we can make some more progress and let the user fix their settings
469 // for now we assign it to a know value
470 // CRM-4949
471 $value = $this->templateCompileDir;
472 $url = CRM_Utils_System::url('civicrm/admin/setting/path', 'reset=1');
473 CRM_Core_Session::setStatus(ts('%1 has an incorrect directory path. Please go to the <a href="%2">path setting page</a> and correct it.', array(
474 1 => $key,
475 2 => $url,
476 )), ts('Check Settings'), 'alert');
477 }
478 }
479 elseif ($key == 'lcMessages') {
480 // reset the templateCompileDir to locale-specific and make sure it exists
481 if (substr($this->templateCompileDir, -1 * strlen($value) - 1, -1) != $value) {
482 $this->templateCompileDir .= CRM_Utils_File::addTrailingSlash($value);
483 CRM_Utils_File::createDir($this->templateCompileDir);
484 CRM_Utils_File::restrictAccess($this->templateCompileDir);
485 }
486 }
487
488 $this->$key = $value;
489 }
490
491 if ($this->userFrameworkResourceURL) {
492 // we need to do this here so all blocks also load from an ssl server
493 if (CRM_Utils_System::isSSL()) {
494 CRM_Utils_System::mapConfigToSSL();
495 }
496 $rrb = parse_url($this->userFrameworkResourceURL);
497 // don't use absolute path if resources are stored on a different server
498 // CRM-4642
499 $this->resourceBase = $this->userFrameworkResourceURL;
500 if (isset($_SERVER['HTTP_HOST']) &&
501 isset($rrb['host'])
502 ) {
503 $this->resourceBase = ($rrb['host'] == $_SERVER['HTTP_HOST']) ? $rrb['path'] : $this->userFrameworkResourceURL;
504 }
505 }
506
507 if (!$this->customFileUploadDir) {
508 $this->customFileUploadDir = $this->uploadDir;
509 }
510
511 if ($this->geoProvider) {
512 $this->geocodeMethod = 'CRM_Utils_Geocode_' . $this->geoProvider;
513 }
514 elseif ($this->mapProvider) {
515 $this->geocodeMethod = 'CRM_Utils_Geocode_' . $this->mapProvider;
516 }
517
518 require_once str_replace('_', DIRECTORY_SEPARATOR, $this->userFrameworkClass) . '.php';
519 $class = $this->userFrameworkClass;
520 // redundant with _setUserFrameworkConfig
521 $this->userSystem = new $class();
522 }
523
524 /**
525 * Retrieve a mailer to send any mail from the application.
526 *
527 * @return Mail
528 * @deprecated
529 */
530 public static function getMailer() {
531 return Civi\Core\Container::singleton()->get('pear_mail');
532 }
533
534 /**
535 * Deletes the web server writable directories.
536 *
537 * @param int $value
538 * 1: clean templates_c, 2: clean upload, 3: clean both
539 * @param bool $rmdir
540 */
541 public function cleanup($value, $rmdir = TRUE) {
542 $value = (int ) $value;
543
544 if ($value & 1) {
545 // clean templates_c
546 CRM_Utils_File::cleanDir($this->templateCompileDir, $rmdir);
547 CRM_Utils_File::createDir($this->templateCompileDir);
548 }
549 if ($value & 2) {
550 // clean upload dir
551 CRM_Utils_File::cleanDir($this->uploadDir);
552 CRM_Utils_File::createDir($this->uploadDir);
553 }
554
555 // Whether we delete/create or simply preserve directories, we should
556 // certainly make sure the restrictions are enforced.
557 foreach (array(
558 $this->templateCompileDir,
559 $this->uploadDir,
560 $this->configAndLogDir,
561 $this->customFileUploadDir,
562 ) as $dir) {
563 if ($dir && is_dir($dir)) {
564 CRM_Utils_File::restrictAccess($dir);
565 }
566 }
567 }
568
569 /**
570 * Verify that the needed parameters are not null in the config.
571 *
572 * @param CRM_Core_Config $config (reference) the system config object
573 * @param array $required (reference) the parameters that need a value
574 *
575 * @return bool
576 */
577 public static function check(&$config, &$required) {
578 foreach ($required as $name) {
579 if (CRM_Utils_System::isNull($config->$name)) {
580 return FALSE;
581 }
582 }
583 return TRUE;
584 }
585
586 /**
587 * Reset the serialized array and recompute.
588 * use with care
589 */
590 public function reset() {
591 $query = "UPDATE civicrm_domain SET config_backend = null";
592 CRM_Core_DAO::executeQuery($query);
593 }
594
595 /**
596 * This method should initialize auth sources.
597 */
598 public function initAuthSrc() {
599 $session = CRM_Core_Session::singleton();
600 if ($session->get('userID') && !$session->get('authSrc')) {
601 $session->set('authSrc', CRM_Core_Permission::AUTH_SRC_LOGIN);
602 }
603
604 // checksum source
605 CRM_Contact_BAO_Contact_Permission::initChecksumAuthSrc();
606 }
607
608 /**
609 * One function to get domain ID.
610 */
611 public static function domainID($domainID = NULL, $reset = FALSE) {
612 static $domain;
613 if ($domainID) {
614 $domain = $domainID;
615 }
616 if ($reset || empty($domain)) {
617 $domain = defined('CIVICRM_DOMAIN_ID') ? CIVICRM_DOMAIN_ID : 1;
618 }
619
620 return $domain;
621 }
622
623 /**
624 * Do general cleanup of caches, temp directories and temp tables
625 * CRM-8739
626 */
627 public function cleanupCaches($sessionReset = TRUE) {
628 // cleanup templates_c directory
629 $this->cleanup(1, FALSE);
630
631 // clear all caches
632 self::clearDBCache();
633 CRM_Utils_System::flushCache();
634
635 if ($sessionReset) {
636 $session = CRM_Core_Session::singleton();
637 $session->reset(2);
638 }
639 }
640
641 /**
642 * Do general cleanup of module permissions.
643 */
644 public function cleanupPermissions() {
645 $module_files = CRM_Extension_System::singleton()->getMapper()->getActiveModuleFiles();
646 if ($this->userPermissionClass->isModulePermissionSupported()) {
647 // Can store permissions -- so do it!
648 $this->userPermissionClass->upgradePermissions(
649 CRM_Core_Permission::basicPermissions()
650 );
651 }
652 else {
653 // Cannot store permissions -- warn if any modules require them
654 $modules_with_perms = array();
655 foreach ($module_files as $module_file) {
656 $perms = $this->userPermissionClass->getModulePermissions($module_file['prefix']);
657 if (!empty($perms)) {
658 $modules_with_perms[] = $module_file['prefix'];
659 }
660 }
661 if (!empty($modules_with_perms)) {
662 CRM_Core_Session::setStatus(
663 ts('Some modules define permissions, but the CMS cannot store them: %1', array(1 => implode(', ', $modules_with_perms))),
664 ts('Permission Error'),
665 'error'
666 );
667 }
668 }
669 }
670
671 /**
672 * Flush information about loaded modules.
673 */
674 public function clearModuleList() {
675 CRM_Extension_System::singleton()->getCache()->flush();
676 CRM_Utils_Hook::singleton(TRUE);
677 CRM_Core_PseudoConstant::getModuleExtensions(TRUE);
678 CRM_Core_Module::getAll(TRUE);
679 }
680
681 /**
682 * Clear db cache.
683 */
684 public static function clearDBCache() {
685 $queries = array(
686 'TRUNCATE TABLE civicrm_acl_cache',
687 'TRUNCATE TABLE civicrm_acl_contact_cache',
688 'TRUNCATE TABLE civicrm_cache',
689 'TRUNCATE TABLE civicrm_prevnext_cache',
690 'UPDATE civicrm_group SET cache_date = NULL',
691 'TRUNCATE TABLE civicrm_group_contact_cache',
692 'TRUNCATE TABLE civicrm_menu',
693 'UPDATE civicrm_setting SET value = NULL WHERE name="navigation" AND contact_id IS NOT NULL',
694 'DELETE FROM civicrm_setting WHERE name="modulePaths"', // CRM-10543
695 );
696
697 foreach ($queries as $query) {
698 CRM_Core_DAO::executeQuery($query);
699 }
700
701 // also delete all the import and export temp tables
702 self::clearTempTables();
703 }
704
705 /**
706 * Clear leftover temporary tables.
707 *
708 * This is called on upgrade, during tests and site move, from the cron and via clear caches in the UI.
709 *
710 * Currently the UI clear caches does not pass a time interval - which may need review as it does risk
711 * ripping the tables out from underneath a current action. This was considered but
712 * out-of-scope for CRM-16167
713 *
714 * @param string|bool $timeInterval
715 * Optional time interval for mysql date function.g '2 day'. This can be used to prevent
716 * tables created recently from being deleted.
717 */
718 public static function clearTempTables($timeInterval = FALSE) {
719
720 $dao = new CRM_Core_DAO();
721 $query = "
722 SELECT TABLE_NAME as tableName
723 FROM INFORMATION_SCHEMA.TABLES
724 WHERE TABLE_SCHEMA = %1
725 AND (
726 TABLE_NAME LIKE 'civicrm_import_job_%'
727 OR TABLE_NAME LIKE 'civicrm_export_temp%'
728 OR TABLE_NAME LIKE 'civicrm_task_action_temp%'
729 OR TABLE_NAME LIKE 'civicrm_report_temp%'
730 )
731 ";
732 if ($timeInterval) {
733 $query .= " AND CREATE_TIME < DATE_SUB(NOW(), INTERVAL {$timeInterval})";
734 }
735
736 $tableDAO = CRM_Core_DAO::executeQuery($query, array(1 => array($dao->database(), 'String')));
737 $tables = array();
738 while ($tableDAO->fetch()) {
739 $tables[] = $tableDAO->tableName;
740 }
741 if (!empty($tables)) {
742 $table = implode(',', $tables);
743 // drop leftover temporary tables
744 CRM_Core_DAO::executeQuery("DROP TABLE $table");
745 }
746 }
747
748 /**
749 * Check if running in upgrade mode.
750 */
751 public static function isUpgradeMode($path = NULL) {
752 if (defined('CIVICRM_UPGRADE_ACTIVE')) {
753 return TRUE;
754 }
755
756 if (!$path) {
757 // note: do not re-initialize config here, since this function is part of
758 // config initialization itself
759 $urlVar = 'q';
760 if (defined('CIVICRM_UF') && CIVICRM_UF == 'Joomla') {
761 $urlVar = 'task';
762 }
763
764 $path = CRM_Utils_Array::value($urlVar, $_GET);
765 }
766
767 if ($path && preg_match('/^civicrm\/upgrade(\/.*)?$/', $path)) {
768 return TRUE;
769 }
770
771 return FALSE;
772 }
773
774 /**
775 * Wrapper function to allow unit tests to switch user framework on the fly.
776 */
777 public function setUserFramework($userFramework = NULL) {
778 $this->userFramework = $userFramework;
779 $this->_setUserFrameworkConfig($userFramework);
780 }
781
782 /**
783 * Is back office credit card processing enabled for this site - ie are there any installed processors that support
784 * it?
785 * This function is used for determining whether to show the submit credit card link, not for determining which processors to show, hence
786 * it is a config var
787 * @return bool
788 */
789 public static function isEnabledBackOfficeCreditCardPayments() {
790 return CRM_Financial_BAO_PaymentProcessor::hasPaymentProcessorSupporting(array('BackOffice'));
791 }
792
793 /**
794 * Resets the singleton, so that the next call to CRM_Core_Config::singleton()
795 * reloads completely.
796 *
797 * While normally we could call the singleton function with $force = TRUE,
798 * this function addresses a very specific use-case in the CiviCRM installer,
799 * where we cannot yet force a reload, but we want to make sure that the next
800 * call to this object gets a fresh start (ex: to initialize the DAO).
801 */
802 public function free() {
803 self::$_singleton = NULL;
804 }
805
806 }