CRM-16373 - CRM_Core_Config - Use `Runtime` and `MagicMerge`
authorTim Otten <totten@civicrm.org>
Fri, 11 Sep 2015 08:07:25 +0000 (01:07 -0700)
committerTim Otten <totten@civicrm.org>
Thu, 17 Sep 2015 22:49:29 +0000 (15:49 -0700)
CRM/Core/Config.php
CRM/Core/Config/Defaults.php
CRM/Core/Config/MagicMerge.php [new file with mode: 0644]
CRM/Core/Config/Runtime.php [new file with mode: 0644]
tests/phpunit/CiviTest/CiviUnitTestCase.php

index 664bf345ee40ff4695e073c0ede2f62354c590aa..d19bc978ad4a3fef07bae06a29d0d052145301c0 100644 (file)
@@ -43,7 +43,7 @@ require_once 'api/api.php';
 /**
  * Class CRM_Core_Config
  */
-class CRM_Core_Config extends CRM_Core_Config_Variables {
+class CRM_Core_Config extends CRM_Core_Config_MagicMerge {
 
   /**
    * The handle to the log that we are using
@@ -64,7 +64,7 @@ class CRM_Core_Config extends CRM_Core_Config_Variables {
    * single instance installation.
    */
   public function __construct() {
-    //parent::__construct();
+    parent::__construct();
   }
 
   /**
@@ -90,11 +90,16 @@ class CRM_Core_Config extends CRM_Core_Config_Variables {
       self::$_singleton = $cache->get('CRM_Core_Config' . CRM_Core_Config::domainID());
       if (!self::$_singleton) {
         self::$_singleton = new CRM_Core_Config();
-        self::$_singleton->_initialize($loadFromDB);
+        self::$_singleton->getRuntime()->initialize($loadFromDB);
         $cache->set('CRM_Core_Config' . CRM_Core_Config::domainID(), self::$_singleton);
       }
       else {
-        self::$_singleton->_initialize(FALSE);
+        self::$_singleton->getRuntime()->initialize(FALSE);
+      }
+
+      if (self::$_singleton->getRuntime()->dsn) {
+        $domain = \CRM_Core_BAO_Domain::getDomain();
+        \CRM_Core_BAO_ConfigSetting::applyLocale(\Civi::settings($domain->id), $domain->locales);
       }
 
       unset($errorScope);
@@ -106,59 +111,12 @@ class CRM_Core_Config extends CRM_Core_Config_Variables {
     return self::$_singleton;
   }
 
-  /**
-   * Initializes the entire application.
-   * Reads constants defined in civicrm.settings.php and
-   * stores them in config properties.
-   *
-   * @param bool $loadFromDB
-   */
-  private function _initialize($loadFromDB = TRUE) {
-    if (!defined('CIVICRM_DSN') && $loadFromDB) {
-      $this->fatal('You need to define CIVICRM_DSN in civicrm.settings.php');
-    }
-    $this->dsn = defined('CIVICRM_DSN') ? CIVICRM_DSN : NULL;
-
-    if (!defined('CIVICRM_TEMPLATE_COMPILEDIR') && $loadFromDB) {
-      $this->fatal('You need to define CIVICRM_TEMPLATE_COMPILEDIR in civicrm.settings.php');
-    }
-
-    if (defined('CIVICRM_TEMPLATE_COMPILEDIR')) {
-      $this->configAndLogDir = CRM_Utils_File::baseFilePath() . 'ConfigAndLog' . DIRECTORY_SEPARATOR;
-      CRM_Utils_File::createDir($this->configAndLogDir);
-      CRM_Utils_File::restrictAccess($this->configAndLogDir);
-
-      $this->templateCompileDir = defined('CIVICRM_TEMPLATE_COMPILEDIR') ? CRM_Utils_File::addTrailingSlash(CIVICRM_TEMPLATE_COMPILEDIR) : NULL;
-      CRM_Utils_File::createDir($this->templateCompileDir);
-      CRM_Utils_File::restrictAccess($this->templateCompileDir);
-    }
-
-    CRM_Core_DAO::init($this->dsn);
-
-    if (!defined('CIVICRM_UF')) {
-      $this->fatal('You need to define CIVICRM_UF in civicrm.settings.php');
-    }
-    $this->setUserFramework(CIVICRM_UF);
-
-    if ($loadFromDB) {
-      $this->_initVariables();
-    }
-
-    if (CRM_Utils_System::isSSL()) {
-      $this->userSystem->mapConfigToSSL();
-    }
-
-    if (isset($this->customPHPPathDir) && $this->customPHPPathDir) {
-      set_include_path($this->customPHPPathDir . PATH_SEPARATOR . get_include_path());
-    }
-
-    $this->initialized = 1;
-  }
-
   /**
    * Returns the singleton logger for the application.
    *
+   * @deprecated
    * @return object
+   * @see Civi::log()
    */
   static public function &getLog() {
     if (!isset(self::$_log)) {
@@ -168,54 +126,12 @@ class CRM_Core_Config extends CRM_Core_Config_Variables {
     return self::$_log;
   }
 
-  /**
-   * Initialize the config variables.
-   */
-  private function _initVariables() {
-    $this->templateDir = array(dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR);
-
-    // retrieve serialised settings
-    $variables = array();
-    CRM_Core_BAO_ConfigSetting::retrieve($variables);
-
-    // if settings are not available, go down the full path
-    if (empty($variables)) {
-      // Step 1. get system variables with their hardcoded defaults
-      $variables = get_object_vars($this);
-
-      // serialise settings
-      $settings = $variables;
-      CRM_Core_BAO_ConfigSetting::add($settings);
-    }
-
-    foreach ($variables as $key => $value) {
-      $this->$key = $value;
-    }
-
-    $this->enableComponents = Civi::settings()->get('enable_components');
-
-    $this->customFileUploadDir = CRM_Core_Config_Defaults::getCustomFileUploadDir();
-    $this->customPHPPathDir = CRM_Core_Config_Defaults::getCustomPhpPathDir();
-    $this->customTemplateDir = CRM_Core_Config_Defaults::getCustomTemplateDir();
-    $this->extensionsDir = CRM_Core_Config_Defaults::getExtensionsDir();
-    $this->imageUploadDir = CRM_Core_Config_Defaults::getImageUploadDir();
-    $this->resourceBase = CRM_Core_Config_Defaults::getResourceBase();
-    $this->uploadDir = CRM_Core_Config_Defaults::getUploadDir();
-
-    $this->userFrameworkResourceURL = CRM_Core_Config_Defaults::getUserFrameworkResourceUrl();
-    $this->customCSSURL = CRM_Core_Config_Defaults::getCustomCssUrl();
-    $this->extensionsURL = CRM_Core_Config_Defaults::getExtensionsUrl();
-    $this->imageUploadURL = CRM_Core_Config_Defaults::getImageUploadUrl();
-
-    $this->geocodeMethod = CRM_Utils_Geocode::getProviderClass();
-    $this->defaultCurrencySymbol = CRM_Core_Config_Defaults::getDefaultCurrencySymbol();
-  }
-
   /**
    * Retrieve a mailer to send any mail from the application.
    *
    * @return Mail
    * @deprecated
+   * @see Civi::service()
    */
   public static function getMailer() {
     return Civi::service('pear_mail');
@@ -471,50 +387,17 @@ class CRM_Core_Config extends CRM_Core_Config_Variables {
     return FALSE;
   }
 
+
   /**
    * Wrapper function to allow unit tests to switch user framework on the fly.
    *
    * @param string $userFramework
    *   One of 'Drupal', 'Joomla', etc.
+   * @deprecated
    */
   public function setUserFramework($userFramework) {
-    $this->userFramework = $userFramework;
-    $this->userFrameworkClass = 'CRM_Utils_System_' . $userFramework;
-    $this->userHookClass = 'CRM_Utils_Hook_' . $userFramework;
-    $userPermissionClass = 'CRM_Core_Permission_' . $userFramework;
-    $this->userPermissionClass = new $userPermissionClass();
-
-    $class = $this->userFrameworkClass;
-    $this->userSystem = new $class();
-
-    if ($userFramework == 'Joomla') {
-      $this->userFrameworkURLVar = 'task';
-    }
-
-    if (defined('CIVICRM_UF_BASEURL')) {
-      $this->userFrameworkBaseURL = CRM_Utils_File::addTrailingSlash(CIVICRM_UF_BASEURL, '/');
-
-      //format url for language negotiation, CRM-7803
-      $this->userFrameworkBaseURL = CRM_Utils_System::languageNegotiationURL($this->userFrameworkBaseURL);
-
-      if (CRM_Utils_System::isSSL()) {
-        $this->userFrameworkBaseURL = str_replace('http://', 'https://', $this->userFrameworkBaseURL);
-      }
-    }
-
-    if (defined('CIVICRM_UF_DSN')) {
-      $this->userFrameworkDSN = CIVICRM_UF_DSN;
-    }
-
-    // this is dynamically figured out in the civicrm.settings.php file
-    if (defined('CIVICRM_CLEANURL')) {
-      $this->cleanURL = CIVICRM_CLEANURL;
-    }
-    else {
-      $this->cleanURL = 0;
-    }
+    $this->getRuntime()->setUserFramework($userFramework);
   }
-
   /**
    * Is back office credit card processing enabled for this site - ie are there any installed processors that support
    * it?
@@ -567,9 +450,4 @@ class CRM_Core_Config extends CRM_Core_Config_Variables {
     self::$_singleton = NULL;
   }
 
-  private function fatal($message) {
-    echo $message;
-    exit();
-  }
-
 }
index 3ea2982de58035fbeb526dd9b86dc4889169b61b..a89db3a5d9409bc024d16f66bf8ac69b35313c2e 100644 (file)
@@ -56,11 +56,11 @@ class CRM_Core_Config_Defaults {
   public static function setValues(&$defaults, $formMode = FALSE) {
   }
 
-  public static function getCustomCssUrl() {
+  public static function getCustomCssUrl($k = NULL) {
     return Civi::settings()->getUrl('customCSSURL', 'absolute');
   }
 
-  public static function getCustomFileUploadDir() {
+  public static function getCustomFileUploadDir($k = NULL) {
     $settings = Civi::settings();
     $value = $settings->getPath('customFileUploadDir');
     if (empty($value)) {
@@ -74,23 +74,23 @@ class CRM_Core_Config_Defaults {
   }
 
 
-  public static function getCustomPhpPathDir() {
+  public static function getCustomPhpPathDir($k = NULL) {
     return Civi::settings()->getPath('customPHPPathDir');
   }
 
-  public static function getCustomTemplateDir() {
+  public static function getCustomTemplateDir($k = NULL) {
     return Civi::settings()->getPath('customTemplateDir');
   }
 
-  public static function getExtensionsUrl() {
+  public static function getExtensionsUrl($k = NULL) {
     return Civi::settings()->getUrl('extensionsURL', 'absolute');
   }
 
-  public static function getExtensionsDir() {
+  public static function getExtensionsDir($k = NULL) {
     return Civi::settings()->getPath('extensionsDir');
   }
 
-  public static function getImageUploadDir() {
+  public static function getImageUploadDir($k = NULL) {
     $settings = Civi::settings();
     $value = $settings->getPath('imageUploadDir');
     if (empty($value)) {
@@ -102,7 +102,7 @@ class CRM_Core_Config_Defaults {
     return $value;
   }
 
-  public static function getImageUploadUrl() {
+  public static function getImageUploadUrl($k = NULL) {
     $settings = Civi::settings();
     $imageUploadURL = $settings->getUrl('imageUploadURL', 'absolute');
     if (empty($imageUploadURL)) {
@@ -112,7 +112,7 @@ class CRM_Core_Config_Defaults {
     return $imageUploadURL;
   }
 
-  public static function getUploadDir() {
+  public static function getUploadDir($k = NULL) {
     $settings = Civi::settings();
     $value = $settings->getPath('uploadDir');
     if (empty($value)) {
@@ -125,7 +125,7 @@ class CRM_Core_Config_Defaults {
     return $value;
   }
 
-  public static function getUserFrameworkResourceUrl() {
+  public static function getUserFrameworkResourceUrl($k = NULL) {
     $settings = Civi::settings();
     $url = $settings->getUrl('userFrameworkResourceURL', 'absolute');
     if (empty($url)) {
@@ -136,7 +136,7 @@ class CRM_Core_Config_Defaults {
     return $url;
   }
 
-  public static function getResourceBase() {
+  public static function getResourceBase($k = NULL) {
     $settings = Civi::settings();
     $url = $settings->getUrl('userFrameworkResourceURL', 'relative');
     if (empty($url)) {
@@ -147,9 +147,21 @@ class CRM_Core_Config_Defaults {
     return $url;
   }
 
-  public static function getDefaultCurrencySymbol() {
+  public static function getDefaultCurrencySymbol($k = NULL) {
     $config = CRM_Core_Config::singleton();
     return $config->defaultCurrencySymbol(Civi::settings()->get('defaultCurrency'));
   }
 
+  public static function setPath($key, $value) {
+    Civi::settings()->setPath($key, $value);
+  }
+
+  public static function setUrl($key, $value) {
+    Civi::settings()->setPath($key, $value);
+  }
+
+  public static function revert($key) {
+    Civi::settings()->revert($key);
+  }
+
 }
diff --git a/CRM/Core/Config/MagicMerge.php b/CRM/Core/Config/MagicMerge.php
new file mode 100644 (file)
index 0000000..a1bd9c2
--- /dev/null
@@ -0,0 +1,320 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 4.7                                                |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2015                                |
+ +--------------------------------------------------------------------+
+ | This file is a part of CiviCRM.                                    |
+ |                                                                    |
+ | CiviCRM is free software; you can copy, modify, and distribute it  |
+ | under the terms of the GNU Affero General Public License           |
+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
+ |                                                                    |
+ | CiviCRM is distributed in the hope that it will be useful, but     |
+ | WITHOUT ANY WARRANTY; without even the implied warranty of         |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
+ | See the GNU Affero General Public License for more details.        |
+ |                                                                    |
+ | You should have received a copy of the GNU Affero General Public   |
+ | License and the CiviCRM Licensing Exception along                  |
+ | with this program; if not, contact CiviCRM LLC                     |
+ | at info[AT]civicrm[DOT]org. If you have questions about the        |
+ | GNU Affero General Public License or the licensing of CiviCRM,     |
+ | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * Class CRM_Core_Config_MagicMerge
+ *
+ * Originally, the $config object was based on a single, serialized
+ * data object stored in the database. As the needs for settings
+ * grew (with robust metadata, system overrides, and extension support),
+ * the $config started to store a mix of:
+ *   (a) canonical config options,
+ *   (b) dynamically generated runtime data,
+ *   (c) cached data derived from other sources (esp civicrm_setting)
+ *   (d) instances of service objects
+ *
+ * The config object is now deprecated. Settings and service objects
+ * should generally be accessed via Civi::settings() and Civi::service().
+ *
+ * MagicMerge provides backward compatibility. You may still access
+ * old properties via $config, but they will be loaded from their
+ * new services.
+ */
+class CRM_Core_Config_MagicMerge {
+
+  /**
+   * Map old config properties to their contemporary counterparts.
+   *
+   * @var array
+   *   Array(string $configAlias => Array(string $realType, string $realName)).
+   */
+  private $map;
+
+  private $runtime, $locals;
+
+  public function __construct() {
+    $this->map = self::getPropertyMap();
+  }
+
+  public function __wakeup() {
+    $this->map = self::getPropertyMap();
+  }
+
+  /**
+   * @return array
+   */
+  public static function getPropertyMap() {
+    return array(
+      'backtrace' => array('setting', 'backtrace'),
+      'countryLimit' => array('setting', 'countryLimit'),
+      'dashboardCacheTimeout' => array('setting', 'dashboardCacheTimeout'),
+      'dateInputFormat' => array('setting', 'dateInputFormat'),
+      'dateformatDatetime' => array('setting', 'dateformatDatetime'),
+      'dateformatFull' => array('setting', 'dateformatFull'),
+      'dateformatPartial' => array('setting', 'dateformatPartial'),
+      'dateformatTime' => array('setting', 'dateformatTime'),
+      'dateformatYear' => array('setting', 'dateformatYear'),
+      'debug' => array('setting', 'debug_enabled'), // renamed.
+      'defaultContactCountry' => array('setting', 'defaultContactCountry'),
+      'defaultContactStateProvince' => array('setting', 'defaultContactStateProvince'),
+      'defaultCurrency' => array('setting', 'defaultCurrency'),
+      'defaultSearchProfileID' => array('setting', 'defaultSearchProfileID'),
+      'doNotAttachPDFReceipt' => array('setting', 'doNotAttachPDFReceipt'),
+      'empoweredBy' => array('setting', 'empoweredBy'),
+      'enableComponents' => array('setting', 'enable_components'), // renamed.
+      'enableSSL' => array('setting', 'enableSSL'),
+      'fatalErrorHandler' => array('setting', 'fatalErrorHandler'),
+      'fieldSeparator' => array('setting', 'fieldSeparator'),
+      'fiscalYearStart' => array('setting', 'fiscalYearStart'),
+      'geoAPIKey' => array('setting', 'geoAPIKey'),
+      'geoProvider' => array('setting', 'geoProvider'),
+      'includeAlphabeticalPager' => array('setting', 'includeAlphabeticalPager'),
+      'includeEmailInName' => array('setting', 'includeEmailInName'),
+      'includeNickNameInName' => array('setting', 'includeNickNameInName'),
+      'includeOrderByClause' => array('setting', 'includeOrderByClause'),
+      'includeWildCardInName' => array('setting', 'includeWildCardInName'),
+      'inheritLocale' => array('setting', 'inheritLocale'),
+      'languageLimit' => array('setting', 'languageLimit'),
+      'lcMessages' => array('setting', 'lcMessages'),
+      'legacyEncoding' => array('setting', 'legacyEncoding'),
+      'logging' => array('setting', 'logging'),
+      'mailThrottleTime' => array('setting', 'mailThrottleTime'),
+      'mailerBatchLimit' => array('setting', 'mailerBatchLimit'),
+      'mailerJobSize' => array('setting', 'mailerJobSize'),
+      'mailerJobsMax' => array('setting', 'mailerJobsMax'),
+      'mapAPIKey' => array('setting', 'mapAPIKey'),
+      'mapProvider' => array('setting', 'mapProvider'),
+      'maxFileSize' => array('setting', 'maxFileSize'),
+      'maxAttachments' => array('setting', 'max_attachments'), // renamed.
+      'monetaryDecimalPoint' => array('setting', 'monetaryDecimalPoint'),
+      'monetaryThousandSeparator' => array('setting', 'monetaryThousandSeparator'),
+      'moneyformat' => array('setting', 'moneyformat'),
+      'moneyvalueformat' => array('setting', 'moneyvalueformat'),
+      'provinceLimit' => array('setting', 'provinceLimit'),
+      'recaptchaOptions' => array('setting', 'recaptchaOptions'),
+      'recaptchaPublicKey' => array('setting', 'recaptchaPublicKey'),
+      'recaptchaPrivateKey' => array('setting', 'recaptchaPrivateKey'),
+      'secondDegRelPermissions' => array('setting', 'secondDegRelPermissions'),
+      'smartGroupCacheTimeout' => array('setting', 'smartGroupCacheTimeout'),
+      'timeInputFormat' => array('setting', 'timeInputFormat'),
+      'userFrameworkLogging' => array('setting', 'userFrameworkLogging'),
+      'userFrameworkUsersTableName' => array('setting', 'userFrameworkUsersTableName'),
+      'verpSeparator' => array('setting', 'verpSeparator'),
+      'wkhtmltopdfPath' => array('setting', 'wkhtmltopdfPath'),
+      'wpBasePage' => array('setting', 'wpBasePage'),
+      'wpLoadPhp' => array('setting', 'wpLoadPhp'),
+
+      'doNotResetCache' => array('local', 'doNotResetCache'),
+      'inCiviCRM' => array('local', 'inCiviCRM'),
+      'userFrameworkFrontend' => array('local', 'userFrameworkFrontend'),
+      'initialized' => array('local', 'initialized'),
+
+      'dsn' => array('runtime', 'dsn'),
+      'userFramework' => array('runtime', 'userFramework'),
+      'userFrameworkBaseURL' => array('runtime', 'userFrameworkBaseURL'),
+      'userFrameworkClass' => array('runtime', 'userFrameworkClass'),
+      'userFrameworkDSN' => array('runtime', 'userFrameworkDSN'),
+      'useFrameworkRelativeBase' => array('runtime', 'useFrameworkRelativeBase'),
+      'userFrameworkURLVar' => array('runtime', 'userFrameworkURLVar'),
+      'userPermissionClass' => array('runtime', 'userPermissionClass'),
+      'userPermissionTemp' => array('runtime', 'userPermissionTemp'),
+      'userSystem' => array('runtime', 'userSystem'),
+      'userHookClass' => array('runtime', 'userHookClass'),
+      'cleanURL' => array('runtime', 'cleanURL'),
+      'configAndLogDir' => array('runtime', 'configAndLogDir'),
+      'templateCompileDir' => array('runtime', 'templateCompileDir'),
+      'templateDir' => array('runtime', 'templateDir'),
+
+      'customFileUploadDir' => array('callback', 'CRM_Core_Config_Defaults', 'getCustomFileUploadDir', 'setPath', 'revert'),
+      'customPHPPathDir' => array('callback', 'CRM_Core_Config_Defaults', 'getCustomPhpPathDir', 'setPath', 'revert'),
+      'customTemplateDir' => array('callback', 'CRM_Core_Config_Defaults', 'getCustomTemplateDir', 'setPath', 'revert'),
+      'extensionsDir' => array('callback', 'CRM_Core_Config_Defaults', 'getExtensionsDir', 'setPath', 'revert'),
+      'imageUploadDir' => array('callback', 'CRM_Core_Config_Defaults', 'getImageUploadDir', 'setPath', 'revert'),
+      'uploadDir' => array('callback', 'CRM_Core_Config_Defaults', 'getUploadDir', 'setPath'),
+
+      'customCSSURL' => array('callback', 'CRM_Core_Config_Defaults', 'getCustomCssUrl', 'setUrl', 'revert'),
+      'extensionsURL' => array('callback', 'CRM_Core_Config_Defaults', 'getExtensionsUrl', 'setUrl', 'revert'),
+      'imageUploadURL' => array('callback', 'CRM_Core_Config_Defaults', 'getImageUploadUrl', 'setUrl', 'revert'),
+      'resourceBase' => array('callback', 'CRM_Core_Config_Defaults', 'getResourceBase', 'setUrl', 'revert'),
+      'userFrameworkResourceURL' => array('callback', 'CRM_Core_Config_Defaults', 'getUserFrameworkResourceUrl', 'setUrl', 'revert'),
+
+      'geocodeMethod' => array('callback', 'CRM_Utils_Geocode', 'getProviderClass'),
+      'defaultCurrencySymbol' => array('callback', 'CRM_Core_Config_Defaults', 'getDefaultCurrencySymbol'),
+      //'customFileUploadDir' => array('runtime', 'customFileUploadDir'),
+      //'customPHPPathDir' => array('runtime', 'customPHPPathDir'),
+      //'customTemplateDir' => array('runtime', 'customTemplateDir'),
+      //'extensionsDir' => array('runtime', 'extensionsDir'),
+      //'imageUploadDir' => array('runtime', 'imageUploadDir'),
+      //'uploadDir' => array('runtime', 'uploadDir'),
+      //
+      //'customCSSURL' => array('runtime', 'customCSSURL'),
+      //'extensionsURL' => array('runtime', 'extensionsURL'),
+      //'imageUploadURL' => array('runtime', 'imageUploadURL'),
+      //'resourceBase' => array('runtime', 'resourceBase'),
+      //'userFrameworkResourceURL' => array('runtime', 'userFrameworkResourceURL'),
+      //
+      //'geocodeMethod' => array('runtime', 'geocodeMethod'),
+      //'defaultCurrencySymbol' => array('runtime', 'defaultCurrencySymbol'),
+    );
+  }
+
+  public function __get($k) {
+    if (!isset($this->map[$k])) {
+      throw new \CRM_Core_Exception("Cannot read unrecognized property CRM_Core_Config::\${$k}.");
+    }
+    list ($type, $name) = $this->map[$k];
+
+    switch ($type) {
+      case 'setting':
+        return \Civi::settings()->get($name);
+
+      case 'setting-path':
+        return \Civi::settings()->getPath($name);
+
+      case 'setting-url':
+        return \Civi::settings()->getUrl($name, 'absolute');
+
+      case 'runtime':
+        return $this->getRuntime()->{$name};
+
+      case 'local':
+        $this->initLocals();
+        return $this->locals[$name];
+
+      case 'service':
+        return \Civi::service($name);
+
+      case 'callback':
+        // Array(0 => $type, 1 => $obj, 2 => $getter, 3 => $setter, 4 => $unsetter).
+        if (!isset($this->map[$k][1], $this->map[$k][2])) {
+          throw new \CRM_Core_Exception("Cannot find getter for property CRM_Core_Config::\${$k}");
+        }
+        return \Civi\Core\Resolver::singleton()->call(array($this->map[$k][1], $this->map[$k][2]), array($k));
+
+      default:
+        throw new \CRM_Core_Exception("Cannot read property CRM_Core_Config::\${$k} ($type)");
+    }
+  }
+
+  public function __set($k, $v) {
+    if (!isset($this->map[$k])) {
+      throw new \CRM_Core_Exception("Cannot set unrecognized property CRM_Core_Config::\${$k}");
+    }
+    list ($type, $name) = $this->map[$k];
+
+    switch ($type) {
+      case 'setting':
+        \Civi::settings()->set($name, $v);
+        return;
+
+      case 'setting-path':
+        \Civi::settings()->setPath($name, $v);
+        return;
+
+      case 'setting-url':
+        \Civi::settings()->setUrl($name, $v);
+        return;
+
+      case 'runtime':
+        $this->getRuntime()->{$name} = $v;
+        return;
+
+      case 'local':
+        $this->initLocals();
+        $this->locals[$name] = $v;
+        return;
+
+      case 'callback':
+        // Array(0 => $type, 1 => $obj, 2 => $getter, 3 => $setter, 4 => $unsetter).
+        if (!isset($this->map[$k][1], $this->map[$k][3])) {
+          throw new \CRM_Core_Exception("Cannot find setter for property CRM_Core_Config::\${$k}");
+        }
+        \Civi\Core\Resolver::singleton()->call(array($this->map[$k][1], $this->map[$k][3]), array($k, $v));
+        return;
+
+      default:
+        throw new \CRM_Core_Exception("Cannot set property CRM_Core_Config::\${$k} ($type)");
+    }
+  }
+
+  public function __isset($k) {
+    return isset($this->map[$k]);
+  }
+
+  public function __unset($k) {
+    if (!isset($this->map[$k])) {
+      throw new \CRM_Core_Exception("Cannot unset unrecognized property CRM_Core_Config::\${$k}");
+    }
+    list ($type, $name) = $this->map[$k];
+
+    switch ($type) {
+      case 'setting':
+      case 'setting-path':
+      case 'setting-url':
+        \Civi::settings()->revert($k);
+        return;
+
+      case 'local':
+        $this->initLocals();
+        $this->locals[$name] = NULL;
+        return;
+
+      case 'callback':
+        // Array(0 => $type, 1 => $obj, 2 => $getter, 3 => $setter, 4 => $unsetter).
+        if (!isset($this->map[$k][1], $this->map[$k][4])) {
+          throw new \CRM_Core_Exception("Cannot find unsetter for property CRM_Core_Config::\${$k}");
+        }
+        \Civi\Core\Resolver::singleton()->call(array($this->map[$k][1], $this->map[$k][4]), array($k));
+        return;
+
+      default:
+        throw new \CRM_Core_Exception("Cannot unset property CRM_Core_Config::\${$k} ($type)");
+    }
+  }
+
+  /**
+   * @return CRM_Core_Config_Runtime
+   */
+  protected function getRuntime() {
+    if ($this->runtime === NULL) {
+      $this->runtime = new CRM_Core_Config_Runtime();
+    }
+    return $this->runtime;
+  }
+
+  private function initLocals() {
+    if ($this->locals === NULL) {
+      $this->locals = array(
+        'inCiviCRM' => FALSE,
+        'doNotResetCache' => 0,
+        'initialized' => FALSE,
+        'userFrameworkFrontend' => FALSE,
+      );
+    }
+  }
+
+}
diff --git a/CRM/Core/Config/Runtime.php b/CRM/Core/Config/Runtime.php
new file mode 100644 (file)
index 0000000..bd68943
--- /dev/null
@@ -0,0 +1,221 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 4.7                                                |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2015                                |
+ +--------------------------------------------------------------------+
+ | This file is a part of CiviCRM.                                    |
+ |                                                                    |
+ | CiviCRM is free software; you can copy, modify, and distribute it  |
+ | under the terms of the GNU Affero General Public License           |
+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
+ |                                                                    |
+ | CiviCRM is distributed in the hope that it will be useful, but     |
+ | WITHOUT ANY WARRANTY; without even the implied warranty of         |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
+ | See the GNU Affero General Public License for more details.        |
+ |                                                                    |
+ | You should have received a copy of the GNU Affero General Public   |
+ | License and the CiviCRM Licensing Exception along                  |
+ | with this program; if not, contact CiviCRM LLC                     |
+ | at info[AT]civicrm[DOT]org. If you have questions about the        |
+ | GNU Affero General Public License or the licensing of CiviCRM,     |
+ | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * Class CRM_Core_Config_Runtime
+ *
+ * The runtime describes the environment in which CiviCRM executes -- ie
+ * the DSN, CMS type, CMS URL, etc. Generally, runtime properties must be
+ * determined externally (before loading CiviCRM).
+ */
+class CRM_Core_Config_Runtime {
+
+  public $dsn;
+
+  /**
+   * The name of user framework
+   *
+   * @var string
+   */
+  public $userFramework;
+
+  public $userFrameworkBaseURL;
+
+  public $userFrameworkClass;
+
+  /**
+   * The dsn of the database connection for user framework
+   *
+   * @var string
+   */
+  public $userFrameworkDSN;
+
+  /**
+   * The name of user framework url variable name
+   *
+   * @var string
+   */
+  public $userFrameworkURLVar = 'q';
+
+  public $useFrameworkRelativeBase;
+
+  public $userHookClass;
+
+  public $userPermissionClass;
+
+  /**
+   * Manager for temporary permissions.
+   * @todo move to container
+   *
+   * @var CRM_Core_Permission_Temp
+   */
+  public $userPermissionTemp;
+
+  /**
+   * The connector module for the CMS/UF
+   * @todo Introduce an interface.
+   * @todo move to container
+   *
+   * @var CRM_Utils_System_Base
+   */
+  public $userSystem;
+
+  /**
+   * Are we generating clean url's and using mod_rewrite
+   * @var string
+   */
+  public $cleanURL;
+
+  /**
+   * @var string
+   */
+  public $configAndLogDir;
+
+  public $templateCompileDir;
+
+  /**
+   * The root directory of our template tree.
+   * @var string
+   */
+  public $templateDir;
+
+  //public $customFileUploadDir, $customPHPPathDir, $customTemplateDir, $extensionsDir, $imageUploadDir, $resourceBase, $uploadDir;
+  //public $userFrameworkResourceURL, $customCSSURL, $extensionsURL, $imageUploadURL;
+  //public $geocodeMethod, $defaultCurrencySymbol;
+
+  /**
+   * @param bool $loadFromDB
+   */
+  public function initialize($loadFromDB = TRUE) {
+    if (!defined('CIVICRM_DSN') && $loadFromDB) {
+      $this->fatal('You need to define CIVICRM_DSN in civicrm.settings.php');
+    }
+    $this->dsn = defined('CIVICRM_DSN') ? CIVICRM_DSN : NULL;
+
+    if (!defined('CIVICRM_TEMPLATE_COMPILEDIR') && $loadFromDB) {
+      $this->fatal('You need to define CIVICRM_TEMPLATE_COMPILEDIR in civicrm.settings.php');
+    }
+
+    if (defined('CIVICRM_TEMPLATE_COMPILEDIR')) {
+      $this->configAndLogDir = CRM_Utils_File::baseFilePath() . 'ConfigAndLog' . DIRECTORY_SEPARATOR;
+      CRM_Utils_File::createDir($this->configAndLogDir);
+      CRM_Utils_File::restrictAccess($this->configAndLogDir);
+
+      $this->templateCompileDir = defined('CIVICRM_TEMPLATE_COMPILEDIR') ? CRM_Utils_File::addTrailingSlash(CIVICRM_TEMPLATE_COMPILEDIR) : NULL;
+      CRM_Utils_File::createDir($this->templateCompileDir);
+      CRM_Utils_File::restrictAccess($this->templateCompileDir);
+    }
+
+    CRM_Core_DAO::init($this->dsn);
+
+    if (!defined('CIVICRM_UF')) {
+      $this->fatal('You need to define CIVICRM_UF in civicrm.settings.php');
+    }
+    $this->setUserFramework(CIVICRM_UF);
+
+    $this->templateDir = array(dirname(dirname(dirname(__DIR__))) . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR);
+    //if ($loadFromDB) {
+    //  // //$this->enableComponents = \Civi::settings()->get('enable_components');
+    //
+    //  $this->customFileUploadDir = CRM_Core_Config_Defaults::getCustomFileUploadDir();
+    //  $this->customPHPPathDir = CRM_Core_Config_Defaults::getCustomPhpPathDir();
+    //  $this->customTemplateDir = CRM_Core_Config_Defaults::getCustomTemplateDir();
+    //  $this->extensionsDir = CRM_Core_Config_Defaults::getExtensionsDir();
+    //  $this->imageUploadDir = CRM_Core_Config_Defaults::getImageUploadDir();
+    //  $this->uploadDir = CRM_Core_Config_Defaults::getUploadDir();
+    //
+    //  $this->resourceBase = CRM_Core_Config_Defaults::getResourceBase();
+    //  $this->useFrameworkRelativeBase = CRM_Core_Config_Defaults::getUserFrameworkRelativeBase();
+    //
+    //  $this->userFrameworkResourceURL = CRM_Core_Config_Defaults::getUserFrameworkResourceUrl();
+    //  $this->customCSSURL = CRM_Core_Config_Defaults::getCustomCssUrl();
+    //  $this->extensionsURL = CRM_Core_Config_Defaults::getExtensionsUrl();
+    //  $this->imageUploadURL = CRM_Core_Config_Defaults::getImageUploadUrl();
+    //
+    //  $this->geocodeMethod = CRM_Utils_Geocode::getProviderClass();
+    //  $this->defaultCurrencySymbol = CRM_Core_Config_Defaults::getDefaultCurrencySymbol();
+    //}
+
+    if (CRM_Utils_System::isSSL()) {
+      $this->userSystem->mapConfigToSSL();
+    }
+
+    if (isset($this->customPHPPathDir) && $this->customPHPPathDir) {
+      set_include_path($this->customPHPPathDir . PATH_SEPARATOR . get_include_path());
+    }
+
+    $this->initialized = 1;
+  }
+
+  public function setUserFramework($userFramework) {
+    $this->userFramework = $userFramework;
+    $this->userFrameworkClass = 'CRM_Utils_System_' . $userFramework;
+    $this->userHookClass = 'CRM_Utils_Hook_' . $userFramework;
+    $userPermissionClass = 'CRM_Core_Permission_' . $userFramework;
+    $this->userPermissionClass = new $userPermissionClass();
+
+    $class = $this->userFrameworkClass;
+    $this->userSystem = new $class();
+
+    if ($userFramework == 'Joomla') {
+      $this->userFrameworkURLVar = 'task';
+    }
+
+    if (defined('CIVICRM_UF_BASEURL')) {
+      $this->userFrameworkBaseURL = CRM_Utils_File::addTrailingSlash(CIVICRM_UF_BASEURL, '/');
+
+      //format url for language negotiation, CRM-7803
+      $this->userFrameworkBaseURL = CRM_Utils_System::languageNegotiationURL($this->userFrameworkBaseURL);
+
+      if (CRM_Utils_System::isSSL()) {
+        $this->userFrameworkBaseURL = str_replace('http://', 'https://', $this->userFrameworkBaseURL);
+      }
+
+      $base = parse_url($this->userFrameworkBaseURL);
+      $this->useFrameworkRelativeBase = $base['path'];
+      //$this->useFrameworkRelativeBase = empty($base['path']) ? '/' : $base['path'];
+    }
+
+    if (defined('CIVICRM_UF_DSN')) {
+      $this->userFrameworkDSN = CIVICRM_UF_DSN;
+    }
+
+    // this is dynamically figured out in the civicrm.settings.php file
+    if (defined('CIVICRM_CLEANURL')) {
+      $this->cleanURL = CIVICRM_CLEANURL;
+    }
+    else {
+      $this->cleanURL = 0;
+    }
+  }
+
+  private function fatal($message) {
+    echo $message;
+    exit();
+  }
+
+}
index dc1c93ff1fefec215b58487899157e36a4c1ab1a..10fb69f97694da28bb044e9625bcc91ec4c0a084 100755 (executable)
@@ -396,19 +396,8 @@ class CiviUnitTestCase extends PHPUnit_Extensions_Database_TestCase {
     // "initialize" CiviCRM to avoid problems when running single tests
     // FIXME: look at it closer in second stage
 
-    // initialize the object once db is loaded
-    $config = CRM_Core_Config::singleton();
-    \Civi::reset();
-
-    // when running unit tests, use mockup user framework
-    $config->setUserFramework('UnitTests');
-    $this->hookClass = CRM_Utils_Hook::singleton(TRUE);
-    // also fix the fatal error handler to throw exceptions,
-    // rather than exit
-    $config->fatalErrorHandler = 'CiviUnitTestCase_fatalErrorHandler';
-
-    // enable backtrace to get meaningful errors
-    $config->backtrace = 1;
+    $GLOBALS['civicrm_setting']['domain']['fatalErrorHandler'] = 'CiviUnitTestCase_fatalErrorHandler';
+    $GLOBALS['civicrm_setting']['domain']['backtrace'] = 1;
 
     // disable any left-over test extensions
     CRM_Core_DAO::executeQuery('DELETE FROM civicrm_extension WHERE full_name LIKE "test.%"');
@@ -416,13 +405,20 @@ class CiviUnitTestCase extends PHPUnit_Extensions_Database_TestCase {
     // reset all the caches
     CRM_Utils_System::flushCache();
 
+    // initialize the object once db is loaded
+    \Civi::reset();
+    $config = CRM_Core_Config::singleton(TRUE, TRUE); // ugh, performance
+
+    // when running unit tests, use mockup user framework
+    $config->setUserFramework('UnitTests');
+    $this->hookClass = CRM_Utils_Hook::singleton(TRUE);
+
     // Make sure the DB connection is setup properly
     $config->userSystem->setMySQLTimeZone();
     $env = new CRM_Utils_Check_Env();
     CRM_Utils_Check::singleton()->assertValid($env->checkMysqlTime());
 
     // clear permissions stub to not check permissions
-    $config = CRM_Core_Config::singleton();
     $config->userPermissionClass->permissions = NULL;
 
     //flush component settings