Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'core/Config.php')
-rw-r--r--core/Config.php898
1 files changed, 428 insertions, 470 deletions
diff --git a/core/Config.php b/core/Config.php
index 78d236d4ac..e906311306 100644
--- a/core/Config.php
+++ b/core/Config.php
@@ -30,7 +30,7 @@
* Piwik_Config::getInstance()->branding = $brandingConfig;
*
* Example setting an option within a section in the configuration:
- *
+ *
* $brandingConfig = Piwik_Config::getInstance()->branding;
* $brandingConfig['use_custom_logo'] = 1;
* Piwik_Config::getInstance()->branding = $brandingConfig;
@@ -40,473 +40,431 @@
*/
class Piwik_Config
{
- static private $instance = null;
-
- /**
- * Returns the singleton Piwik_Config
- *
- * @return Piwik_Config
- */
- static public function getInstance()
- {
- if (self::$instance == null)
- {
- self::$instance = new self;
- }
- return self::$instance;
- }
-
- /**
- * Contains configuration files values
- *
- * @var array
- */
- protected $initialized = false;
- protected $configGlobal = array();
- protected $configLocal = array();
- protected $configCache = array();
- protected $pathGlobal = null;
- protected $pathLocal = null;
-
- protected function __construct()
- {
- $this->pathGlobal = self::getGlobalConfigPath();
- $this->pathLocal = self::getLocalConfigPath();
- }
-
- /**
- * @var boolean
- */
- protected $isTest = false;
-
- /**
- * Enable test environment
- *
- * @param string $pathLocal
- * @param string $pathGlobal
- */
- public function setTestEnvironment($pathLocal = null, $pathGlobal = null)
- {
- $this->isTest = true;
-
- $this->clear();
-
- if ($pathLocal)
- {
- $this->pathLocal = $pathLocal;
- }
-
- if ($pathGlobal)
- {
- $this->pathGlobal = $pathGlobal;
- }
-
- $this->init();
- if(isset($this->configGlobal['database_tests'])
- || isset($this->configLocal['database_tests']))
- {
- $this->__get('database_tests');
- $this->configCache['database'] = $this->configCache['database_tests'];
- }
-
- // Ensure local mods do not affect tests
- if(is_null($pathGlobal))
- {
- $this->configCache['Debug'] = $this->configGlobal['Debug'];
- $this->configCache['branding'] = $this->configGlobal['branding'];
- $this->configCache['mail'] = $this->configGlobal['mail'];
- $this->configCache['General'] = $this->configGlobal['General'];
- $this->configCache['Segments'] = $this->configGlobal['Segments'];
- $this->configCache['Tracker'] = $this->configGlobal['Tracker'];
- $this->configCache['Deletelogs'] = $this->configGlobal['Deletelogs'];
- }
-
- // for unit tests, we set that no plugin is installed. This will force
- // the test initialization to create the plugins tables, execute ALTER queries, etc.
- $this->configCache['PluginsInstalled'] = array('PluginsInstalled' => array());
- }
-
- /**
- * Returns absolute path to the global configuration file
- *
- * @return string
- */
- static public function getGlobalConfigPath()
- {
- return PIWIK_USER_PATH .'/config/global.ini.php';
- }
-
- /**
- * Backward compatibility stub
- *
- * @todo remove in 2.0
- * @since 1.7
- * @deprecated 1.7
- * @return string
- */
- static public function getDefaultDefaultConfigPath()
- {
- return self::getGlobalConfigPath();
- }
-
- /**
- * Returns absolute path to the local configuration file
- *
- * @return string
- */
- static public function getLocalConfigPath()
- {
- return PIWIK_USER_PATH .'/config/config.ini.php';
- }
-
- /**
- * Is local configuration file writable?
- *
- * @return bool
- */
- public function isFileWritable()
- {
- return is_writable($this->pathLocal);
- }
-
- /**
- * Clear in-memory configuration so it can be reloaded
- */
- public function clear()
- {
- $this->configGlobal = array();
- $this->configLocal = array();
- $this->configCache = array();
- $this->initialized = false;
-
- $this->pathGlobal = self::getGlobalConfigPath();
- $this->pathLocal = self::getLocalConfigPath();
- }
-
- /**
- * Read configuration from files into memory
- *
- * @throws Exception if local config file is not readable; exits for other errors
- */
- public function init()
- {
- $this->initialized = true;
- $reportError = empty($GLOBALS['PIWIK_TRACKER_MODE']);
-
- // read defaults from global.ini.php
- if(!is_readable($this->pathGlobal) && $reportError)
- {
- Piwik_ExitWithMessage(Piwik_TranslateException('General_ExceptionConfigurationFileNotFound', array($this->pathGlobal)));
- }
-
- $this->configGlobal = _parse_ini_file($this->pathGlobal, true);
- if(empty($this->configGlobal) && $reportError)
- {
- Piwik_ExitWithMessage(Piwik_TranslateException('General_ExceptionUnreadableFileDisabledMethod', array($this->pathGlobal, "parse_ini_file()")));
- }
-
- // read the local settings from config.ini.php
- if(!is_readable($this->pathLocal) && $reportError)
- {
- throw new Exception(Piwik_TranslateException('General_ExceptionConfigurationFileNotFound', array($this->pathLocal)));
- }
-
- $this->configLocal = _parse_ini_file($this->pathLocal, true);
- if(empty($this->configLocal) && $reportError)
- {
- Piwik_ExitWithMessage(Piwik_TranslateException('General_ExceptionUnreadableFileDisabledMethod', array($this->pathLocal, "parse_ini_file()")));
- }
- }
-
- /**
- * Decode HTML entities
- *
- * @param mixed $values
- * @return mixed
- */
- protected function decodeValues($values)
- {
- if(is_array($values))
- {
- foreach($values as &$value)
- {
- $value = $this->decodeValues($value);
- }
- }
- else
- {
- $values = html_entity_decode($values, ENT_COMPAT, 'UTF-8');
- }
- return $values;
- }
-
- /**
- * Encode HTML entities
- *
- * @param mixed $values
- * @return mixed
- */
- protected function encodeValues($values)
- {
- if(is_array($values))
- {
- foreach($values as &$value)
- {
- $value = $this->encodeValues($value);
- }
- }
- else
- {
- $values = htmlentities($values, ENT_COMPAT, 'UTF-8');
- }
- return $values;
- }
-
- /**
- * Magic get methods catching calls to $config->var_name
- * Returns the value if found in the configuration
- *
- * @param string $name
- * @return string|array The value requested, returned by reference
- * @throws Exception if the value requested not found in both files
- */
- public function &__get( $name )
- {
- if(!$this->initialized)
- {
- $this->init();
- }
-
- // check cache for merged section
- if (isset($this->configCache[$name]))
- {
- $tmp =& $this->configCache[$name];
- return $tmp;
- }
-
- $section = null;
-
- // merge corresponding sections from global and local settings
- if(isset($this->configGlobal[$name]))
- {
- $section = $this->configGlobal[$name];
- }
-
- if(isset($this->configLocal[$name]))
- {
- // local settings override the global defaults
- $section = $section
- ? array_merge($section, $this->configLocal[$name])
- : $this->configLocal[$name];
- }
-
- if ($section === null)
- {
- throw new Exception("Error while trying to read a specific config file entry <b>'$name'</b> from your configuration files.</b>If you just completed a Piwik upgrade, please check that the file config/global.ini.php was overwritten by the latest Piwik version.");
- }
-
- // cache merged section for later
- $this->configCache[$name] = $this->decodeValues($section);
- $tmp =& $this->configCache[$name];
-
- return $tmp;
- }
-
- /**
- * Set value
- *
- * @param string $name This corresponds to the section name
- * @param mixed $value
- */
- public function __set($name, $value)
- {
- $this->configCache[$name] = $value;
- }
-
- /**
- * Comparison function
- *
- * @param mixed $elem1
- * @param mixed $elem2
- * @return int;
- */
- static function compareElements($elem1, $elem2)
- {
- if (is_array($elem1))
- {
- if (is_array($elem2))
- {
- return strcmp(serialize($elem1), serialize($elem2));
- }
-
- return 1;
- }
-
- if (is_array($elem2))
- {
- return -1;
- }
-
- if ((string)$elem1 === (string)$elem2)
- {
- return 0;
- }
-
- return ((string)$elem1 > (string)$elem2) ? 1 : -1;
- }
-
- /**
- * Compare arrays and return difference, such that:
- *
- * $modified = array_merge($original, $difference);
- *
- * @param array $original original array
- * @param array $modified modified array
- * @return array differences between original and modified
- */
- public function array_unmerge($original, $modified)
- {
- // return key/value pairs for keys in $modified but not in $original
- // return key/value pairs for keys in both $modified and $original, but values differ
- // ignore keys that are in $original but not in $modified
-
- return array_udiff_assoc($modified, $original, array(__CLASS__, 'compareElements'));
- }
-
- /**
- * Dump config
- *
- * @param array $configLocal
- * @param array $configGlobal
- * @param array $configCache
- * @return string
- */
- public function dumpConfig($configLocal, $configGlobal, $configCache)
- {
- $dirty = false;
-
- $output = "; <?php exit; ?> DO NOT REMOVE THIS LINE\n";
- $output .= "; file automatically generated or modified by Piwik; you can manually override the default values in global.ini.php by redefining them in this file.\n";
-
- if ($configCache)
- {
- foreach($configLocal as $name => $section)
- {
- if (!isset($configCache[$name]))
- {
- $configCache[$name] = $this->decodeValues($section);
- }
- }
-
- $sectionNames = array_unique(array_merge(array_keys($configGlobal), array_keys($configCache)));
-
- foreach($sectionNames as $section)
- {
- if(!isset($configCache[$section]))
- {
- continue;
- }
-
- // Only merge if the section exists in global.ini.php (in case a section only lives in config.ini.php)
-
- // get local and cached config
- $local = isset($configLocal[$section]) ? $configLocal[$section] : array();
- $config = $configCache[$section];
-
- // remove default values from both (they should not get written to local)
- if (isset($configGlobal[$section]))
- {
- $config = $this->array_unmerge($configGlobal[$section], $configCache[$section]);
- $local = $this->array_unmerge($configGlobal[$section], $local);
- }
-
- // if either local/config have non-default values and the other doesn't,
- // OR both have values, but different values, we must write to config.ini.php
- if (empty($local) xor empty($config)
- || (!empty($local)
- && !empty($config)
- && self::compareElements($config, $configLocal[$section])))
- {
- $dirty = true;
- }
-
- // no point in writing empty sections, so skip if the cached section is empty
- if (empty($config))
- {
- continue;
- }
-
- $output .= "[$section]\n";
-
- foreach($config as $name => $value)
- {
- $value = $this->encodeValues($value);
-
- if(is_numeric($name))
- {
- $name = $section;
- $value = array($value);
- }
-
- if(is_array($value))
- {
- foreach($value as $currentValue)
- {
- $output .= $name."[] = \"$currentValue\"\n";
- }
- }
- else
- {
- if(!is_numeric($value))
- {
- $value = "\"$value\"";
- }
- $output .= $name.' = '.$value."\n";
- }
- }
-
- $output .= "\n";
- }
-
- if ($dirty)
- {
- return $output;
- }
- }
-
- return false;
- }
-
-
- /**
- * Write user configuration file
- *
- * @param array $configLocal
- * @param array $configGlobal
- * @param array $configCache
- * @param string $pathLocal
- */
- public function writeConfig($configLocal, $configGlobal, $configCache, $pathLocal)
- {
- if ($this->isTest)
- {
- return;
- }
-
- $output = $this->dumpConfig($configLocal, $configGlobal, $configCache);
- if ($output !== false)
- {
- @file_put_contents($pathLocal, $output);
- }
-
- $this->clear();
- }
-
- /**
- * Force save
- */
- public function forceSave()
- {
- $this->writeConfig($this->configLocal, $this->configGlobal, $this->configCache, $this->pathLocal);
- }
+ static private $instance = null;
+
+ /**
+ * Returns the singleton Piwik_Config
+ *
+ * @return Piwik_Config
+ */
+ static public function getInstance()
+ {
+ if (self::$instance == null) {
+ self::$instance = new self;
+ }
+ return self::$instance;
+ }
+
+ /**
+ * Contains configuration files values
+ *
+ * @var array
+ */
+ protected $initialized = false;
+ protected $configGlobal = array();
+ protected $configLocal = array();
+ protected $configCache = array();
+ protected $pathGlobal = null;
+ protected $pathLocal = null;
+
+ protected function __construct()
+ {
+ $this->pathGlobal = self::getGlobalConfigPath();
+ $this->pathLocal = self::getLocalConfigPath();
+ }
+
+ /**
+ * @var boolean
+ */
+ protected $isTest = false;
+
+ /**
+ * Enable test environment
+ *
+ * @param string $pathLocal
+ * @param string $pathGlobal
+ */
+ public function setTestEnvironment($pathLocal = null, $pathGlobal = null)
+ {
+ $this->isTest = true;
+
+ $this->clear();
+
+ if ($pathLocal) {
+ $this->pathLocal = $pathLocal;
+ }
+
+ if ($pathGlobal) {
+ $this->pathGlobal = $pathGlobal;
+ }
+
+ $this->init();
+ if (isset($this->configGlobal['database_tests'])
+ || isset($this->configLocal['database_tests'])
+ ) {
+ $this->__get('database_tests');
+ $this->configCache['database'] = $this->configCache['database_tests'];
+ }
+
+ // Ensure local mods do not affect tests
+ if (is_null($pathGlobal)) {
+ $this->configCache['Debug'] = $this->configGlobal['Debug'];
+ $this->configCache['branding'] = $this->configGlobal['branding'];
+ $this->configCache['mail'] = $this->configGlobal['mail'];
+ $this->configCache['General'] = $this->configGlobal['General'];
+ $this->configCache['Segments'] = $this->configGlobal['Segments'];
+ $this->configCache['Tracker'] = $this->configGlobal['Tracker'];
+ $this->configCache['Deletelogs'] = $this->configGlobal['Deletelogs'];
+ }
+
+ // for unit tests, we set that no plugin is installed. This will force
+ // the test initialization to create the plugins tables, execute ALTER queries, etc.
+ $this->configCache['PluginsInstalled'] = array('PluginsInstalled' => array());
+ }
+
+ /**
+ * Returns absolute path to the global configuration file
+ *
+ * @return string
+ */
+ static public function getGlobalConfigPath()
+ {
+ return PIWIK_USER_PATH . '/config/global.ini.php';
+ }
+
+ /**
+ * Backward compatibility stub
+ *
+ * @todo remove in 2.0
+ * @since 1.7
+ * @deprecated 1.7
+ * @return string
+ */
+ static public function getDefaultDefaultConfigPath()
+ {
+ return self::getGlobalConfigPath();
+ }
+
+ /**
+ * Returns absolute path to the local configuration file
+ *
+ * @return string
+ */
+ static public function getLocalConfigPath()
+ {
+ return PIWIK_USER_PATH . '/config/config.ini.php';
+ }
+
+ /**
+ * Is local configuration file writable?
+ *
+ * @return bool
+ */
+ public function isFileWritable()
+ {
+ return is_writable($this->pathLocal);
+ }
+
+ /**
+ * Clear in-memory configuration so it can be reloaded
+ */
+ public function clear()
+ {
+ $this->configGlobal = array();
+ $this->configLocal = array();
+ $this->configCache = array();
+ $this->initialized = false;
+
+ $this->pathGlobal = self::getGlobalConfigPath();
+ $this->pathLocal = self::getLocalConfigPath();
+ }
+
+ /**
+ * Read configuration from files into memory
+ *
+ * @throws Exception if local config file is not readable; exits for other errors
+ */
+ public function init()
+ {
+ $this->initialized = true;
+ $reportError = empty($GLOBALS['PIWIK_TRACKER_MODE']);
+
+ // read defaults from global.ini.php
+ if (!is_readable($this->pathGlobal) && $reportError) {
+ Piwik_ExitWithMessage(Piwik_TranslateException('General_ExceptionConfigurationFileNotFound', array($this->pathGlobal)));
+ }
+
+ $this->configGlobal = _parse_ini_file($this->pathGlobal, true);
+ if (empty($this->configGlobal) && $reportError) {
+ Piwik_ExitWithMessage(Piwik_TranslateException('General_ExceptionUnreadableFileDisabledMethod', array($this->pathGlobal, "parse_ini_file()")));
+ }
+
+ // read the local settings from config.ini.php
+ if (!is_readable($this->pathLocal) && $reportError) {
+ throw new Exception(Piwik_TranslateException('General_ExceptionConfigurationFileNotFound', array($this->pathLocal)));
+ }
+
+ $this->configLocal = _parse_ini_file($this->pathLocal, true);
+ if (empty($this->configLocal) && $reportError) {
+ Piwik_ExitWithMessage(Piwik_TranslateException('General_ExceptionUnreadableFileDisabledMethod', array($this->pathLocal, "parse_ini_file()")));
+ }
+ }
+
+ /**
+ * Decode HTML entities
+ *
+ * @param mixed $values
+ * @return mixed
+ */
+ protected function decodeValues($values)
+ {
+ if (is_array($values)) {
+ foreach ($values as &$value) {
+ $value = $this->decodeValues($value);
+ }
+ } else {
+ $values = html_entity_decode($values, ENT_COMPAT, 'UTF-8');
+ }
+ return $values;
+ }
+
+ /**
+ * Encode HTML entities
+ *
+ * @param mixed $values
+ * @return mixed
+ */
+ protected function encodeValues($values)
+ {
+ if (is_array($values)) {
+ foreach ($values as &$value) {
+ $value = $this->encodeValues($value);
+ }
+ } else {
+ $values = htmlentities($values, ENT_COMPAT, 'UTF-8');
+ }
+ return $values;
+ }
+
+ /**
+ * Magic get methods catching calls to $config->var_name
+ * Returns the value if found in the configuration
+ *
+ * @param string $name
+ * @return string|array The value requested, returned by reference
+ * @throws Exception if the value requested not found in both files
+ */
+ public function &__get($name)
+ {
+ if (!$this->initialized) {
+ $this->init();
+ }
+
+ // check cache for merged section
+ if (isset($this->configCache[$name])) {
+ $tmp =& $this->configCache[$name];
+ return $tmp;
+ }
+
+ $section = null;
+
+ // merge corresponding sections from global and local settings
+ if (isset($this->configGlobal[$name])) {
+ $section = $this->configGlobal[$name];
+ }
+
+ if (isset($this->configLocal[$name])) {
+ // local settings override the global defaults
+ $section = $section
+ ? array_merge($section, $this->configLocal[$name])
+ : $this->configLocal[$name];
+ }
+
+ if ($section === null) {
+ throw new Exception("Error while trying to read a specific config file entry <b>'$name'</b> from your configuration files.</b>If you just completed a Piwik upgrade, please check that the file config/global.ini.php was overwritten by the latest Piwik version.");
+ }
+
+ // cache merged section for later
+ $this->configCache[$name] = $this->decodeValues($section);
+ $tmp =& $this->configCache[$name];
+
+ return $tmp;
+ }
+
+ /**
+ * Set value
+ *
+ * @param string $name This corresponds to the section name
+ * @param mixed $value
+ */
+ public function __set($name, $value)
+ {
+ $this->configCache[$name] = $value;
+ }
+
+ /**
+ * Comparison function
+ *
+ * @param mixed $elem1
+ * @param mixed $elem2
+ * @return int;
+ */
+ static function compareElements($elem1, $elem2)
+ {
+ if (is_array($elem1)) {
+ if (is_array($elem2)) {
+ return strcmp(serialize($elem1), serialize($elem2));
+ }
+
+ return 1;
+ }
+
+ if (is_array($elem2)) {
+ return -1;
+ }
+
+ if ((string)$elem1 === (string)$elem2) {
+ return 0;
+ }
+
+ return ((string)$elem1 > (string)$elem2) ? 1 : -1;
+ }
+
+ /**
+ * Compare arrays and return difference, such that:
+ *
+ * $modified = array_merge($original, $difference);
+ *
+ * @param array $original original array
+ * @param array $modified modified array
+ * @return array differences between original and modified
+ */
+ public function array_unmerge($original, $modified)
+ {
+ // return key/value pairs for keys in $modified but not in $original
+ // return key/value pairs for keys in both $modified and $original, but values differ
+ // ignore keys that are in $original but not in $modified
+
+ return array_udiff_assoc($modified, $original, array(__CLASS__, 'compareElements'));
+ }
+
+ /**
+ * Dump config
+ *
+ * @param array $configLocal
+ * @param array $configGlobal
+ * @param array $configCache
+ * @return string
+ */
+ public function dumpConfig($configLocal, $configGlobal, $configCache)
+ {
+ $dirty = false;
+
+ $output = "; <?php exit; ?> DO NOT REMOVE THIS LINE\n";
+ $output .= "; file automatically generated or modified by Piwik; you can manually override the default values in global.ini.php by redefining them in this file.\n";
+
+ if ($configCache) {
+ foreach ($configLocal as $name => $section) {
+ if (!isset($configCache[$name])) {
+ $configCache[$name] = $this->decodeValues($section);
+ }
+ }
+
+ $sectionNames = array_unique(array_merge(array_keys($configGlobal), array_keys($configCache)));
+
+ foreach ($sectionNames as $section) {
+ if (!isset($configCache[$section])) {
+ continue;
+ }
+
+ // Only merge if the section exists in global.ini.php (in case a section only lives in config.ini.php)
+
+ // get local and cached config
+ $local = isset($configLocal[$section]) ? $configLocal[$section] : array();
+ $config = $configCache[$section];
+
+ // remove default values from both (they should not get written to local)
+ if (isset($configGlobal[$section])) {
+ $config = $this->array_unmerge($configGlobal[$section], $configCache[$section]);
+ $local = $this->array_unmerge($configGlobal[$section], $local);
+ }
+
+ // if either local/config have non-default values and the other doesn't,
+ // OR both have values, but different values, we must write to config.ini.php
+ if (empty($local) xor empty($config)
+ || (!empty($local)
+ && !empty($config)
+ && self::compareElements($config, $configLocal[$section]))
+ ) {
+ $dirty = true;
+ }
+
+ // no point in writing empty sections, so skip if the cached section is empty
+ if (empty($config)) {
+ continue;
+ }
+
+ $output .= "[$section]\n";
+
+ foreach ($config as $name => $value) {
+ $value = $this->encodeValues($value);
+
+ if (is_numeric($name)) {
+ $name = $section;
+ $value = array($value);
+ }
+
+ if (is_array($value)) {
+ foreach ($value as $currentValue) {
+ $output .= $name . "[] = \"$currentValue\"\n";
+ }
+ } else {
+ if (!is_numeric($value)) {
+ $value = "\"$value\"";
+ }
+ $output .= $name . ' = ' . $value . "\n";
+ }
+ }
+
+ $output .= "\n";
+ }
+
+ if ($dirty) {
+ return $output;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Write user configuration file
+ *
+ * @param array $configLocal
+ * @param array $configGlobal
+ * @param array $configCache
+ * @param string $pathLocal
+ */
+ public function writeConfig($configLocal, $configGlobal, $configCache, $pathLocal)
+ {
+ if ($this->isTest) {
+ return;
+ }
+
+ $output = $this->dumpConfig($configLocal, $configGlobal, $configCache);
+ if ($output !== false) {
+ @file_put_contents($pathLocal, $output);
+ }
+
+ $this->clear();
+ }
+
+ /**
+ * Force save
+ */
+ public function forceSave()
+ {
+ $this->writeConfig($this->configLocal, $this->configGlobal, $this->configCache, $this->pathLocal);
+ }
}