diff options
author | diosmosis <benaka@piwik.pro> | 2015-04-09 06:36:22 +0300 |
---|---|---|
committer | diosmosis <benaka@piwik.pro> | 2015-04-09 06:36:22 +0300 |
commit | 67829227ce2d0c4473466acbc42118a7a150b14c (patch) | |
tree | 973ebb1b5aa30d0b47a8d14ce73b7524a4051be0 /core | |
parent | 47e7d3a74c6b13431e489d2d652af53410f880ad (diff) |
Added environment validation system test (mostly failing) that tests Piwik's behavior when INI files are gone or corrupt from each Piwik endpoint (tracker/reporting UI/console). Hacked test code to make it possible and for some tests to pass.
Diffstat (limited to 'core')
-rw-r--r-- | core/Application/Environment.php | 2 | ||||
-rw-r--r-- | core/Application/Kernel/EnvironmentValidator.php | 14 | ||||
-rw-r--r-- | core/Application/Kernel/GlobalSettingsProvider/IniSettingsProvider.php | 48 | ||||
-rw-r--r-- | core/Application/Kernel/PluginList.php | 7 | ||||
-rw-r--r-- | core/Application/Kernel/PluginList/IniPluginList.php | 16 | ||||
-rw-r--r-- | core/Config.php | 105 | ||||
-rw-r--r-- | core/Config/IniFileChain.php | 7 | ||||
-rw-r--r-- | core/ExceptionHandler.php | 6 | ||||
-rw-r--r-- | core/Plugin/Manager.php | 5 | ||||
-rw-r--r-- | core/Translation/Translator.php | 3 |
10 files changed, 124 insertions, 89 deletions
diff --git a/core/Application/Environment.php b/core/Application/Environment.php index 38a6c2eb5c..6687b015c4 100644 --- a/core/Application/Environment.php +++ b/core/Application/Environment.php @@ -150,6 +150,8 @@ class Environment */ protected function getGlobalSettings() { + // TODO: need to be able to set path global/local/etc. which is in DI... for now works because TestingEnvironment creates + // singleton instance before this method. return IniSettingsProvider::getSingletonInstance(); } diff --git a/core/Application/Kernel/EnvironmentValidator.php b/core/Application/Kernel/EnvironmentValidator.php index 9474652ac9..9e116a7cb1 100644 --- a/core/Application/Kernel/EnvironmentValidator.php +++ b/core/Application/Kernel/EnvironmentValidator.php @@ -12,6 +12,7 @@ use Piwik\Application\Kernel\GlobalSettingsProvider\IniSettingsProvider; use Piwik\Common; use Piwik\Piwik; use Piwik\SettingsServer; +use Piwik\Translate; use Piwik\Translation\Translator; /** @@ -33,6 +34,7 @@ class EnvironmentValidator public function __construct(GlobalSettingsProvider $settingsProvider, Translator $translator) { $this->iniSettingsProvider = $settingsProvider; + $this->translator = $translator; } public function validate() @@ -40,23 +42,23 @@ class EnvironmentValidator $inTrackerRequest = SettingsServer::isTrackerApiRequest(); $inConsole = Common::isPhpCliMode(); - $this->checkConfigFileExists('global.ini.php'); - $this->checkConfigFileExists('config.ini.php', $startInstaller = !$inTrackerRequest && !$inConsole); + $this->checkConfigFileExists($this->iniSettingsProvider->getPathGlobal()); + $this->checkConfigFileExists($this->iniSettingsProvider->getPathLocal(), $startInstaller = !$inTrackerRequest && !$inConsole); } /** - * @param $filename + * @param $path * @param bool $startInstaller * @throws \Exception */ - private function checkConfigFileExists($filename, $startInstaller = false) + private function checkConfigFileExists($path, $startInstaller = false) { - $path = PIWIK_INCLUDE_PATH . '/config/' . $filename; - if (is_readable($path)) { return; } + Translate::loadAllTranslations(); + $message = $this->translator->translate('General_ExceptionConfigurationFileNotFound', array($path)); $exception = new \Exception($message); diff --git a/core/Application/Kernel/GlobalSettingsProvider/IniSettingsProvider.php b/core/Application/Kernel/GlobalSettingsProvider/IniSettingsProvider.php index 07dd25606e..75123b1645 100644 --- a/core/Application/Kernel/GlobalSettingsProvider/IniSettingsProvider.php +++ b/core/Application/Kernel/GlobalSettingsProvider/IniSettingsProvider.php @@ -28,17 +28,42 @@ class IniSettingsProvider implements GlobalSettingsProvider private $iniFileChain; /** + * @var string + */ + protected $pathGlobal = null; + + /** + * @var string + */ + protected $pathCommon = null; + + /** + * @var string + */ + protected $pathLocal = null; + + /** * @param string|null $pathGlobal Path to the global.ini.php file. Or null to use the default. * @param string|null $pathLocal Path to the config.ini.php file. Or null to use the default. * @param string|null $pathCommon Path to the common.ini.php file. Or null to use the default. */ public function __construct($pathGlobal = null, $pathLocal = null, $pathCommon = null) { - $pathGlobal = $pathGlobal ?: Config::getGlobalConfigPath(); - $pathCommon = $pathCommon ?: Config::getCommonConfigPath(); - $pathLocal = $pathLocal ?: Config::getLocalConfigPath(); + $this->pathGlobal = $pathGlobal ?: Config::getGlobalConfigPath(); + $this->pathCommon = $pathCommon ?: Config::getCommonConfigPath(); + $this->pathLocal = $pathLocal ?: Config::getLocalConfigPath(); + + $this->iniFileChain = new IniFileChain(); + $this->reload(); + } + + public function reload($pathGlobal = null, $pathLocal = null, $pathCommon = null) + { + $this->pathGlobal = $pathGlobal ?: $this->pathGlobal; + $this->pathCommon = $pathCommon ?: $this->pathCommon; + $this->pathLocal = $pathLocal ?: $this->pathLocal; - $this->iniFileChain = new IniFileChain(array($pathGlobal, $pathCommon), $pathLocal); + $this->iniFileChain->reload(array($this->pathGlobal, $this->pathCommon), $this->pathLocal); } public function &getSection($name) @@ -57,6 +82,21 @@ class IniSettingsProvider implements GlobalSettingsProvider return $this->iniFileChain; } + public function getPathGlobal() + { + return $this->pathGlobal; + } + + public function getPathLocal() + { + return $this->pathLocal; + } + + public function getPathCommon() + { + return $this->pathCommon; + } + public static function getSingletonInstance($pathGlobal = null, $pathLocal = null, $pathCommon = null) { if (self::$instance === null) { diff --git a/core/Application/Kernel/PluginList.php b/core/Application/Kernel/PluginList.php index 9d5e03cc0a..672110853b 100644 --- a/core/Application/Kernel/PluginList.php +++ b/core/Application/Kernel/PluginList.php @@ -23,4 +23,11 @@ interface PluginList * @return string[] */ public function getActivatedPlugins(); + + /** + * Returns the list of plugins that are bundled with Piwik. + * + * @return string[] + */ + public function getPluginsBundledWithPiwik(); }
\ No newline at end of file diff --git a/core/Application/Kernel/PluginList/IniPluginList.php b/core/Application/Kernel/PluginList/IniPluginList.php index 6636cc4fd6..8825661e82 100644 --- a/core/Application/Kernel/PluginList/IniPluginList.php +++ b/core/Application/Kernel/PluginList/IniPluginList.php @@ -9,16 +9,19 @@ namespace Piwik\Application\Kernel\PluginList; use Piwik\Application\Kernel\GlobalSettingsProvider; +use Piwik\Application\Kernel\GlobalSettingsProvider\IniSettingsProvider; use Piwik\Application\Kernel\PluginList; /** * Default implementation of the PluginList interface. Uses the [Plugins] section * in Piwik's INI config to get the activated plugins. + * + * Depends on IniSettingsProvider being used. */ class IniPluginList implements PluginList { /** - * @var GlobalSettingsProvider + * @var IniSettingsProvider */ private $settings; @@ -35,4 +38,15 @@ class IniPluginList implements PluginList $section = $this->settings->getSection('Plugins'); return @$section['Plugins'] ?: array(); } + + /** + * @return string[] + */ + public function getPluginsBundledWithPiwik() + { + $pathGlobal = $this->settings->getPathGlobal(); + + $section = $this->settings->getIniFileChain()->getFrom($pathGlobal, 'Plugins'); + return $section['Plugins']; + } }
\ No newline at end of file diff --git a/core/Config.php b/core/Config.php index 42cec66702..edc54d6a07 100644 --- a/core/Config.php +++ b/core/Config.php @@ -52,17 +52,10 @@ class Config extends Singleton /** * @var boolean */ - protected $pathGlobal = null; - protected $pathCommon = null; - protected $pathLocal = null; - - /** - * @var boolean - */ protected $doNotWriteConfigInTests = false; /** - * @var IniFileChain + * @var IniSettingsProvider */ protected $settings; @@ -70,11 +63,7 @@ class Config extends Singleton public function __construct($pathGlobal = null, $pathLocal = null, $pathCommon = null) { - $this->pathGlobal = $pathGlobal ?: self::getGlobalConfigPath(); - $this->pathCommon = $pathCommon ?: self::getCommonConfigPath(); - $this->pathLocal = $pathLocal ?: self::getLocalConfigPath(); - - $this->settings = IniSettingsProvider::getSingletonInstance($pathGlobal, $pathLocal, $pathCommon)->getIniFileChain(); + $this->settings = IniSettingsProvider::getSingletonInstance($pathGlobal, $pathLocal, $pathCommon); } /** @@ -84,7 +73,7 @@ class Config extends Singleton */ public function getLocalPath() { - return $this->pathLocal; + return $this->settings->getPathLocal(); } /** @@ -94,7 +83,7 @@ class Config extends Singleton */ public function getGlobalPath() { - return $this->pathGlobal; + return $this->settings->getPathGlobal(); } /** @@ -104,7 +93,7 @@ class Config extends Singleton */ public function getCommonPath() { - return $this->pathCommon; + return $this->settings->getPathCommon(); } /** @@ -121,37 +110,35 @@ class Config extends Singleton $this->doNotWriteConfigInTests = true; } - $this->pathLocal = $pathLocal ?: Config::getLocalConfigPath(); - $this->pathGlobal = $pathGlobal ?: Config::getGlobalConfigPath(); - $this->pathCommon = $pathCommon ?: Config::getCommonConfigPath(); + $this->reload($pathLocal, $pathGlobal, $pathCommon); - $this->reload(); + $chain = $this->settings->getIniFileChain(); - $databaseTestsSettings = $this->settings->get('database_tests'); // has to be __get otherwise when called from TestConfig, PHP will issue a NOTICE + $databaseTestsSettings = $chain->get('database_tests'); // has to be __get otherwise when called from TestConfig, PHP will issue a NOTICE if (!empty($databaseTestsSettings)) { - $this->settings->set('database', $databaseTestsSettings); + $chain->set('database', $databaseTestsSettings); } // Ensure local mods do not affect tests if (empty($pathGlobal)) { - $this->settings->set('Debug', $this->settings->getFrom($this->pathGlobal, 'Debug')); - $this->settings->set('mail', $this->settings->getFrom($this->pathGlobal, 'mail')); - $this->settings->set('General', $this->settings->getFrom($this->pathGlobal, 'General')); - $this->settings->set('Segments', $this->settings->getFrom($this->pathGlobal, 'Segments')); - $this->settings->set('Tracker', $this->settings->getFrom($this->pathGlobal, 'Tracker')); - $this->settings->set('Deletelogs', $this->settings->getFrom($this->pathGlobal, 'Deletelogs')); - $this->settings->set('Deletereports', $this->settings->getFrom($this->pathGlobal, 'Deletereports')); - $this->settings->set('Development', $this->settings->getFrom($this->pathGlobal, 'Development')); + $chain->set('Debug', $chain->getFrom($this->getGlobalPath(), 'Debug')); + $chain->set('mail', $chain->getFrom($this->getGlobalPath(), 'mail')); + $chain->set('General', $chain->getFrom($this->getGlobalPath(), 'General')); + $chain->set('Segments', $chain->getFrom($this->getGlobalPath(), 'Segments')); + $chain->set('Tracker', $chain->getFrom($this->getGlobalPath(), 'Tracker')); + $chain->set('Deletelogs', $chain->getFrom($this->getGlobalPath(), 'Deletelogs')); + $chain->set('Deletereports', $chain->getFrom($this->getGlobalPath(), 'Deletereports')); + $chain->set('Development', $chain->getFrom($this->getGlobalPath(), 'Development')); } // 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->settings->set('PluginsInstalled', array('PluginsInstalled' => array())); + $chain->set('PluginsInstalled', array('PluginsInstalled' => array())); } protected function postConfigTestEvent() { - Piwik::postTestEvent('Config.createConfigSingleton', array($this->settings, $this) ); + Piwik::postTestEvent('Config.createConfigSingleton', array($this->settings->getIniFileChain(), $this) ); } /** @@ -230,7 +217,7 @@ class Config extends Singleton return $limits; } - protected static function getByDomainConfigPath() + public static function getByDomainConfigPath() { $host = self::getHostname(); $hostConfig = self::getLocalConfigInfoForHostname($host); @@ -281,16 +268,15 @@ class Config extends Singleton throw new Exception('Piwik domain is not a valid looking hostname (' . $filename . ').'); } - $this->pathLocal = $hostConfig['path']; - $this->initialized = false; + $pathLocal = $hostConfig['path']; try { - $this->reload(); + $this->reload($pathLocal); } catch (Exception $ex) { // pass (not required for local file to exist at this point) } - return $this->pathLocal; + return $pathLocal; } /** @@ -300,7 +286,7 @@ class Config extends Singleton */ public function isFileWritable() { - return is_writable($this->pathLocal); + return is_writable($this->settings->getPathLocal()); } /** @@ -330,11 +316,10 @@ class Config extends Singleton * @throws \Exception if the global config file is not found and this is a tracker request, or * if the local config file is not found and this is NOT a tracker request. */ - protected function reload() + protected function reload($pathLocal = null, $pathGlobal = null, $pathCommon = null) { $this->initialized = false; - - $this->settings->reload(array($this->pathGlobal, $this->pathCommon), $this->pathLocal); + $this->settings->reload($pathGlobal, $pathLocal, $pathCommon); } /** @@ -342,7 +327,7 @@ class Config extends Singleton */ public function existsLocalConfig() { - return is_readable($this->pathLocal); + return is_readable($this->getLocalPath()); } public function deleteLocalConfig() @@ -351,13 +336,6 @@ class Config extends Singleton unlink($configLocal); } -/* public function checkLocalConfigFound() - { - if (!$this->existsLocalConfig()) { - throw new ConfigNotFoundException(Piwik::translate('General_ExceptionConfigurationFileNotFound', array($this->pathLocal))); - } - }*/ - /** * Decode HTML entities * @@ -412,28 +390,21 @@ class Config extends Singleton if (!$this->initialized) { $this->initialized = true; - // this is done lazily and not in __construct so Installation will properly be triggered. ideally, it should be - // done in __construct, but the exception that is thrown depends on Translator which depends on Config. the - // circular dependency causes problems. - /*if (!SettingsServer::isTrackerApiRequest()) { - $this->checkLocalConfigFound(); - }*/ - $this->postConfigTestEvent(); } - $section =& $this->settings->get($name); + $section =& $this->settings->getIniFileChain()->get($name); return $section; } public function getFromGlobalConfig($name) { - return $this->settings->getFrom($this->pathGlobal, $name); + return $this->settings->getIniFileChain()->getFrom($this->getGlobalPath(), $name); } public function getFromCommonConfig($name) { - return $this->settings->getFrom($this->pathCommon, $name); + return $this->settings->getIniFileChain()->getFrom($this->getCommonPath(), $name); } /** @@ -445,7 +416,7 @@ class Config extends Singleton */ public function __set($name, $value) { - $this->settings->set($name, $value); + $this->settings->getIniFileChain()->set($name, $value); } /** @@ -456,16 +427,18 @@ class Config extends Singleton */ public function dumpConfig() { - $this->encodeValues($this->settings->getAll()); + $chain = $this->settings->getIniFileChain(); + + $this->encodeValues($chain->getAll()); try { $header = "; <?php exit; ?> DO NOT REMOVE THIS LINE\n"; $header .= "; 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"; - $dumpedString = $this->settings->dumpChanges($header); + $dumpedString = $chain->dumpChanges($header); - $this->decodeValues($this->settings->getAll()); + $this->decodeValues($chain->getAll()); } catch (Exception $ex) { - $this->decodeValues($this->settings->getAll()); + $this->decodeValues($chain->getAll()); throw $ex; } @@ -495,7 +468,7 @@ class Config extends Singleton if ($output !== null && $output !== false ) { - $success = @file_put_contents($this->pathLocal, $output); + $success = @file_put_contents($this->getLocalPath(), $output); if ($success === false) { throw $this->getConfigNotWritableException(); } @@ -522,7 +495,7 @@ class Config extends Singleton */ public function getConfigNotWritableException() { - $path = "config/" . basename($this->pathLocal); + $path = "config/" . basename($this->getLocalPath()); return new Exception(Piwik::translate('General_ConfigFileIsNotWritable', array("(" . $path . ")", ""))); } }
\ No newline at end of file diff --git a/core/Config/IniFileChain.php b/core/Config/IniFileChain.php index bffca9cbc6..95516921b8 100644 --- a/core/Config/IniFileChain.php +++ b/core/Config/IniFileChain.php @@ -206,12 +206,7 @@ class IniFileChain $reader = new IniReader(); foreach ($this->settingsChain as $file => $ignore) { if (is_readable($file)) { - try { - $this->settingsChain[$file] = $reader->readFile($file); - } catch (IniReadingException $ex) { - $message = Piwik::translate('General_ExceptionUnreadableFileDisabledMethod', array($file, "parse_ini_file()")); - throw new IniReadingException($message, $code = 0, $ex); - } + $this->settingsChain[$file] = $reader->readFile($file); } } diff --git a/core/ExceptionHandler.php b/core/ExceptionHandler.php index e68a058e4a..5b02cd77f6 100644 --- a/core/ExceptionHandler.php +++ b/core/ExceptionHandler.php @@ -78,7 +78,11 @@ class ExceptionHandler $logoHeaderUrl = $logo->getHeaderLogoUrl(); $logoFaviconUrl = $logo->getPathUserFavicon(); } catch (Exception $ex) { - Log::debug($ex); + try { + Log::debug($ex); + } catch (\Exception $otherEx) { + // DI container may not be setup at this point + } } $result = Piwik_GetErrorMessagePage($message, $debugTrace, true, true, $logoHeaderUrl, $logoFaviconUrl); diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php index 0d69083af7..1cdf9ebb2e 100644 --- a/core/Plugin/Manager.php +++ b/core/Plugin/Manager.php @@ -1280,9 +1280,7 @@ class Manager */ protected function getPluginsFromGlobalIniConfigFile() // TODO: if this is only used for sorting, move to PluginList { - $pluginsBundledWithPiwik = PiwikConfig::getInstance()->getFromGlobalConfig('Plugins'); - $pluginsBundledWithPiwik = $pluginsBundledWithPiwik['Plugins']; - return $pluginsBundledWithPiwik; + return $this->pluginList->getPluginsBundledWithPiwik(); } /** @@ -1292,7 +1290,6 @@ class Manager protected function isPluginEnabledByDefault($name) { $pluginsBundledWithPiwik = $this->getPluginsFromGlobalIniConfigFile(); - if(empty($pluginsBundledWithPiwik)) { return false; } diff --git a/core/Translation/Translator.php b/core/Translation/Translator.php index dda946ccd9..46503a0185 100644 --- a/core/Translation/Translator.php +++ b/core/Translation/Translator.php @@ -114,7 +114,8 @@ class Translator */ public function getDefaultLanguage() { - return Config::getInstance()->General['default_language']; + $generalSection = Config::getInstance()->General; + return @$generalSection['default_language'] ?: 'en'; } /** |