From: Philipp Date: Sat, 23 Oct 2021 09:29:16 +0000 (+0200) Subject: Restructure (P)Config to follow new paradigm X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=ab83d0dd27e46e733ecb49f25789bfb318852ac7;p=friendica.git Restructure (P)Config to follow new paradigm --- diff --git a/src/App.php b/src/App.php index 3ef9bdb4ed..cd217c34e7 100644 --- a/src/App.php +++ b/src/App.php @@ -25,10 +25,10 @@ use Exception; use Friendica\App\Arguments; use Friendica\App\BaseURL; use Friendica\App\Module; -use Friendica\Factory\ConfigFactory; +use Friendica\Core\Config\Factory\ConfigFactory; use Friendica\Module\Maintenance; use Friendica\Security\Authentication; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Core\Config\IConfig; use Friendica\Core\PConfig\IPConfig; use Friendica\Core\L10n; @@ -39,7 +39,6 @@ use Friendica\Model\Contact; use Friendica\Model\Profile; use Friendica\Module\Special\HTTPException as ModuleHTTPException; use Friendica\Network\HTTPException; -use Friendica\Util\ConfigFileLoader; use Friendica\Util\DateTimeFormat; use Friendica\Util\HTTPSignature; use Friendica\Util\Profiler; diff --git a/src/App/Mode.php b/src/App/Mode.php index 7210184a0d..9f7a34a53e 100644 --- a/src/App/Mode.php +++ b/src/App/Mode.php @@ -22,7 +22,7 @@ namespace Friendica\App; use Detection\MobileDetect; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Database\Database; use Friendica\Util\BasePath; diff --git a/src/Console/AutomaticInstallation.php b/src/Console/AutomaticInstallation.php index 5d608b00d5..9ef82524aa 100644 --- a/src/Console/AutomaticInstallation.php +++ b/src/Console/AutomaticInstallation.php @@ -25,7 +25,7 @@ use Asika\SimpleConsole\Console; use Friendica\App; use Friendica\App\BaseURL; use Friendica\Core\Config\IConfig; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Core\Installer; use Friendica\Core\Theme; use Friendica\Database\Database; @@ -36,7 +36,7 @@ class AutomaticInstallation extends Console { /** @var App\Mode */ private $appMode; - /** @var Cache */ + /** @var \Friendica\Core\Config\Cache\Cache */ private $configCache; /** @var IConfig */ private $config; diff --git a/src/Console/DatabaseStructure.php b/src/Console/DatabaseStructure.php index b44400c01a..1083a512d4 100644 --- a/src/Console/DatabaseStructure.php +++ b/src/Console/DatabaseStructure.php @@ -21,7 +21,7 @@ namespace Friendica\Console; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Core\Update; use Friendica\Database\Database; use Friendica\Database\DBStructure; diff --git a/src/Core/BaseConfig.php b/src/Core/BaseConfig.php deleted file mode 100644 index f8583de46f..0000000000 --- a/src/Core/BaseConfig.php +++ /dev/null @@ -1,63 +0,0 @@ -. - * - */ - -namespace Friendica\Core; - -use Friendica\Core\Config\Cache; -use Friendica\Core\Config\IConfig; -use Friendica\Model; - -/** - * This class is responsible for all system-wide configuration values in Friendica - * There are two types of storage - * - The Config-Files (loaded into the FileCache @see Cache\ConfigCache) - * - The Config-DB-Table (per Config-DB-model @see Model\Config\Config) - */ -abstract class BaseConfig implements IConfig -{ - /** - * @var Cache - */ - protected $configCache; - - /** - * @var Model\Config\Config - */ - protected $configModel; - - /** - * @param Cache $configCache The configuration cache (based on the config-files) - * @param Model\Config\Config $configModel The configuration model - */ - public function __construct(Cache $configCache, Model\Config\Config $configModel) - { - $this->configCache = $configCache; - $this->configModel = $configModel; - } - - /** - * {@inheritDoc} - */ - public function getCache() - { - return $this->configCache; - } -} diff --git a/src/Core/BasePConfig.php b/src/Core/BasePConfig.php deleted file mode 100644 index 366a8e6061..0000000000 --- a/src/Core/BasePConfig.php +++ /dev/null @@ -1,66 +0,0 @@ -. - * - */ - -namespace Friendica\Core; - -use Friendica\Core\PConfig\Cache; -use Friendica\Core\PConfig\IPConfig; -use Friendica\Model; - -/** - * This class is responsible for the user-specific configuration values in Friendica - * The values are set through the Config-DB-Table (per Config-DB-model @see Model\Config\PConfig) - * - * The configuration cache (@see Cache\PConfigCache) is used for temporary caching of database calls. This will - * increase the performance. - */ -abstract class BasePConfig implements IPConfig -{ - /** - * @var Cache - */ - protected $configCache; - - /** - * @var Model\Config\PConfig - */ - protected $configModel; - - /** - * @param Cache $configCache The configuration cache - * @param Model\Config\PConfig $configModel The configuration model - */ - public function __construct(Cache $configCache, Model\Config\PConfig $configModel) - { - $this->configCache = $configCache; - $this->configModel = $configModel; - } - - /** - * Returns the Config Cache - * - * @return Cache - */ - public function getCache() - { - return $this->configCache; - } -} diff --git a/src/Core/Config/Cache.php b/src/Core/Config/Cache.php deleted file mode 100644 index 8d2eb1a97e..0000000000 --- a/src/Core/Config/Cache.php +++ /dev/null @@ -1,210 +0,0 @@ -. - * - */ - -namespace Friendica\Core\Config; - -use ParagonIE\HiddenString\HiddenString; - -/** - * The Friendica config cache for the application - * Initial, all *.config.php files are loaded into this cache with the - * ConfigFileLoader ( @see ConfigFileLoader ) - */ -class Cache -{ - /** @var int Indicates that the cache entry is set by file - Low Priority */ - const SOURCE_FILE = 0; - /** @var int Indicates that the cache entry is set by the DB config table - Middle Priority */ - const SOURCE_DB = 1; - /** @var int Indicates that the cache entry is set by a server environment variable - High Priority */ - const SOURCE_ENV = 3; - /** @var int Indicates that the cache entry is fixed and must not be changed */ - const SOURCE_FIX = 4; - - /** @var int Default value for a config source */ - const SOURCE_DEFAULT = self::SOURCE_FILE; - - /** - * @var array - */ - private $config; - - /** - * @var int[][] - */ - private $source = []; - - /** - * @var bool - */ - private $hidePasswordOutput; - - /** - * @param array $config A initial config array - * @param bool $hidePasswordOutput True, if cache variables should take extra care of password values - * @param int $source Sets a source of the initial config values - */ - public function __construct(array $config = [], bool $hidePasswordOutput = true, $source = self::SOURCE_DEFAULT) - { - $this->hidePasswordOutput = $hidePasswordOutput; - $this->load($config, $source); - } - - /** - * Tries to load the specified configuration array into the config array. - * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config. - * - * @param array $config - * @param int $source Indicates the source of the config entry - */ - public function load(array $config, int $source = self::SOURCE_DEFAULT) - { - $categories = array_keys($config); - - foreach ($categories as $category) { - if (is_array($config[$category])) { - $keys = array_keys($config[$category]); - - foreach ($keys as $key) { - $value = $config[$category][$key]; - if (isset($value)) { - $this->set($category, $key, $value, $source); - } - } - } - } - } - - /** - * Gets a value from the config cache. - * - * @param string $cat Config category - * @param string $key Config key - * - * @return null|mixed Returns the value of the Config entry or null if not set - */ - public function get(string $cat, string $key = null) - { - if (isset($this->config[$cat][$key])) { - return $this->config[$cat][$key]; - } else if (!isset($key) && isset($this->config[$cat])) { - return $this->config[$cat]; - } else { - return null; - } - } - - /** - * Sets a value in the config cache. Accepts raw output from the config table - * - * @param string $cat Config category - * @param string $key Config key - * @param mixed $value Value to set - * @param int $source The source of the current config key - * - * @return bool True, if the value is set - */ - public function set(string $cat, string $key, $value, $source = self::SOURCE_DEFAULT) - { - if (!isset($this->config[$cat])) { - $this->config[$cat] = []; - $this->source[$cat] = []; - } - - if (isset($this->source[$cat][$key]) && - $source < $this->source[$cat][$key]) { - return false; - } - - if ($this->hidePasswordOutput && - $key == 'password' && - is_string($value)) { - $this->config[$cat][$key] = new HiddenString((string)$value); - } else { - $this->config[$cat][$key] = $value; - } - - $this->source[$cat][$key] = $source; - - return true; - } - - /** - * Deletes a value from the config cache. - * - * @param string $cat Config category - * @param string $key Config key - * - * @return bool true, if deleted - */ - public function delete(string $cat, string $key) - { - if (isset($this->config[$cat][$key])) { - unset($this->config[$cat][$key]); - unset($this->source[$cat][$key]); - if (count($this->config[$cat]) == 0) { - unset($this->config[$cat]); - unset($this->source[$cat]); - } - return true; - } else { - return false; - } - } - - /** - * Returns the whole configuration - * - * @return array The configuration - */ - public function getAll() - { - return $this->config; - } - - /** - * Returns an array with missing categories/Keys - * - * @param array $config The array to check - * - * @return array - */ - public function keyDiff(array $config) - { - $return = []; - - $categories = array_keys($config); - - foreach ($categories as $category) { - if (is_array($config[$category])) { - $keys = array_keys($config[$category]); - - foreach ($keys as $key) { - if (!isset($this->config[$category][$key])) { - $return[$category][$key] = $config[$category][$key]; - } - } - } - } - - return $return; - } -} diff --git a/src/Core/Config/Cache/Cache.php b/src/Core/Config/Cache/Cache.php new file mode 100644 index 0000000000..77e6562ca6 --- /dev/null +++ b/src/Core/Config/Cache/Cache.php @@ -0,0 +1,210 @@ +. + * + */ + +namespace Friendica\Core\Config\Cache; + +use ParagonIE\HiddenString\HiddenString; + +/** + * The Friendica config cache for the application + * Initial, all *.config.php files are loaded into this cache with the + * ConfigFileLoader ( @see ConfigFileLoader ) + */ +class Cache +{ + /** @var int Indicates that the cache entry is set by file - Low Priority */ + const SOURCE_FILE = 0; + /** @var int Indicates that the cache entry is set by the DB config table - Middle Priority */ + const SOURCE_DB = 1; + /** @var int Indicates that the cache entry is set by a server environment variable - High Priority */ + const SOURCE_ENV = 3; + /** @var int Indicates that the cache entry is fixed and must not be changed */ + const SOURCE_FIX = 4; + + /** @var int Default value for a config source */ + const SOURCE_DEFAULT = self::SOURCE_FILE; + + /** + * @var array + */ + private $config; + + /** + * @var int[][] + */ + private $source = []; + + /** + * @var bool + */ + private $hidePasswordOutput; + + /** + * @param array $config A initial config array + * @param bool $hidePasswordOutput True, if cache variables should take extra care of password values + * @param int $source Sets a source of the initial config values + */ + public function __construct(array $config = [], bool $hidePasswordOutput = true, $source = self::SOURCE_DEFAULT) + { + $this->hidePasswordOutput = $hidePasswordOutput; + $this->load($config, $source); + } + + /** + * Tries to load the specified configuration array into the config array. + * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config. + * + * @param array $config + * @param int $source Indicates the source of the config entry + */ + public function load(array $config, int $source = self::SOURCE_DEFAULT) + { + $categories = array_keys($config); + + foreach ($categories as $category) { + if (is_array($config[$category])) { + $keys = array_keys($config[$category]); + + foreach ($keys as $key) { + $value = $config[$category][$key]; + if (isset($value)) { + $this->set($category, $key, $value, $source); + } + } + } + } + } + + /** + * Gets a value from the config cache. + * + * @param string $cat Config category + * @param string $key Config key + * + * @return null|mixed Returns the value of the Config entry or null if not set + */ + public function get(string $cat, string $key = null) + { + if (isset($this->config[$cat][$key])) { + return $this->config[$cat][$key]; + } else if (!isset($key) && isset($this->config[$cat])) { + return $this->config[$cat]; + } else { + return null; + } + } + + /** + * Sets a value in the config cache. Accepts raw output from the config table + * + * @param string $cat Config category + * @param string $key Config key + * @param mixed $value Value to set + * @param int $source The source of the current config key + * + * @return bool True, if the value is set + */ + public function set(string $cat, string $key, $value, $source = self::SOURCE_DEFAULT) + { + if (!isset($this->config[$cat])) { + $this->config[$cat] = []; + $this->source[$cat] = []; + } + + if (isset($this->source[$cat][$key]) && + $source < $this->source[$cat][$key]) { + return false; + } + + if ($this->hidePasswordOutput && + $key == 'password' && + is_string($value)) { + $this->config[$cat][$key] = new HiddenString((string)$value); + } else { + $this->config[$cat][$key] = $value; + } + + $this->source[$cat][$key] = $source; + + return true; + } + + /** + * Deletes a value from the config cache. + * + * @param string $cat Config category + * @param string $key Config key + * + * @return bool true, if deleted + */ + public function delete(string $cat, string $key) + { + if (isset($this->config[$cat][$key])) { + unset($this->config[$cat][$key]); + unset($this->source[$cat][$key]); + if (count($this->config[$cat]) == 0) { + unset($this->config[$cat]); + unset($this->source[$cat]); + } + return true; + } else { + return false; + } + } + + /** + * Returns the whole configuration + * + * @return array The configuration + */ + public function getAll() + { + return $this->config; + } + + /** + * Returns an array with missing categories/Keys + * + * @param array $config The array to check + * + * @return array + */ + public function keyDiff(array $config) + { + $return = []; + + $categories = array_keys($config); + + foreach ($categories as $category) { + if (is_array($config[$category])) { + $keys = array_keys($config[$category]); + + foreach ($keys as $key) { + if (!isset($this->config[$category][$key])) { + $return[$category][$key] = $config[$category][$key]; + } + } + } + } + + return $return; + } +} diff --git a/src/Core/Config/Cache/ConfigFileLoader.php b/src/Core/Config/Cache/ConfigFileLoader.php new file mode 100644 index 0000000000..4b1a09c1dc --- /dev/null +++ b/src/Core/Config/Cache/ConfigFileLoader.php @@ -0,0 +1,368 @@ +. + * + */ + +namespace Friendica\Core\Config\Cache; + +use Exception; +use Friendica\Core\Addon; +use Friendica\Core\Config\Cache\Cache; + +/** + * The ConfigFileLoader loads config-files and stores them in a ConfigCache ( @see Cache ) + * + * It is capable of loading the following config files: + * - *.config.php (current) + * - *.ini.php (deprecated) + * - *.htconfig.php (deprecated) + */ +class ConfigFileLoader +{ + /** + * The default name of the user defined ini file + * + * @var string + */ + const CONFIG_INI = 'local'; + + /** + * The default name of the user defined legacy config file + * + * @var string + */ + const CONFIG_HTCONFIG = 'htconfig'; + + /** + * The sample string inside the configs, which shouldn't get loaded + * + * @var string + */ + const SAMPLE_END = '-sample'; + + /** + * @var string + */ + private $baseDir; + /** + * @var string + */ + private $configDir; + /** + * @var string + */ + private $staticDir; + + /** + * @param string $baseDir The base + * @param string $configDir + * @param string $staticDir + */ + public function __construct(string $baseDir, string $configDir, string $staticDir) + { + $this->baseDir = $baseDir; + $this->configDir = $configDir; + $this->staticDir = $staticDir; + } + + /** + * Load the configuration files into an configuration cache + * + * First loads the default value for all the configuration keys, then the legacy configuration files, then the + * expected local.config.php + * + * @param Cache $config The config cache to load to + * @param array $server The $_SERVER array + * @param bool $raw Setup the raw config format + * + * @throws Exception + */ + public function setupCache(Cache $config, array $server = [], bool $raw = false) + { + // Load static config files first, the order is important + $config->load($this->loadStaticConfig('defaults'), Cache::SOURCE_FILE); + $config->load($this->loadStaticConfig('settings'), Cache::SOURCE_FILE); + + // try to load the legacy config first + $config->load($this->loadLegacyConfig('htpreconfig'), Cache::SOURCE_FILE); + $config->load($this->loadLegacyConfig('htconfig'), Cache::SOURCE_FILE); + + // Now load every other config you find inside the 'config/' directory + $this->loadCoreConfig($config); + + $config->load($this->loadEnvConfig($server), Cache::SOURCE_ENV); + + // In case of install mode, add the found basepath (because there isn't a basepath set yet + if (!$raw && empty($config->get('system', 'basepath'))) { + // Setting at least the basepath we know + $config->set('system', 'basepath', $this->baseDir, Cache::SOURCE_FILE); + } + } + + /** + * Tries to load the static core-configuration and returns the config array. + * + * @param string $name The name of the configuration + * + * @return array The config array (empty if no config found) + * + * @throws Exception if the configuration file isn't readable + */ + private function loadStaticConfig($name) + { + $configName = $this->staticDir . DIRECTORY_SEPARATOR . $name . '.config.php'; + $iniName = $this->staticDir . DIRECTORY_SEPARATOR . $name . '.ini.php'; + + if (file_exists($configName)) { + return $this->loadConfigFile($configName); + } elseif (file_exists($iniName)) { + return $this->loadINIConfigFile($iniName); + } else { + return []; + } + } + + /** + * Tries to load the specified core-configuration into the config cache. + * + * @param Cache $config The Config cache + * + * @return array The config array (empty if no config found) + * + * @throws Exception if the configuration file isn't readable + */ + private function loadCoreConfig(Cache $config) + { + // try to load legacy ini-files first + foreach ($this->getConfigFiles(true) as $configFile) { + $config->load($this->loadINIConfigFile($configFile), Cache::SOURCE_FILE); + } + + // try to load supported config at last to overwrite it + foreach ($this->getConfigFiles() as $configFile) { + $config->load($this->loadConfigFile($configFile), Cache::SOURCE_FILE); + } + + return []; + } + + /** + * Tries to load the specified addon-configuration and returns the config array. + * + * @param string $name The name of the configuration + * + * @return array The config array (empty if no config found) + * + * @throws Exception if the configuration file isn't readable + */ + public function loadAddonConfig($name) + { + $filepath = $this->baseDir . DIRECTORY_SEPARATOR . // /var/www/html/ + Addon::DIRECTORY . DIRECTORY_SEPARATOR . // addon/ + $name . DIRECTORY_SEPARATOR . // openstreetmap/ + 'config'. DIRECTORY_SEPARATOR . // config/ + $name . ".config.php"; // openstreetmap.config.php + + if (file_exists($filepath)) { + return $this->loadConfigFile($filepath); + } else { + return []; + } + } + + /** + * Tries to load environment specific variables, based on the `env.config.php` mapping table + * + * @param array $server The $_SERVER variable + * + * @return array The config array (empty if no config was found) + * + * @throws Exception if the configuration file isn't readable + */ + public function loadEnvConfig(array $server) + { + $filepath = $this->staticDir . DIRECTORY_SEPARATOR . // /var/www/html/static/ + "env.config.php"; // env.config.php + + if (!file_exists($filepath)) { + return []; + } + + $envConfig = $this->loadConfigFile($filepath); + + $return = []; + + foreach ($envConfig as $envKey => $configStructure) { + if (isset($server[$envKey])) { + $return[$configStructure[0]][$configStructure[1]] = $server[$envKey]; + } + } + + return $return; + } + + /** + * Get the config files of the config-directory + * + * @param bool $ini True, if scan for ini-files instead of config files + * + * @return array + */ + private function getConfigFiles(bool $ini = false) + { + $files = scandir($this->configDir); + $found = array(); + + $filePattern = ($ini ? '*.ini.php' : '*.config.php'); + + // Don't load sample files + $sampleEnd = self::SAMPLE_END . ($ini ? '.ini.php' : '.config.php'); + + foreach ($files as $filename) { + if (fnmatch($filePattern, $filename) && substr_compare($filename, $sampleEnd, -strlen($sampleEnd))) { + $found[] = $this->configDir . '/' . $filename; + } + } + + return $found; + } + + /** + * Tries to load the legacy config files (.htconfig.php, .htpreconfig.php) and returns the config array. + * + * @param string $name The name of the config file (default is empty, which means .htconfig.php) + * + * @return array The configuration array (empty if no config found) + * + * @deprecated since version 2018.09 + */ + private function loadLegacyConfig($name = '') + { + $name = !empty($name) ? $name : self::CONFIG_HTCONFIG; + $fullName = $this->baseDir . DIRECTORY_SEPARATOR . '.' . $name . '.php'; + + $config = []; + if (file_exists($fullName)) { + $a = new \stdClass(); + $a->config = []; + include $fullName; + + $htConfigCategories = array_keys($a->config); + + // map the legacy configuration structure to the current structure + foreach ($htConfigCategories as $htConfigCategory) { + if (is_array($a->config[$htConfigCategory])) { + $keys = array_keys($a->config[$htConfigCategory]); + + foreach ($keys as $key) { + $config[$htConfigCategory][$key] = $a->config[$htConfigCategory][$key]; + } + } else { + $config['config'][$htConfigCategory] = $a->config[$htConfigCategory]; + } + } + + unset($a); + + if (isset($db_host)) { + $config['database']['hostname'] = $db_host; + unset($db_host); + } + if (isset($db_user)) { + $config['database']['username'] = $db_user; + unset($db_user); + } + if (isset($db_pass)) { + $config['database']['password'] = $db_pass; + unset($db_pass); + } + if (isset($db_data)) { + $config['database']['database'] = $db_data; + unset($db_data); + } + if (isset($config['system']['db_charset'])) { + $config['database']['charset'] = $config['system']['db_charset']; + } + if (isset($pidfile)) { + $config['system']['pidfile'] = $pidfile; + unset($pidfile); + } + if (isset($default_timezone)) { + $config['system']['default_timezone'] = $default_timezone; + unset($default_timezone); + } + if (isset($lang)) { + $config['system']['language'] = $lang; + unset($lang); + } + } + + return $config; + } + + /** + * Tries to load the specified legacy configuration file and returns the config array. + * + * @param string $filepath + * + * @return array The configuration array + * @throws Exception + * @deprecated since version 2018.12 + */ + private function loadINIConfigFile($filepath) + { + $contents = include($filepath); + + $config = parse_ini_string($contents, true, INI_SCANNER_TYPED); + + if ($config === false) { + throw new Exception('Error parsing INI config file ' . $filepath); + } + + return $config; + } + + /** + * Tries to load the specified configuration file and returns the config array. + * + * The config format is PHP array and the template for configuration files is the following: + * + * [ + * 'key' => 'value', + * ], + * ]; + * + * @param string $filepath The filepath of the + * + * @return array The config array0 + * + * @throws Exception if the config cannot get loaded. + */ + private function loadConfigFile($filepath) + { + $config = include($filepath); + + if (!is_array($config)) { + throw new Exception('Error loading config file ' . $filepath); + } + + return $config; + } +} diff --git a/src/Core/Config/Factory/ConfigFactory.php b/src/Core/Config/Factory/ConfigFactory.php new file mode 100644 index 0000000000..9546a0248f --- /dev/null +++ b/src/Core/Config/Factory/ConfigFactory.php @@ -0,0 +1,103 @@ +. + * + */ + +namespace Friendica\Core\Config\Factory; + +use Exception; +use Friendica\Core\Config; +use Friendica\Core\Config\Cache\Cache; +use Friendica\Core\Config\Model\Config as ConfigModel; +use Friendica\Core\Config\Cache\ConfigFileLoader; + +class ConfigFactory +{ + /** + * The key of the $_SERVER variable to override the config directory + * + * @var string + */ + const CONFIG_DIR_ENV = 'FRIENDICA_CONFIG_DIR'; + + /** + * The Sub directory of the config-files + * + * @var string + */ + const CONFIG_DIR = 'config'; + + /** + * The Sub directory of the static config-files + * + * @var string + */ + const STATIC_DIR = 'static'; + + /** + * @param string $basePath The basepath of FRIENDICA + * @param array $serer the $_SERVER array + * + * @return \Friendica\Core\Config\Cache\ConfigFileLoader + */ + public function createConfigFileLoader(string $basePath, array $server = []) + { + if (!empty($server[self::CONFIG_DIR_ENV]) && is_dir($server[self::CONFIG_DIR_ENV])) { + $configDir = $server[self::CONFIG_DIR_ENV]; + } else { + $configDir = $basePath . DIRECTORY_SEPARATOR . self::CONFIG_DIR; + } + $staticDir = $basePath . DIRECTORY_SEPARATOR . self::STATIC_DIR; + + return new ConfigFileLoader($basePath, $configDir, $staticDir); + } + + /** + * @param \Friendica\Core\Config\Cache\ConfigFileLoader $loader The Config Cache loader (INI/config/.htconfig) + * + * @return Cache + * + * @throws Exception + */ + public function createCache(ConfigFileLoader $loader, array $server = []) + { + $configCache = new Cache(); + $loader->setupCache($configCache, $server); + + return $configCache; + } + + /** + * @param \Friendica\Core\Config\Cache\Cache $configCache The config cache of this adapter + * @param ConfigModel $configModel The configuration model + * + * @return Config\IConfig + */ + public function create(Cache $configCache, ConfigModel $configModel) + { + if ($configCache->get('system', 'config_adapter') === 'preload') { + $configuration = new Config\Type\PreloadConfig($configCache, $configModel); + } else { + $configuration = new Config\Type\JitConfig($configCache, $configModel); + } + + + return $configuration; + } +} diff --git a/src/Core/Config/IConfig.php b/src/Core/Config/IConfig.php index 81ea1afd76..21cee2e924 100644 --- a/src/Core/Config/IConfig.php +++ b/src/Core/Config/IConfig.php @@ -21,6 +21,8 @@ namespace Friendica\Core\Config; +use Friendica\Core\Config\Cache\Cache; + /** * Interface for accessing system wide configurations */ diff --git a/src/Core/Config/JitConfig.php b/src/Core/Config/JitConfig.php deleted file mode 100644 index 8eb4ace1ed..0000000000 --- a/src/Core/Config/JitConfig.php +++ /dev/null @@ -1,141 +0,0 @@ -. - * - */ - -namespace Friendica\Core\Config; - -use Friendica\Core\BaseConfig; -use Friendica\Model; - -/** - * This class implements the Just-In-Time configuration, which will cache - * config values in a cache, once they are retrieved. - * - * Default Configuration type. - * Provides the best performance for pages loading few configuration variables. - */ -class JitConfig extends BaseConfig -{ - /** - * @var array Array of already loaded db values (even if there was no value) - */ - private $db_loaded; - - /** - * @param Cache $configCache The configuration cache (based on the config-files) - * @param Model\Config\Config $configModel The configuration model - */ - public function __construct(Cache $configCache, Model\Config\Config $configModel) - { - parent::__construct($configCache, $configModel); - $this->db_loaded = []; - - $this->load(); - } - - /** - * {@inheritDoc} - * - */ - public function load(string $cat = 'config') - { - // If not connected, do nothing - if (!$this->configModel->isConnected()) { - return; - } - - $config = $this->configModel->load($cat); - - if (!empty($config[$cat])) { - foreach ($config[$cat] as $key => $value) { - $this->db_loaded[$cat][$key] = true; - } - } - - // load the whole category out of the DB into the cache - $this->configCache->load($config, Cache::SOURCE_DB); - } - - /** - * {@inheritDoc} - */ - public function get(string $cat, string $key, $default_value = null, bool $refresh = false) - { - // if the value isn't loaded or refresh is needed, load it to the cache - if ($this->configModel->isConnected() && - (empty($this->db_loaded[$cat][$key]) || - $refresh)) { - - $dbvalue = $this->configModel->get($cat, $key); - - if (isset($dbvalue)) { - $this->configCache->set($cat, $key, $dbvalue, Cache::SOURCE_DB); - unset($dbvalue); - } - - $this->db_loaded[$cat][$key] = true; - } - - // use the config cache for return - $result = $this->configCache->get($cat, $key); - - return (isset($result)) ? $result : $default_value; - } - - /** - * {@inheritDoc} - */ - public function set(string $cat, string $key, $value) - { - // set the cache first - $cached = $this->configCache->set($cat, $key, $value, Cache::SOURCE_DB); - - // If there is no connected adapter, we're finished - if (!$this->configModel->isConnected()) { - return $cached; - } - - $stored = $this->configModel->set($cat, $key, $value); - - $this->db_loaded[$cat][$key] = $stored; - - return $cached && $stored; - } - - /** - * {@inheritDoc} - */ - public function delete(string $cat, string $key) - { - $cacheRemoved = $this->configCache->delete($cat, $key); - - if (isset($this->db_loaded[$cat][$key])) { - unset($this->db_loaded[$cat][$key]); - } - - if (!$this->configModel->isConnected()) { - return $cacheRemoved; - } - - $storeRemoved = $this->configModel->delete($cat, $key); - - return $cacheRemoved || $storeRemoved; - } -} diff --git a/src/Core/Config/Model/Config.php b/src/Core/Config/Model/Config.php new file mode 100644 index 0000000000..bca2145fb1 --- /dev/null +++ b/src/Core/Config/Model/Config.php @@ -0,0 +1,172 @@ +. + * + */ + +namespace Friendica\Core\Config\Model; + +use Friendica\Database\Database; + +/** + * The Config model backend, which is using the general DB-model backend for configs + */ +class Config +{ + /** @var Database */ + protected $dba; + + /** + * @param Database $dba The database connection of this model + */ + public function __construct(Database $dba) + { + $this->dba = $dba; + } + + /** + * Checks if the model is currently connected + * + * @return bool + */ + public function isConnected() + { + return $this->dba->isConnected(); + } + + /** + * Loads all configuration values and returns the loaded category as an array. + * + * @param string|null $cat The category of the configuration values to load + * + * @return array The config array + * + * @throws \Exception In case DB calls are invalid + */ + public function load(string $cat = null) + { + $return = []; + + if (empty($cat)) { + $configs = $this->dba->select('config', ['cat', 'v', 'k']); + } else { + $configs = $this->dba->select('config', ['cat', 'v', 'k'], ['cat' => $cat]); + } + + while ($config = $this->dba->fetch($configs)) { + + $key = $config['k']; + $value = DbaUtils::toConfigValue($config['v']); + + // just save it in case it is set + if (isset($value)) { + $return[$config['cat']][$key] = $value; + } + } + $this->dba->close($configs); + + return $return; + } + + /** + * Get a particular, system-wide config variable out of the DB with the + * given category name ($cat) and a key ($key). + * + * Note: Boolean variables are defined as 0/1 in the database + * + * @param string $cat The category of the configuration value + * @param string $key The configuration key to query + * + * @return array|string|null Stored value or null if it does not exist + * + * @throws \Exception In case DB calls are invalid + */ + public function get(string $cat, string $key) + { + if (!$this->isConnected()) { + return null; + } + + $config = $this->dba->selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]); + if ($this->dba->isResult($config)) { + $value = DbaUtils::toConfigValue($config['v']); + + // just return it in case it is set + if (isset($value)) { + return $value; + } + } + + return null; + } + + /** + * Stores a config value ($value) in the category ($cat) under the key ($key). + * + * Note: Please do not store booleans - convert to 0/1 integer values! + * + * @param string $cat The category of the configuration value + * @param string $key The configuration key to set + * @param mixed $value The value to store + * + * @return bool Operation success + * + * @throws \Exception In case DB calls are invalid + */ + public function set(string $cat, string $key, $value) + { + if (!$this->isConnected()) { + return false; + } + + // We store our setting values in a string variable. + // So we have to do the conversion here so that the compare below works. + // The exception are array values. + $compare_value = (!is_array($value) ? (string)$value : $value); + $stored_value = $this->get($cat, $key); + + if (isset($stored_value) && ($stored_value === $compare_value)) { + return true; + } + + $dbvalue = DbaUtils::toDbValue($value); + + $result = $this->dba->update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true); + + return $result; + } + + /** + * Removes the configured value from the database. + * + * @param string $cat The category of the configuration value + * @param string $key The configuration key to delete + * + * @return bool Operation success + * + * @throws \Exception In case DB calls are invalid + */ + public function delete(string $cat, string $key) + { + if (!$this->isConnected()) { + return false; + } + + return $this->dba->delete('config', ['cat' => $cat, 'k' => $key]); + } +} diff --git a/src/Core/Config/Model/DbaUtils.php b/src/Core/Config/Model/DbaUtils.php new file mode 100644 index 0000000000..da2b897378 --- /dev/null +++ b/src/Core/Config/Model/DbaUtils.php @@ -0,0 +1,59 @@ +. - * - */ - -namespace Friendica\Core\Config; - -use Friendica\Core\BaseConfig; -use Friendica\Model; - -/** - * This class implements the preload configuration, which will cache - * all config values per call in a cache. - * - * Minimizes the number of database queries to retrieve configuration values at the cost of memory. - */ -class PreloadConfig extends BaseConfig -{ - /** @var bool */ - private $config_loaded; - - /** - * @param Cache $configCache The configuration cache (based on the config-files) - * @param Model\Config\Config $configModel The configuration model - */ - public function __construct(Cache $configCache, Model\Config\Config $configModel) - { - parent::__construct($configCache, $configModel); - $this->config_loaded = false; - - $this->load(); - } - - /** - * {@inheritDoc} - * - * This loads all config values everytime load is called - * - */ - public function load(string $cat = 'config') - { - // Don't load the whole configuration twice - if ($this->config_loaded) { - return; - } - - // If not connected, do nothing - if (!$this->configModel->isConnected()) { - return; - } - - $config = $this->configModel->load(); - $this->config_loaded = true; - - // load the whole category out of the DB into the cache - $this->configCache->load($config, Cache::SOURCE_DB); - } - - /** - * {@inheritDoc} - */ - public function get(string $cat, string $key, $default_value = null, bool $refresh = false) - { - if ($refresh) { - if ($this->configModel->isConnected()) { - $config = $this->configModel->get($cat, $key); - if (isset($config)) { - $this->configCache->set($cat, $key, $config, Cache::SOURCE_DB); - } - } - } - - // use the config cache for return - $result = $this->configCache->get($cat, $key); - - return (isset($result)) ? $result : $default_value; - } - - /** - * {@inheritDoc} - */ - public function set(string $cat, string $key, $value) - { - if (!$this->config_loaded) { - $this->load(); - } - - // set the cache first - $cached = $this->configCache->set($cat, $key, $value, Cache::SOURCE_DB); - - // If there is no connected adapter, we're finished - if (!$this->configModel->isConnected()) { - return $cached; - } - - $stored = $this->configModel->set($cat, $key, $value); - - return $cached && $stored; - } - - /** - * {@inheritDoc} - */ - public function delete(string $cat, string $key) - { - if ($this->config_loaded) { - $this->load(); - } - - $cacheRemoved = $this->configCache->delete($cat, $key); - - if (!$this->configModel->isConnected()) { - return $cacheRemoved; - } - - $storeRemoved = $this->configModel->delete($cat, $key); - - return $cacheRemoved || $storeRemoved; - } - - public function testSetDouble() - { - $this->configModel->shouldReceive('isConnected') - ->andReturn(true); - - // constructor loading - $this->configModel->shouldReceive('load') - ->with('config') - ->andReturn(['config' => ['test' => 'it']]) - ->once(); - - parent::testSetDouble(); - } -} diff --git a/src/Core/Config/Type/BaseConfig.php b/src/Core/Config/Type/BaseConfig.php new file mode 100644 index 0000000000..86a847a7b6 --- /dev/null +++ b/src/Core/Config/Type/BaseConfig.php @@ -0,0 +1,63 @@ +. + * + */ + +namespace Friendica\Core\Config\Type; + +use Friendica\Core\Config\Cache\Cache; +use Friendica\Core\Config\IConfig; +use Friendica\Model; + +/** + * This class is responsible for all system-wide configuration values in Friendica + * There are two types of storage + * - The Config-Files (loaded into the FileCache @see ConfigCache) + * - The Config-DB-Table (per Config-DB-model @see Model\Config\Config) + */ +abstract class BaseConfig implements IConfig +{ + /** + * @var Cache + */ + protected $configCache; + + /** + * @var \Friendica\Core\Config\Model\Config + */ + protected $configModel; + + /** + * @param Cache $configCache The configuration cache (based on the config-files) + * @param \Friendica\Core\Config\Model\Config $configModel The configuration model + */ + public function __construct(Cache $configCache, \Friendica\Core\Config\Model\Config $configModel) + { + $this->configCache = $configCache; + $this->configModel = $configModel; + } + + /** + * {@inheritDoc} + */ + public function getCache() + { + return $this->configCache; + } +} diff --git a/src/Core/Config/Type/JitConfig.php b/src/Core/Config/Type/JitConfig.php new file mode 100644 index 0000000000..5e1fe24c4b --- /dev/null +++ b/src/Core/Config/Type/JitConfig.php @@ -0,0 +1,141 @@ +. + * + */ + +namespace Friendica\Core\Config\Type; + +use Friendica\Core\Config\Cache\Cache; +use Friendica\Core\Config\Model\Config; + +/** + * This class implements the Just-In-Time configuration, which will cache + * config values in a cache, once they are retrieved. + * + * Default Configuration type. + * Provides the best performance for pages loading few configuration variables. + */ +class JitConfig extends BaseConfig +{ + /** + * @var array Array of already loaded db values (even if there was no value) + */ + private $db_loaded; + + /** + * @param Cache $configCache The configuration cache (based on the config-files) + * @param Config $configModel The configuration model + */ + public function __construct(Cache $configCache, Config $configModel) + { + parent::__construct($configCache, $configModel); + $this->db_loaded = []; + + $this->load(); + } + + /** + * {@inheritDoc} + * + */ + public function load(string $cat = 'config') + { + // If not connected, do nothing + if (!$this->configModel->isConnected()) { + return; + } + + $config = $this->configModel->load($cat); + + if (!empty($config[$cat])) { + foreach ($config[$cat] as $key => $value) { + $this->db_loaded[$cat][$key] = true; + } + } + + // load the whole category out of the DB into the cache + $this->configCache->load($config, Cache::SOURCE_DB); + } + + /** + * {@inheritDoc} + */ + public function get(string $cat, string $key, $default_value = null, bool $refresh = false) + { + // if the value isn't loaded or refresh is needed, load it to the cache + if ($this->configModel->isConnected() && + (empty($this->db_loaded[$cat][$key]) || + $refresh)) { + + $dbvalue = $this->configModel->get($cat, $key); + + if (isset($dbvalue)) { + $this->configCache->set($cat, $key, $dbvalue, Cache::SOURCE_DB); + unset($dbvalue); + } + + $this->db_loaded[$cat][$key] = true; + } + + // use the config cache for return + $result = $this->configCache->get($cat, $key); + + return (isset($result)) ? $result : $default_value; + } + + /** + * {@inheritDoc} + */ + public function set(string $cat, string $key, $value) + { + // set the cache first + $cached = $this->configCache->set($cat, $key, $value, Cache::SOURCE_DB); + + // If there is no connected adapter, we're finished + if (!$this->configModel->isConnected()) { + return $cached; + } + + $stored = $this->configModel->set($cat, $key, $value); + + $this->db_loaded[$cat][$key] = $stored; + + return $cached && $stored; + } + + /** + * {@inheritDoc} + */ + public function delete(string $cat, string $key) + { + $cacheRemoved = $this->configCache->delete($cat, $key); + + if (isset($this->db_loaded[$cat][$key])) { + unset($this->db_loaded[$cat][$key]); + } + + if (!$this->configModel->isConnected()) { + return $cacheRemoved; + } + + $storeRemoved = $this->configModel->delete($cat, $key); + + return $cacheRemoved || $storeRemoved; + } +} diff --git a/src/Core/Config/Type/PreloadConfig.php b/src/Core/Config/Type/PreloadConfig.php new file mode 100644 index 0000000000..c6abfcd9fc --- /dev/null +++ b/src/Core/Config/Type/PreloadConfig.php @@ -0,0 +1,150 @@ +. + * + */ + +namespace Friendica\Core\Config\Type; + +use Friendica\Core\Config\Cache\Cache; +use Friendica\Core\Config\Model\Config; + +/** + * This class implements the preload configuration, which will cache + * all config values per call in a cache. + * + * Minimizes the number of database queries to retrieve configuration values at the cost of memory. + */ +class PreloadConfig extends BaseConfig +{ + /** @var bool */ + private $config_loaded; + + /** + * @param Cache $configCache The configuration cache (based on the config-files) + * @param Config $configModel The configuration model + */ + public function __construct(Cache $configCache, Config $configModel) + { + parent::__construct($configCache, $configModel); + $this->config_loaded = false; + + $this->load(); + } + + /** + * {@inheritDoc} + * + * This loads all config values everytime load is called + * + */ + public function load(string $cat = 'config') + { + // Don't load the whole configuration twice + if ($this->config_loaded) { + return; + } + + // If not connected, do nothing + if (!$this->configModel->isConnected()) { + return; + } + + $config = $this->configModel->load(); + $this->config_loaded = true; + + // load the whole category out of the DB into the cache + $this->configCache->load($config, Cache::SOURCE_DB); + } + + /** + * {@inheritDoc} + */ + public function get(string $cat, string $key, $default_value = null, bool $refresh = false) + { + if ($refresh) { + if ($this->configModel->isConnected()) { + $config = $this->configModel->get($cat, $key); + if (isset($config)) { + $this->configCache->set($cat, $key, $config, Cache::SOURCE_DB); + } + } + } + + // use the config cache for return + $result = $this->configCache->get($cat, $key); + + return (isset($result)) ? $result : $default_value; + } + + /** + * {@inheritDoc} + */ + public function set(string $cat, string $key, $value) + { + if (!$this->config_loaded) { + $this->load(); + } + + // set the cache first + $cached = $this->configCache->set($cat, $key, $value, Cache::SOURCE_DB); + + // If there is no connected adapter, we're finished + if (!$this->configModel->isConnected()) { + return $cached; + } + + $stored = $this->configModel->set($cat, $key, $value); + + return $cached && $stored; + } + + /** + * {@inheritDoc} + */ + public function delete(string $cat, string $key) + { + if ($this->config_loaded) { + $this->load(); + } + + $cacheRemoved = $this->configCache->delete($cat, $key); + + if (!$this->configModel->isConnected()) { + return $cacheRemoved; + } + + $storeRemoved = $this->configModel->delete($cat, $key); + + return $cacheRemoved || $storeRemoved; + } + + public function testSetDouble() + { + $this->configModel->shouldReceive('isConnected') + ->andReturn(true); + + // constructor loading + $this->configModel->shouldReceive('load') + ->with('config') + ->andReturn(['config' => ['test' => 'it']]) + ->once(); + + parent::testSetDouble(); + } +} diff --git a/src/Core/Installer.php b/src/Core/Installer.php index 96fe941564..fc0da6cbed 100644 --- a/src/Core/Installer.php +++ b/src/Core/Installer.php @@ -23,7 +23,7 @@ namespace Friendica\Core; use DOMDocument; use Exception; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Database\Database; use Friendica\Database\DBStructure; use Friendica\DI; @@ -278,7 +278,7 @@ class Installer $cmd = "$phppath -v"; $result = trim(shell_exec($cmd)); $passed2 = (strpos($result, "(cli)") !== false); - list($result) = explode("\n", $result); + [$result] = explode("\n", $result); $help = ""; if (!$passed2) { $help .= DI::l10n()->t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29") . EOL; @@ -678,8 +678,8 @@ class Installer /** * Setup the default cache for a new installation * - * @param Cache $configCache The configuration cache - * @param string $basePath The determined basepath + * @param \Friendica\Core\Config\Cache\Cache $configCache The configuration cache + * @param string $basePath The determined basepath * * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ diff --git a/src/Core/PConfig/Cache.php b/src/Core/PConfig/Cache.php deleted file mode 100644 index d19c34d80a..0000000000 --- a/src/Core/PConfig/Cache.php +++ /dev/null @@ -1,208 +0,0 @@ -. - * - */ - -namespace Friendica\Core\PConfig; - -use ParagonIE\HiddenString\HiddenString; - -/** - * The Friendica config cache for users - */ -class Cache -{ - /** - * @var array - */ - private $config; - - /** - * @var bool - */ - private $hidePasswordOutput; - - /** - * @param bool $hidePasswordOutput True, if cache variables should take extra care of password values - */ - public function __construct(bool $hidePasswordOutput = true) - { - $this->hidePasswordOutput = $hidePasswordOutput; - } - - /** - * Tries to load the specified configuration array into the user specific config array. - * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config. - * - * @param int $uid - * @param array $config - */ - public function load($uid, array $config) - { - if (!is_int($uid)) { - return; - } - - $categories = array_keys($config); - - foreach ($categories as $category) { - if (isset($config[$category]) && is_array($config[$category])) { - - $keys = array_keys($config[$category]); - - foreach ($keys as $key) { - $value = $config[$category][$key]; - if (isset($value)) { - $this->set($uid, $category, $key, $value); - } - } - } - } - } - - /** - * Retrieves a value from the user config cache - * - * @param int $uid User Id - * @param string $cat Config category - * @param string $key Config key - * - * @return null|string The value of the config entry or null if not set - */ - public function get($uid, string $cat, string $key = null) - { - if (!is_int($uid)) { - return null; - } - - if (isset($this->config[$uid][$cat][$key])) { - return $this->config[$uid][$cat][$key]; - } elseif (!isset($key) && isset($this->config[$uid][$cat])) { - return $this->config[$uid][$cat]; - } else { - return null; - } - } - - /** - * Sets a value in the user config cache - * - * Accepts raw output from the pconfig table - * - * @param int $uid User Id - * @param string $cat Config category - * @param string $key Config key - * @param mixed $value Value to set - * - * @return bool Set successful - */ - public function set($uid, string $cat, string $key, $value) - { - if (!is_int($uid)) { - return false; - } - - if (!isset($this->config[$uid]) || !is_array($this->config[$uid])) { - $this->config[$uid] = []; - } - - if (!isset($this->config[$uid][$cat])) { - $this->config[$uid][$cat] = []; - } - - if ($this->hidePasswordOutput && - $key == 'password' && - !empty($value) && is_string($value)) { - $this->config[$uid][$cat][$key] = new HiddenString((string)$value); - } else { - $this->config[$uid][$cat][$key] = $value; - } - - - return true; - } - - /** - * Deletes a value from the user config cache - * - * @param int $uid User Id - * @param string $cat Config category - * @param string $key Config key - * - * @return bool true, if deleted - */ - public function delete($uid, string $cat, string $key) - { - if (!is_int($uid)) { - return false; - } - - if (isset($this->config[$uid][$cat][$key])) { - unset($this->config[$uid][$cat][$key]); - if (count($this->config[$uid][$cat]) == 0) { - unset($this->config[$uid][$cat]); - if (count($this->config[$uid]) == 0) { - unset($this->config[$uid]); - } - } - - return true; - } else { - return false; - } - } - - /** - * Returns the whole configuration - * - * @return array The configuration - */ - public function getAll() - { - return $this->config; - } - - /** - * Returns an array with missing categories/Keys - * - * @param array $config The array to check - * - * @return array - */ - public function keyDiff(array $config) - { - $return = []; - - $categories = array_keys($config); - - foreach ($categories as $category) { - if (is_array($config[$category])) { - $keys = array_keys($config[$category]); - - foreach ($keys as $key) { - if (!isset($this->config[$category][$key])) { - $return[$category][$key] = $config[$category][$key]; - } - } - } - } - - return $return; - } -} diff --git a/src/Core/PConfig/Cache/Cache.php b/src/Core/PConfig/Cache/Cache.php new file mode 100644 index 0000000000..97554b2fe9 --- /dev/null +++ b/src/Core/PConfig/Cache/Cache.php @@ -0,0 +1,208 @@ +. + * + */ + +namespace Friendica\Core\PConfig\Cache; + +use ParagonIE\HiddenString\HiddenString; + +/** + * The Friendica config cache for users + */ +class Cache +{ + /** + * @var array + */ + private $config; + + /** + * @var bool + */ + private $hidePasswordOutput; + + /** + * @param bool $hidePasswordOutput True, if cache variables should take extra care of password values + */ + public function __construct(bool $hidePasswordOutput = true) + { + $this->hidePasswordOutput = $hidePasswordOutput; + } + + /** + * Tries to load the specified configuration array into the user specific config array. + * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config. + * + * @param int $uid + * @param array $config + */ + public function load($uid, array $config) + { + if (!is_int($uid)) { + return; + } + + $categories = array_keys($config); + + foreach ($categories as $category) { + if (isset($config[$category]) && is_array($config[$category])) { + + $keys = array_keys($config[$category]); + + foreach ($keys as $key) { + $value = $config[$category][$key]; + if (isset($value)) { + $this->set($uid, $category, $key, $value); + } + } + } + } + } + + /** + * Retrieves a value from the user config cache + * + * @param int $uid User Id + * @param string $cat Config category + * @param string $key Config key + * + * @return null|string The value of the config entry or null if not set + */ + public function get($uid, string $cat, string $key = null) + { + if (!is_int($uid)) { + return null; + } + + if (isset($this->config[$uid][$cat][$key])) { + return $this->config[$uid][$cat][$key]; + } elseif (!isset($key) && isset($this->config[$uid][$cat])) { + return $this->config[$uid][$cat]; + } else { + return null; + } + } + + /** + * Sets a value in the user config cache + * + * Accepts raw output from the pconfig table + * + * @param int $uid User Id + * @param string $cat Config category + * @param string $key Config key + * @param mixed $value Value to set + * + * @return bool Set successful + */ + public function set($uid, string $cat, string $key, $value) + { + if (!is_int($uid)) { + return false; + } + + if (!isset($this->config[$uid]) || !is_array($this->config[$uid])) { + $this->config[$uid] = []; + } + + if (!isset($this->config[$uid][$cat])) { + $this->config[$uid][$cat] = []; + } + + if ($this->hidePasswordOutput && + $key == 'password' && + !empty($value) && is_string($value)) { + $this->config[$uid][$cat][$key] = new HiddenString((string)$value); + } else { + $this->config[$uid][$cat][$key] = $value; + } + + + return true; + } + + /** + * Deletes a value from the user config cache + * + * @param int $uid User Id + * @param string $cat Config category + * @param string $key Config key + * + * @return bool true, if deleted + */ + public function delete($uid, string $cat, string $key) + { + if (!is_int($uid)) { + return false; + } + + if (isset($this->config[$uid][$cat][$key])) { + unset($this->config[$uid][$cat][$key]); + if (count($this->config[$uid][$cat]) == 0) { + unset($this->config[$uid][$cat]); + if (count($this->config[$uid]) == 0) { + unset($this->config[$uid]); + } + } + + return true; + } else { + return false; + } + } + + /** + * Returns the whole configuration + * + * @return array The configuration + */ + public function getAll() + { + return $this->config; + } + + /** + * Returns an array with missing categories/Keys + * + * @param array $config The array to check + * + * @return array + */ + public function keyDiff(array $config) + { + $return = []; + + $categories = array_keys($config); + + foreach ($categories as $category) { + if (is_array($config[$category])) { + $keys = array_keys($config[$category]); + + foreach ($keys as $key) { + if (!isset($this->config[$category][$key])) { + $return[$category][$key] = $config[$category][$key]; + } + } + } + } + + return $return; + } +} diff --git a/src/Core/PConfig/Factory/PConfigFactory.php b/src/Core/PConfig/Factory/PConfigFactory.php new file mode 100644 index 0000000000..eb248f14ad --- /dev/null +++ b/src/Core/PConfig/Factory/PConfigFactory.php @@ -0,0 +1,48 @@ +. + * + */ + +namespace Friendica\Core\PConfig\Factory; + +use Friendica\Core\Config\Cache\Cache; +use Friendica\Core\PConfig\IPConfig; +use Friendica\Core\PConfig\Model\PConfig as PConfigModel; +use Friendica\Core\PConfig\Type; + +class PConfigFactory +{ + /** + * @param Cache $configCache The config cache + * @param \Friendica\Core\PConfig\Cache\Cache $pConfigCache The personal config cache + * @param PConfigModel $configModel The configuration model + * + * @return IPConfig + */ + public function create(Cache $configCache, \Friendica\Core\PConfig\Cache\Cache $pConfigCache, PConfigModel $configModel) + { + if ($configCache->get('system', 'config_adapter') === 'preload') { + $configuration = new Type\PreloadPConfig($pConfigCache, $configModel); + } else { + $configuration = new Type\JitPConfig($pConfigCache, $configModel); + } + + return $configuration; + } +} diff --git a/src/Core/PConfig/IPConfig.php b/src/Core/PConfig/IPConfig.php index 25d81bd7e9..1795a60392 100644 --- a/src/Core/PConfig/IPConfig.php +++ b/src/Core/PConfig/IPConfig.php @@ -21,6 +21,8 @@ namespace Friendica\Core\PConfig; +use Friendica\Core\Config\Cache\Cache; + /** * Interface for accessing user specific configurations */ @@ -95,7 +97,7 @@ interface IPConfig /** * Returns the Config Cache * - * @return Cache + * @return \Friendica\Core\PConfig\Cache\Cache */ function getCache(); } diff --git a/src/Core/PConfig/JitPConfig.php b/src/Core/PConfig/JitPConfig.php deleted file mode 100644 index 251f1bd0b8..0000000000 --- a/src/Core/PConfig/JitPConfig.php +++ /dev/null @@ -1,153 +0,0 @@ -. - * - */ - -namespace Friendica\Core\PConfig; - -use Friendica\Core\BasePConfig; -use Friendica\Model; - -/** - * This class implements the Just-In-Time configuration, which will cache - * user config values in a cache, once they are retrieved. - * - * Default Configuration type. - * Provides the best performance for pages loading few configuration variables. - */ -class JitPConfig extends BasePConfig -{ - /** - * @var array Array of already loaded db values (even if there was no value) - */ - private $db_loaded; - - /** - * @param Cache $configCache The configuration cache - * @param Model\Config\PConfig $configModel The configuration model - */ - public function __construct(Cache $configCache, Model\Config\PConfig $configModel) - { - parent::__construct($configCache, $configModel); - $this->db_loaded = []; - } - - /** - * {@inheritDoc} - * - */ - public function load(int $uid, string $cat = 'config') - { - // If not connected or no uid, do nothing - if (!$uid || !$this->configModel->isConnected()) { - return; - } - - $config = $this->configModel->load($uid, $cat); - - if (!empty($config[$cat])) { - foreach ($config[$cat] as $key => $value) { - $this->db_loaded[$uid][$cat][$key] = true; - } - } - - // load the whole category out of the DB into the cache - $this->configCache->load($uid, $config); - - return $config; - } - - /** - * {@inheritDoc} - */ - public function get(int $uid, string $cat, string $key, $default_value = null, bool $refresh = false) - { - if (!$uid) { - return $default_value; - } - - // if the value isn't loaded or refresh is needed, load it to the cache - if ($this->configModel->isConnected() && - (empty($this->db_loaded[$uid][$cat][$key]) || - $refresh)) { - - $dbvalue = $this->configModel->get($uid, $cat, $key); - - if (isset($dbvalue)) { - $this->configCache->set($uid, $cat, $key, $dbvalue); - unset($dbvalue); - } - - $this->db_loaded[$uid][$cat][$key] = true; - } - - // use the config cache for return - $result = $this->configCache->get($uid, $cat, $key); - - return (isset($result)) ? $result : $default_value; - } - - /** - * {@inheritDoc} - */ - public function set(int $uid, string $cat, string $key, $value) - { - if (!$uid) { - return false; - } - - // set the cache first - $cached = $this->configCache->set($uid, $cat, $key, $value); - - // If there is no connected adapter, we're finished - if (!$this->configModel->isConnected()) { - return $cached; - } - - $stored = $this->configModel->set($uid, $cat, $key, $value); - - $this->db_loaded[$uid][$cat][$key] = $stored; - - return $cached && $stored; - } - - /** - * {@inheritDoc} - */ - public function delete(int $uid, string $cat, string $key) - { - if (!$uid) { - return false; - } - - $cacheRemoved = $this->configCache->delete($uid, $cat, $key); - - if (isset($this->db_loaded[$uid][$cat][$key])) { - unset($this->db_loaded[$uid][$cat][$key]); - } - - if (!$this->configModel->isConnected()) { - return $cacheRemoved; - } - - $storeRemoved = $this->configModel->delete($uid, $cat, $key); - - return $cacheRemoved || $storeRemoved; - } -} diff --git a/src/Core/PConfig/Model/PConfig.php b/src/Core/PConfig/Model/PConfig.php new file mode 100644 index 0000000000..35ff34a56b --- /dev/null +++ b/src/Core/PConfig/Model/PConfig.php @@ -0,0 +1,177 @@ +. + * + */ + +namespace Friendica\Core\PConfig\Model; + +use Friendica\Core\Config\Model\DbaUtils; +use Friendica\Database\Database; + +/** + * The Config model backend for users, which is using the general DB-model backend for user-configs + */ +class PConfig +{ + /** @var Database */ + protected $dba; + + /** + * @param Database $dba The database connection of this model + */ + public function __construct(Database $dba) + { + $this->dba = $dba; + } + + /** + * Checks if the model is currently connected + * + * @return bool + */ + public function isConnected() + { + return $this->dba->isConnected(); + } + + /** + * Loads all configuration values and returns the loaded category as an array. + * + * @param int $uid The id of the user to load + * @param string|null $cat The category of the configuration values to load + * + * @return array The config array + * + * @throws \Exception In case DB calls are invalid + */ + public function load(int $uid, string $cat = null) + { + $return = []; + + if (empty($cat)) { + $configs = $this->dba->select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]); + } else { + $configs = $this->dba->select('pconfig', ['cat', 'v', 'k'], ['cat' => $cat, 'uid' => $uid]); + } + + while ($config = $this->dba->fetch($configs)) { + $key = $config['k']; + $value = DbaUtils::toConfigValue($config['v']); + + // just save it in case it is set + if (isset($value)) { + $return[$config['cat']][$key] = $value; + } + } + $this->dba->close($configs); + + return $return; + } + + /** + * Get a particular user config variable out of the DB with the + * given category name ($cat) and a key ($key). + * + * Note: Boolean variables are defined as 0/1 in the database + * + * @param int $uid The id of the user to load + * @param string $cat The category of the configuration value + * @param string $key The configuration key to query + * + * @return array|string|null Stored value or null if it does not exist + * + * @throws \Exception In case DB calls are invalid + */ + public function get(int $uid, string $cat, string $key) + { + if (!$this->isConnected()) { + return null; + } + + $config = $this->dba->selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]); + if ($this->dba->isResult($config)) { + $value = DbaUtils::toConfigValue($config['v']); + + // just return it in case it is set + if (isset($value)) { + return $value; + } + } + + return null; + } + + /** + * Stores a config value ($value) in the category ($cat) under the key ($key) for a + * given user ($uid). + * + * Note: Please do not store booleans - convert to 0/1 integer values! + * + * @param int $uid The id of the user to load + * @param string $cat The category of the configuration value + * @param string $key The configuration key to set + * @param mixed $value The value to store + * + * @return bool Operation success + * + * @throws \Exception In case DB calls are invalid + */ + public function set(int $uid, string $cat, string $key, $value) + { + if (!$this->isConnected()) { + return false; + } + + // We store our setting values in a string variable. + // So we have to do the conversion here so that the compare below works. + // The exception are array values. + $compare_value = (!is_array($value) ? (string)$value : $value); + $stored_value = $this->get($uid, $cat, $key); + + if (isset($stored_value) && ($stored_value === $compare_value)) { + return true; + } + + $dbvalue = DbaUtils::toDbValue($value); + + $result = $this->dba->update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true); + + return $result; + } + + /** + * Removes the configured value of the given user. + * + * @param int $uid The id of the user to load + * @param string $cat The category of the configuration value + * @param string $key The configuration key to delete + * + * @return bool Operation success + * + * @throws \Exception In case DB calls are invalid + */ + public function delete(int $uid, string $cat, string $key) + { + if (!$this->isConnected()) { + return false; + } + + return $this->dba->delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]); + } +} diff --git a/src/Core/PConfig/PreloadPConfig.php b/src/Core/PConfig/PreloadPConfig.php deleted file mode 100644 index abdc18b159..0000000000 --- a/src/Core/PConfig/PreloadPConfig.php +++ /dev/null @@ -1,150 +0,0 @@ -. - * - */ - -namespace Friendica\Core\PConfig; - -use Friendica\Core\BasePConfig; -use Friendica\Model; - -/** - * This class implements the preload configuration, which will cache - * all user config values per call in a cache. - * - * Minimizes the number of database queries to retrieve configuration values at the cost of memory. - */ -class PreloadPConfig extends BasePConfig -{ - /** @var array */ - private $config_loaded; - - /** - * @param Cache $configCache The configuration cache - * @param Model\Config\PConfig $configModel The configuration model - */ - public function __construct(Cache $configCache, Model\Config\PConfig $configModel) - { - parent::__construct($configCache, $configModel); - $this->config_loaded = []; - } - - /** - * {@inheritDoc} - * - * This loads all config values everytime load is called - * - */ - public function load(int $uid, string $cat = 'config') - { - // Don't load the whole configuration twice or with invalid uid - if (!$uid || !empty($this->config_loaded[$uid])) { - return; - } - - // If not connected, do nothing - if (!$this->configModel->isConnected()) { - return; - } - - $config = $this->configModel->load($uid); - $this->config_loaded[$uid] = true; - - // load the whole category out of the DB into the cache - $this->configCache->load($uid, $config); - - return $config; - } - - /** - * {@inheritDoc} - */ - public function get(int $uid, string $cat, string $key, $default_value = null, bool $refresh = false) - { - if (!$uid) { - return $default_value; - } - - if (empty($this->config_loaded[$uid])) { - $this->load($uid); - } elseif ($refresh) { - if ($this->configModel->isConnected()) { - $config = $this->configModel->get($uid, $cat, $key); - if (isset($config)) { - $this->configCache->set($uid, $cat, $key, $config); - } - } - } - - // use the config cache for return - $result = $this->configCache->get($uid, $cat, $key); - - return (isset($result)) ? $result : $default_value; - } - - /** - * {@inheritDoc} - */ - public function set(int $uid, string $cat, string $key, $value) - { - if (!$uid) { - return false; - } - - if (empty($this->config_loaded[$uid])) { - $this->load($uid); - } - - // set the cache first - $cached = $this->configCache->set($uid, $cat, $key, $value); - - // If there is no connected adapter, we're finished - if (!$this->configModel->isConnected()) { - return $cached; - } - - $stored = $this->configModel->set($uid, $cat, $key, $value); - - return $cached && $stored; - } - - /** - * {@inheritDoc} - */ - public function delete(int $uid, string $cat, string $key) - { - if (!$uid) { - return false; - } - - if (empty($this->config_loaded[$uid])) { - $this->load($uid); - } - - $cacheRemoved = $this->configCache->delete($uid, $cat, $key); - - if (!$this->configModel->isConnected()) { - return $cacheRemoved; - } - - $storeRemoved = $this->configModel->delete($uid, $cat, $key); - - return $cacheRemoved || $storeRemoved; - } -} diff --git a/src/Core/PConfig/Type/BasePConfig.php b/src/Core/PConfig/Type/BasePConfig.php new file mode 100644 index 0000000000..9ae374f2e0 --- /dev/null +++ b/src/Core/PConfig/Type/BasePConfig.php @@ -0,0 +1,66 @@ +. + * + */ + +namespace Friendica\Core\PConfig\Type; + +use Friendica\Core\PConfig\Cache\Cache; +use Friendica\Core\PConfig\IPConfig; +use Friendica\Model; + +/** + * This class is responsible for the user-specific configuration values in Friendica + * The values are set through the Config-DB-Table (per Config-DB-model @see Model\Config\PConfig) + * + * The configuration cache (@see Cache\PConfigCache) is used for temporary caching of database calls. This will + * increase the performance. + */ +abstract class BasePConfig implements IPConfig +{ + /** + * @var \Friendica\Core\PConfig\Cache\Cache + */ + protected $configCache; + + /** + * @var \Friendica\Core\PConfig\Model\PConfig + */ + protected $configModel; + + /** + * @param \Friendica\Core\PConfig\Cache\Cache $configCache The configuration cache + * @param \Friendica\Core\PConfig\Model\PConfig $configModel The configuration model + */ + public function __construct(Cache $configCache, \Friendica\Core\PConfig\Model\PConfig $configModel) + { + $this->configCache = $configCache; + $this->configModel = $configModel; + } + + /** + * Returns the Config Cache + * + * @return \Friendica\Core\PConfig\Cache\Cache + */ + public function getCache() + { + return $this->configCache; + } +} diff --git a/src/Core/PConfig/Type/JitPConfig.php b/src/Core/PConfig/Type/JitPConfig.php new file mode 100644 index 0000000000..99c3b581bf --- /dev/null +++ b/src/Core/PConfig/Type/JitPConfig.php @@ -0,0 +1,153 @@ +. + * + */ + +namespace Friendica\Core\PConfig\Type; + +use Friendica\Core\PConfig\Cache\Cache; +use Friendica\Model; + +/** + * This class implements the Just-In-Time configuration, which will cache + * user config values in a cache, once they are retrieved. + * + * Default Configuration type. + * Provides the best performance for pages loading few configuration variables. + */ +class JitPConfig extends BasePConfig +{ + /** + * @var array Array of already loaded db values (even if there was no value) + */ + private $db_loaded; + + /** + * @param Cache $configCache The configuration cache + * @param \Friendica\Core\PConfig\Model\PConfig $configModel The configuration model + */ + public function __construct(Cache $configCache, \Friendica\Core\PConfig\Model\PConfig $configModel) + { + parent::__construct($configCache, $configModel); + $this->db_loaded = []; + } + + /** + * {@inheritDoc} + * + */ + public function load(int $uid, string $cat = 'config') + { + // If not connected or no uid, do nothing + if (!$uid || !$this->configModel->isConnected()) { + return; + } + + $config = $this->configModel->load($uid, $cat); + + if (!empty($config[$cat])) { + foreach ($config[$cat] as $key => $value) { + $this->db_loaded[$uid][$cat][$key] = true; + } + } + + // load the whole category out of the DB into the cache + $this->configCache->load($uid, $config); + + return $config; + } + + /** + * {@inheritDoc} + */ + public function get(int $uid, string $cat, string $key, $default_value = null, bool $refresh = false) + { + if (!$uid) { + return $default_value; + } + + // if the value isn't loaded or refresh is needed, load it to the cache + if ($this->configModel->isConnected() && + (empty($this->db_loaded[$uid][$cat][$key]) || + $refresh)) { + + $dbvalue = $this->configModel->get($uid, $cat, $key); + + if (isset($dbvalue)) { + $this->configCache->set($uid, $cat, $key, $dbvalue); + unset($dbvalue); + } + + $this->db_loaded[$uid][$cat][$key] = true; + } + + // use the config cache for return + $result = $this->configCache->get($uid, $cat, $key); + + return (isset($result)) ? $result : $default_value; + } + + /** + * {@inheritDoc} + */ + public function set(int $uid, string $cat, string $key, $value) + { + if (!$uid) { + return false; + } + + // set the cache first + $cached = $this->configCache->set($uid, $cat, $key, $value); + + // If there is no connected adapter, we're finished + if (!$this->configModel->isConnected()) { + return $cached; + } + + $stored = $this->configModel->set($uid, $cat, $key, $value); + + $this->db_loaded[$uid][$cat][$key] = $stored; + + return $cached && $stored; + } + + /** + * {@inheritDoc} + */ + public function delete(int $uid, string $cat, string $key) + { + if (!$uid) { + return false; + } + + $cacheRemoved = $this->configCache->delete($uid, $cat, $key); + + if (isset($this->db_loaded[$uid][$cat][$key])) { + unset($this->db_loaded[$uid][$cat][$key]); + } + + if (!$this->configModel->isConnected()) { + return $cacheRemoved; + } + + $storeRemoved = $this->configModel->delete($uid, $cat, $key); + + return $cacheRemoved || $storeRemoved; + } +} diff --git a/src/Core/PConfig/Type/PreloadPConfig.php b/src/Core/PConfig/Type/PreloadPConfig.php new file mode 100644 index 0000000000..4498bb409d --- /dev/null +++ b/src/Core/PConfig/Type/PreloadPConfig.php @@ -0,0 +1,150 @@ +. + * + */ + +namespace Friendica\Core\PConfig\Type; + +use Friendica\Core\PConfig\Cache\Cache; +use Friendica\Model; + +/** + * This class implements the preload configuration, which will cache + * all user config values per call in a cache. + * + * Minimizes the number of database queries to retrieve configuration values at the cost of memory. + */ +class PreloadPConfig extends BasePConfig +{ + /** @var array */ + private $config_loaded; + + /** + * @param \Friendica\Core\PConfig\Cache\Cache $configCache The configuration cache + * @param \Friendica\Core\PConfig\Model\PConfig $configModel The configuration model + */ + public function __construct(Cache $configCache, \Friendica\Core\PConfig\Model\PConfig $configModel) + { + parent::__construct($configCache, $configModel); + $this->config_loaded = []; + } + + /** + * {@inheritDoc} + * + * This loads all config values everytime load is called + * + */ + public function load(int $uid, string $cat = 'config') + { + // Don't load the whole configuration twice or with invalid uid + if (!$uid || !empty($this->config_loaded[$uid])) { + return; + } + + // If not connected, do nothing + if (!$this->configModel->isConnected()) { + return; + } + + $config = $this->configModel->load($uid); + $this->config_loaded[$uid] = true; + + // load the whole category out of the DB into the cache + $this->configCache->load($uid, $config); + + return $config; + } + + /** + * {@inheritDoc} + */ + public function get(int $uid, string $cat, string $key, $default_value = null, bool $refresh = false) + { + if (!$uid) { + return $default_value; + } + + if (empty($this->config_loaded[$uid])) { + $this->load($uid); + } elseif ($refresh) { + if ($this->configModel->isConnected()) { + $config = $this->configModel->get($uid, $cat, $key); + if (isset($config)) { + $this->configCache->set($uid, $cat, $key, $config); + } + } + } + + // use the config cache for return + $result = $this->configCache->get($uid, $cat, $key); + + return (isset($result)) ? $result : $default_value; + } + + /** + * {@inheritDoc} + */ + public function set(int $uid, string $cat, string $key, $value) + { + if (!$uid) { + return false; + } + + if (empty($this->config_loaded[$uid])) { + $this->load($uid); + } + + // set the cache first + $cached = $this->configCache->set($uid, $cat, $key, $value); + + // If there is no connected adapter, we're finished + if (!$this->configModel->isConnected()) { + return $cached; + } + + $stored = $this->configModel->set($uid, $cat, $key, $value); + + return $cached && $stored; + } + + /** + * {@inheritDoc} + */ + public function delete(int $uid, string $cat, string $key) + { + if (!$uid) { + return false; + } + + if (empty($this->config_loaded[$uid])) { + $this->load($uid); + } + + $cacheRemoved = $this->configCache->delete($uid, $cat, $key); + + if (!$this->configModel->isConnected()) { + return $cacheRemoved; + } + + $storeRemoved = $this->configModel->delete($uid, $cat, $key); + + return $cacheRemoved || $storeRemoved; + } +} diff --git a/src/Database/Database.php b/src/Database/Database.php index a654cccc5b..4a8d5d36e7 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -21,7 +21,7 @@ namespace Friendica\Database; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Core\System; use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Util\DateTimeFormat; diff --git a/src/Factory/ConfigFactory.php b/src/Factory/ConfigFactory.php deleted file mode 100644 index cf55640960..0000000000 --- a/src/Factory/ConfigFactory.php +++ /dev/null @@ -1,122 +0,0 @@ -. - * - */ - -namespace Friendica\Factory; - -use Exception; -use Friendica\Core\Config; -use Friendica\Core\Config\Cache; -use Friendica\Model\Config\Config as ConfigModel; -use Friendica\Model\Config\PConfig as PConfigModel; -use Friendica\Util\ConfigFileLoader; - -class ConfigFactory -{ - /** - * The key of the $_SERVER variable to override the config directory - * - * @var string - */ - const CONFIG_DIR_ENV = 'FRIENDICA_CONFIG_DIR'; - - /** - * The Sub directory of the config-files - * - * @var string - */ - const CONFIG_DIR = 'config'; - - /** - * The Sub directory of the static config-files - * - * @var string - */ - const STATIC_DIR = 'static'; - - /** - * @param string $basePath The basepath of FRIENDICA - * @param array $serer the $_SERVER array - * - * @return ConfigFileLoader - */ - public function createConfigFileLoader(string $basePath, array $server = []) - { - if (!empty($server[self::CONFIG_DIR_ENV]) && is_dir($server[self::CONFIG_DIR_ENV])) { - $configDir = $server[self::CONFIG_DIR_ENV]; - } else { - $configDir = $basePath . DIRECTORY_SEPARATOR . self::CONFIG_DIR; - } - $staticDir = $basePath . DIRECTORY_SEPARATOR . self::STATIC_DIR; - - return new ConfigFileLoader($basePath, $configDir, $staticDir); - } - - /** - * @param ConfigFileLoader $loader The Config Cache loader (INI/config/.htconfig) - * - * @return Cache - * - * @throws Exception - */ - public function createCache(ConfigFileLoader $loader, array $server = []) - { - $configCache = new Cache(); - $loader->setupCache($configCache, $server); - - return $configCache; - } - - /** - * @param Cache $configCache The config cache of this adapter - * @param ConfigModel $configModel The configuration model - * - * @return Config\IConfig - */ - public function createConfig(Cache $configCache, ConfigModel $configModel) - { - if ($configCache->get('system', 'config_adapter') === 'preload') { - $configuration = new Config\PreloadConfig($configCache, $configModel); - } else { - $configuration = new Config\JitConfig($configCache, $configModel); - } - - - return $configuration; - } - - /** - * @param Cache $configCache The config cache - * @param \Friendica\Core\PConfig\Cache $pConfigCache The personal config cache - * @param PConfigModel $configModel The configuration model - * - * @return \Friendica\Core\PConfig\IPConfig - */ - public function createPConfig(Cache $configCache, \Friendica\Core\PConfig\Cache $pConfigCache, PConfigModel $configModel) - { - if ($configCache->get('system', 'config_adapter') === 'preload') { - $configuration = new \Friendica\Core\PConfig\PreloadPConfig($pConfigCache, $configModel); - } else { - $configuration = new \Friendica\Core\PConfig\JitPConfig($pConfigCache, $configModel); - } - - return $configuration; - } -} diff --git a/src/Model/Config/Config.php b/src/Model/Config/Config.php deleted file mode 100644 index ecc6b6f665..0000000000 --- a/src/Model/Config/Config.php +++ /dev/null @@ -1,150 +0,0 @@ -. - * - */ - -namespace Friendica\Model\Config; - - -/** - * The Config model backend, which is using the general DB-model backend for configs - */ -class Config extends DbaConfig -{ - /** - * Loads all configuration values and returns the loaded category as an array. - * - * @param string|null $cat The category of the configuration values to load - * - * @return array The config array - * - * @throws \Exception In case DB calls are invalid - */ - public function load(string $cat = null) - { - $return = []; - - if (empty($cat)) { - $configs = $this->dba->select('config', ['cat', 'v', 'k']); - } else { - $configs = $this->dba->select('config', ['cat', 'v', 'k'], ['cat' => $cat]); - } - - while ($config = $this->dba->fetch($configs)) { - - $key = $config['k']; - $value = $this->toConfigValue($config['v']); - - // just save it in case it is set - if (isset($value)) { - $return[$config['cat']][$key] = $value; - } - } - $this->dba->close($configs); - - return $return; - } - - /** - * Get a particular, system-wide config variable out of the DB with the - * given category name ($cat) and a key ($key). - * - * Note: Boolean variables are defined as 0/1 in the database - * - * @param string $cat The category of the configuration value - * @param string $key The configuration key to query - * - * @return array|string|null Stored value or null if it does not exist - * - * @throws \Exception In case DB calls are invalid - */ - public function get(string $cat, string $key) - { - if (!$this->isConnected()) { - return null; - } - - $config = $this->dba->selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]); - if ($this->dba->isResult($config)) { - $value = $this->toConfigValue($config['v']); - - // just return it in case it is set - if (isset($value)) { - return $value; - } - } - - return null; - } - - /** - * Stores a config value ($value) in the category ($cat) under the key ($key). - * - * Note: Please do not store booleans - convert to 0/1 integer values! - * - * @param string $cat The category of the configuration value - * @param string $key The configuration key to set - * @param mixed $value The value to store - * - * @return bool Operation success - * - * @throws \Exception In case DB calls are invalid - */ - public function set(string $cat, string $key, $value) - { - if (!$this->isConnected()) { - return false; - } - - // We store our setting values in a string variable. - // So we have to do the conversion here so that the compare below works. - // The exception are array values. - $compare_value = (!is_array($value) ? (string)$value : $value); - $stored_value = $this->get($cat, $key); - - if (isset($stored_value) && ($stored_value === $compare_value)) { - return true; - } - - $dbvalue = $this->toDbValue($value); - - $result = $this->dba->update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true); - - return $result; - } - - /** - * Removes the configured value from the database. - * - * @param string $cat The category of the configuration value - * @param string $key The configuration key to delete - * - * @return bool Operation success - * - * @throws \Exception In case DB calls are invalid - */ - public function delete(string $cat, string $key) - { - if (!$this->isConnected()) { - return false; - } - - return $this->dba->delete('config', ['cat' => $cat, 'k' => $key]); - } -} diff --git a/src/Model/Config/DbaConfig.php b/src/Model/Config/DbaConfig.php deleted file mode 100644 index 4ef96f6c23..0000000000 --- a/src/Model/Config/DbaConfig.php +++ /dev/null @@ -1,105 +0,0 @@ -. - * - */ - -namespace Friendica\Model\Config; - -use Friendica\Database\Database; - -/** - * The DB-based model of (P-)Config values - * Encapsulates db-calls in case of config queries - */ -abstract class DbaConfig -{ - /** @var Database */ - protected $dba; - - /** - * @param Database $dba The database connection of this model - */ - public function __construct(Database $dba) - { - $this->dba = $dba; - } - - /** - * Checks if the model is currently connected - * - * @return bool - */ - public function isConnected() - { - return $this->dba->isConnected(); - } - - /** - * Formats a DB value to a config value - * - null = The db-value isn't set - * - bool = The db-value is either '0' or '1' - * - array = The db-value is a serialized array - * - string = The db-value is a string - * - * Keep in mind that there aren't any numeric/integer config values in the database - * - * @param null|string $value - * - * @return null|array|string - */ - protected function toConfigValue($value) - { - if (!isset($value)) { - return null; - } - - switch (true) { - // manage array value - case preg_match("|^a:[0-9]+:{.*}$|s", $value): - return unserialize($value); - - default: - return $value; - } - } - - /** - * Formats a config value to a DB value (string) - * - * @param mixed $value - * - * @return string - */ - protected function toDbValue($value) - { - // if not set, save an empty string - if (!isset($value)) { - return ''; - } - - switch (true) { - // manage arrays - case is_array($value): - return serialize($value); - - default: - return (string)$value; - } - } -} diff --git a/src/Model/Config/PConfig.php b/src/Model/Config/PConfig.php deleted file mode 100644 index 0aeb0df42b..0000000000 --- a/src/Model/Config/PConfig.php +++ /dev/null @@ -1,154 +0,0 @@ -. - * - */ - -namespace Friendica\Model\Config; - - -/** - * The Config model backend for users, which is using the general DB-model backend for user-configs - */ -class PConfig extends DbaConfig -{ - /** - * Loads all configuration values and returns the loaded category as an array. - * - * @param int $uid The id of the user to load - * @param string|null $cat The category of the configuration values to load - * - * @return array The config array - * - * @throws \Exception In case DB calls are invalid - */ - public function load(int $uid, string $cat = null) - { - $return = []; - - if (empty($cat)) { - $configs = $this->dba->select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]); - } else { - $configs = $this->dba->select('pconfig', ['cat', 'v', 'k'], ['cat' => $cat, 'uid' => $uid]); - } - - while ($config = $this->dba->fetch($configs)) { - $key = $config['k']; - $value = $this->toConfigValue($config['v']); - - // just save it in case it is set - if (isset($value)) { - $return[$config['cat']][$key] = $value; - } - } - $this->dba->close($configs); - - return $return; - } - - /** - * Get a particular user config variable out of the DB with the - * given category name ($cat) and a key ($key). - * - * Note: Boolean variables are defined as 0/1 in the database - * - * @param int $uid The id of the user to load - * @param string $cat The category of the configuration value - * @param string $key The configuration key to query - * - * @return array|string|null Stored value or null if it does not exist - * - * @throws \Exception In case DB calls are invalid - */ - public function get(int $uid, string $cat, string $key) - { - if (!$this->isConnected()) { - return null; - } - - $config = $this->dba->selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]); - if ($this->dba->isResult($config)) { - $value = $this->toConfigValue($config['v']); - - // just return it in case it is set - if (isset($value)) { - return $value; - } - } - - return null; - } - - /** - * Stores a config value ($value) in the category ($cat) under the key ($key) for a - * given user ($uid). - * - * Note: Please do not store booleans - convert to 0/1 integer values! - * - * @param int $uid The id of the user to load - * @param string $cat The category of the configuration value - * @param string $key The configuration key to set - * @param mixed $value The value to store - * - * @return bool Operation success - * - * @throws \Exception In case DB calls are invalid - */ - public function set(int $uid, string $cat, string $key, $value) - { - if (!$this->isConnected()) { - return false; - } - - // We store our setting values in a string variable. - // So we have to do the conversion here so that the compare below works. - // The exception are array values. - $compare_value = (!is_array($value) ? (string)$value : $value); - $stored_value = $this->get($uid, $cat, $key); - - if (isset($stored_value) && ($stored_value === $compare_value)) { - return true; - } - - $dbvalue = $this->toDbValue($value); - - $result = $this->dba->update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true); - - return $result; - } - - /** - * Removes the configured value of the given user. - * - * @param int $uid The id of the user to load - * @param string $cat The category of the configuration value - * @param string $key The configuration key to delete - * - * @return bool Operation success - * - * @throws \Exception In case DB calls are invalid - */ - public function delete(int $uid, string $cat, string $key) - { - if (!$this->isConnected()) { - return false; - } - - return $this->dba->delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]); - } -} diff --git a/src/Module/Admin/Summary.php b/src/Module/Admin/Summary.php index 2d081f4077..5077d3b5db 100644 --- a/src/Module/Admin/Summary.php +++ b/src/Module/Admin/Summary.php @@ -22,18 +22,18 @@ namespace Friendica\Module\Admin; use Friendica\Core\Addon; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\Update; use Friendica\Database\DBA; use Friendica\Database\DBStructure; use Friendica\DI; -use Friendica\Factory\ConfigFactory; +use Friendica\Core\Config\Factory\ConfigFactory; use Friendica\Model\Register; use Friendica\Module\BaseAdmin; use Friendica\Network\HTTPException\InternalServerErrorException; -use Friendica\Util\ConfigFileLoader; +use Friendica\Core\Config\Cache\ConfigFileLoader; use Friendica\Util\DateTimeFormat; class Summary extends BaseAdmin diff --git a/src/Module/Install.php b/src/Module/Install.php index c61f162338..b9ae763b72 100644 --- a/src/Module/Install.php +++ b/src/Module/Install.php @@ -24,7 +24,7 @@ namespace Friendica\Module; use Friendica\App; use Friendica\BaseModule; use Friendica\Core; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Core\Renderer; use Friendica\Core\Theme; use Friendica\DI; diff --git a/src/Util/ConfigFileLoader.php b/src/Util/ConfigFileLoader.php deleted file mode 100644 index aabefc18bb..0000000000 --- a/src/Util/ConfigFileLoader.php +++ /dev/null @@ -1,368 +0,0 @@ -. - * - */ - -namespace Friendica\Util; - -use Exception; -use Friendica\Core\Addon; -use Friendica\Core\Config\Cache; - -/** - * The ConfigFileLoader loads config-files and stores them in a ConfigCache ( @see Cache ) - * - * It is capable of loading the following config files: - * - *.config.php (current) - * - *.ini.php (deprecated) - * - *.htconfig.php (deprecated) - */ -class ConfigFileLoader -{ - /** - * The default name of the user defined ini file - * - * @var string - */ - const CONFIG_INI = 'local'; - - /** - * The default name of the user defined legacy config file - * - * @var string - */ - const CONFIG_HTCONFIG = 'htconfig'; - - /** - * The sample string inside the configs, which shouldn't get loaded - * - * @var string - */ - const SAMPLE_END = '-sample'; - - /** - * @var string - */ - private $baseDir; - /** - * @var string - */ - private $configDir; - /** - * @var string - */ - private $staticDir; - - /** - * @param string $baseDir The base - * @param string $configDir - * @param string $staticDir - */ - public function __construct(string $baseDir, string $configDir, string $staticDir) - { - $this->baseDir = $baseDir; - $this->configDir = $configDir; - $this->staticDir = $staticDir; - } - - /** - * Load the configuration files into an configuration cache - * - * First loads the default value for all the configuration keys, then the legacy configuration files, then the - * expected local.config.php - * - * @param Cache $config The config cache to load to - * @param array $server The $_SERVER array - * @param bool $raw Setup the raw config format - * - * @throws Exception - */ - public function setupCache(Cache $config, array $server = [], bool $raw = false) - { - // Load static config files first, the order is important - $config->load($this->loadStaticConfig('defaults'), Cache::SOURCE_FILE); - $config->load($this->loadStaticConfig('settings'), Cache::SOURCE_FILE); - - // try to load the legacy config first - $config->load($this->loadLegacyConfig('htpreconfig'), Cache::SOURCE_FILE); - $config->load($this->loadLegacyConfig('htconfig'), Cache::SOURCE_FILE); - - // Now load every other config you find inside the 'config/' directory - $this->loadCoreConfig($config); - - $config->load($this->loadEnvConfig($server), Cache::SOURCE_ENV); - - // In case of install mode, add the found basepath (because there isn't a basepath set yet - if (!$raw && empty($config->get('system', 'basepath'))) { - // Setting at least the basepath we know - $config->set('system', 'basepath', $this->baseDir, Cache::SOURCE_FILE); - } - } - - /** - * Tries to load the static core-configuration and returns the config array. - * - * @param string $name The name of the configuration - * - * @return array The config array (empty if no config found) - * - * @throws Exception if the configuration file isn't readable - */ - private function loadStaticConfig($name) - { - $configName = $this->staticDir . DIRECTORY_SEPARATOR . $name . '.config.php'; - $iniName = $this->staticDir . DIRECTORY_SEPARATOR . $name . '.ini.php'; - - if (file_exists($configName)) { - return $this->loadConfigFile($configName); - } elseif (file_exists($iniName)) { - return $this->loadINIConfigFile($iniName); - } else { - return []; - } - } - - /** - * Tries to load the specified core-configuration into the config cache. - * - * @param Cache $config The Config cache - * - * @return array The config array (empty if no config found) - * - * @throws Exception if the configuration file isn't readable - */ - private function loadCoreConfig(Cache $config) - { - // try to load legacy ini-files first - foreach ($this->getConfigFiles(true) as $configFile) { - $config->load($this->loadINIConfigFile($configFile), Cache::SOURCE_FILE); - } - - // try to load supported config at last to overwrite it - foreach ($this->getConfigFiles() as $configFile) { - $config->load($this->loadConfigFile($configFile), Cache::SOURCE_FILE); - } - - return []; - } - - /** - * Tries to load the specified addon-configuration and returns the config array. - * - * @param string $name The name of the configuration - * - * @return array The config array (empty if no config found) - * - * @throws Exception if the configuration file isn't readable - */ - public function loadAddonConfig($name) - { - $filepath = $this->baseDir . DIRECTORY_SEPARATOR . // /var/www/html/ - Addon::DIRECTORY . DIRECTORY_SEPARATOR . // addon/ - $name . DIRECTORY_SEPARATOR . // openstreetmap/ - 'config'. DIRECTORY_SEPARATOR . // config/ - $name . ".config.php"; // openstreetmap.config.php - - if (file_exists($filepath)) { - return $this->loadConfigFile($filepath); - } else { - return []; - } - } - - /** - * Tries to load environment specific variables, based on the `env.config.php` mapping table - * - * @param array $server The $_SERVER variable - * - * @return array The config array (empty if no config was found) - * - * @throws Exception if the configuration file isn't readable - */ - public function loadEnvConfig(array $server) - { - $filepath = $this->staticDir . DIRECTORY_SEPARATOR . // /var/www/html/static/ - "env.config.php"; // env.config.php - - if (!file_exists($filepath)) { - return []; - } - - $envConfig = $this->loadConfigFile($filepath); - - $return = []; - - foreach ($envConfig as $envKey => $configStructure) { - if (isset($server[$envKey])) { - $return[$configStructure[0]][$configStructure[1]] = $server[$envKey]; - } - } - - return $return; - } - - /** - * Get the config files of the config-directory - * - * @param bool $ini True, if scan for ini-files instead of config files - * - * @return array - */ - private function getConfigFiles(bool $ini = false) - { - $files = scandir($this->configDir); - $found = array(); - - $filePattern = ($ini ? '*.ini.php' : '*.config.php'); - - // Don't load sample files - $sampleEnd = self::SAMPLE_END . ($ini ? '.ini.php' : '.config.php'); - - foreach ($files as $filename) { - if (fnmatch($filePattern, $filename) && substr_compare($filename, $sampleEnd, -strlen($sampleEnd))) { - $found[] = $this->configDir . '/' . $filename; - } - } - - return $found; - } - - /** - * Tries to load the legacy config files (.htconfig.php, .htpreconfig.php) and returns the config array. - * - * @param string $name The name of the config file (default is empty, which means .htconfig.php) - * - * @return array The configuration array (empty if no config found) - * - * @deprecated since version 2018.09 - */ - private function loadLegacyConfig($name = '') - { - $name = !empty($name) ? $name : self::CONFIG_HTCONFIG; - $fullName = $this->baseDir . DIRECTORY_SEPARATOR . '.' . $name . '.php'; - - $config = []; - if (file_exists($fullName)) { - $a = new \stdClass(); - $a->config = []; - include $fullName; - - $htConfigCategories = array_keys($a->config); - - // map the legacy configuration structure to the current structure - foreach ($htConfigCategories as $htConfigCategory) { - if (is_array($a->config[$htConfigCategory])) { - $keys = array_keys($a->config[$htConfigCategory]); - - foreach ($keys as $key) { - $config[$htConfigCategory][$key] = $a->config[$htConfigCategory][$key]; - } - } else { - $config['config'][$htConfigCategory] = $a->config[$htConfigCategory]; - } - } - - unset($a); - - if (isset($db_host)) { - $config['database']['hostname'] = $db_host; - unset($db_host); - } - if (isset($db_user)) { - $config['database']['username'] = $db_user; - unset($db_user); - } - if (isset($db_pass)) { - $config['database']['password'] = $db_pass; - unset($db_pass); - } - if (isset($db_data)) { - $config['database']['database'] = $db_data; - unset($db_data); - } - if (isset($config['system']['db_charset'])) { - $config['database']['charset'] = $config['system']['db_charset']; - } - if (isset($pidfile)) { - $config['system']['pidfile'] = $pidfile; - unset($pidfile); - } - if (isset($default_timezone)) { - $config['system']['default_timezone'] = $default_timezone; - unset($default_timezone); - } - if (isset($lang)) { - $config['system']['language'] = $lang; - unset($lang); - } - } - - return $config; - } - - /** - * Tries to load the specified legacy configuration file and returns the config array. - * - * @param string $filepath - * - * @return array The configuration array - * @throws Exception - * @deprecated since version 2018.12 - */ - private function loadINIConfigFile($filepath) - { - $contents = include($filepath); - - $config = parse_ini_string($contents, true, INI_SCANNER_TYPED); - - if ($config === false) { - throw new Exception('Error parsing INI config file ' . $filepath); - } - - return $config; - } - - /** - * Tries to load the specified configuration file and returns the config array. - * - * The config format is PHP array and the template for configuration files is the following: - * - * [ - * 'key' => 'value', - * ], - * ]; - * - * @param string $filepath The filepath of the - * - * @return array The config array0 - * - * @throws Exception if the config cannot get loaded. - */ - private function loadConfigFile($filepath) - { - $config = include($filepath); - - if (!is_array($config)) { - throw new Exception('Error loading config file ' . $filepath); - } - - return $config; - } -} diff --git a/src/Util/Profiler.php b/src/Util/Profiler.php index fb499d8156..0ff338353e 100644 --- a/src/Util/Profiler.php +++ b/src/Util/Profiler.php @@ -21,7 +21,7 @@ namespace Friendica\Util; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Core\Config\IConfig; use Friendica\Core\System; use Psr\Container\ContainerExceptionInterface; @@ -78,7 +78,7 @@ class Profiler implements ContainerInterface } /** - * @param Cache $configCache The configuration cache + * @param \Friendica\Core\Config\Cache\Cache $configCache The configuration cache */ public function __construct(Cache $configCache) { diff --git a/static/dependencies.config.php b/static/dependencies.config.php index 39aae97fd1..fe063c0463 100644 --- a/static/dependencies.config.php +++ b/static/dependencies.config.php @@ -37,6 +37,7 @@ use Dice\Dice; use Friendica\App; use Friendica\Core\Cache; use Friendica\Core\Config; +use Friendica\Core\PConfig; use Friendica\Core\L10n; use Friendica\Core\Lock\ILock; use Friendica\Core\Process; @@ -73,8 +74,8 @@ return [ $_SERVER ] ], - Util\ConfigFileLoader::class => [ - 'instanceOf' => Factory\ConfigFactory::class, + Config\Cache\ConfigFileLoader::class => [ + 'instanceOf' => Config\Factory\ConfigFactory::class, 'call' => [ ['createConfigFileLoader', [ [Dice::INSTANCE => '$basepath'], @@ -82,8 +83,8 @@ return [ ], Dice::CHAIN_CALL], ], ], - Config\Cache::class => [ - 'instanceOf' => Factory\ConfigFactory::class, + Config\Cache\Cache::class => [ + 'instanceOf' => Config\Factory\ConfigFactory::class, 'call' => [ ['createCache', [$_SERVER], Dice::CHAIN_CALL], ], @@ -95,15 +96,15 @@ return [ ], ], Config\IConfig::class => [ - 'instanceOf' => Factory\ConfigFactory::class, + 'instanceOf' => Config\Factory\ConfigFactory::class, 'call' => [ - ['createConfig', [], Dice::CHAIN_CALL], + ['create', [], Dice::CHAIN_CALL], ], ], \Friendica\Core\PConfig\IPConfig::class => [ - 'instanceOf' => Factory\ConfigFactory::class, + 'instanceOf' => PConfig\Factory\PConfigFactory::class, 'call' => [ - ['createPConfig', [], Dice::CHAIN_CALL], + ['create', [], Dice::CHAIN_CALL], ] ], Database::class => [ diff --git a/tests/FixtureTest.php b/tests/FixtureTest.php index f30b50878b..fdeda1febc 100644 --- a/tests/FixtureTest.php +++ b/tests/FixtureTest.php @@ -6,7 +6,7 @@ namespace Friendica\Test; use Dice\Dice; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Core\Config\IConfig; use Friendica\Core\Session; use Friendica\Core\Session\ISession; diff --git a/tests/Util/AppMockTrait.php b/tests/Util/AppMockTrait.php index 4266a4a023..cca9bd37e8 100644 --- a/tests/Util/AppMockTrait.php +++ b/tests/Util/AppMockTrait.php @@ -74,19 +74,19 @@ trait AppMockTrait $this->dice = \Mockery::mock(Dice::class)->makePartial(); $this->dice = $this->dice->addRules(include __DIR__ . '/../../static/dependencies.config.php'); - $this->configMock = \Mockery::mock(Config\Cache::class); + $this->configMock = \Mockery::mock(Config\Cache\Cache::class); $this->dice->shouldReceive('create') - ->with(Config\Cache::class) + ->with(Config\Cache\Cache::class) ->andReturn($this->configMock); $this->mode = \Mockery::mock(App\Mode::class); $this->dice->shouldReceive('create') ->with(App\Mode::class) ->andReturn($this->mode); - $configModel= \Mockery::mock(\Friendica\Model\Config\Config::class); + $configModel= \Mockery::mock(Config\Model\Config::class); // Disable the adapter $configModel->shouldReceive('isConnected')->andReturn(false); - $config = new Config\JitConfig($this->configMock, $configModel); + $config = new Config\Type\JitConfig($this->configMock, $configModel); $this->dice->shouldReceive('create') ->with(Config\IConfig::class) ->andReturn($config); diff --git a/tests/functional/DependencyCheckTest.php b/tests/functional/DependencyCheckTest.php index a7b45ccebe..3d207d07d1 100644 --- a/tests/functional/DependencyCheckTest.php +++ b/tests/functional/DependencyCheckTest.php @@ -25,13 +25,13 @@ use Dice\Dice; use Friendica\App; use Friendica\Core\Cache\ICache; use Friendica\Core\Cache\IMemoryCache; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Core\Config\IConfig; use Friendica\Core\Lock\ILock; use Friendica\Database\Database; use Friendica\Test\Util\VFSTrait; use Friendica\Util\BasePath; -use Friendica\Util\ConfigFileLoader; +use Friendica\Core\Config\Cache\ConfigFileLoader; use Friendica\Util\Profiler; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; diff --git a/tests/src/App/ModeTest.php b/tests/src/App/ModeTest.php index 36ca6b21d6..c3a5c5e72b 100644 --- a/tests/src/App/ModeTest.php +++ b/tests/src/App/ModeTest.php @@ -24,7 +24,7 @@ namespace Friendica\Test\src\App; use Detection\MobileDetect; use Friendica\App\Mode; use Friendica\App\Module; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Database\Database; use Friendica\Test\MockedTest; use Friendica\Test\Util\VFSTrait; diff --git a/tests/src/Console/AutomaticInstallationConsoleTest.php b/tests/src/Console/AutomaticInstallationConsoleTest.php index 01a57b57e9..f11d383658 100644 --- a/tests/src/Console/AutomaticInstallationConsoleTest.php +++ b/tests/src/Console/AutomaticInstallationConsoleTest.php @@ -24,7 +24,7 @@ namespace Friendica\Test\src\Console; use Dice\Dice; use Friendica\App; use Friendica\Console\AutomaticInstallation; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Core\Installer; use Friendica\Core\L10n; use Friendica\Core\Logger; @@ -53,7 +53,7 @@ class AutomaticInstallationConsoleTest extends ConsoleTest private $assertFileDb; /** - * @var Cache The configuration cache to check after each test + * @var \Friendica\Core\Config\Cache\Cache The configuration cache to check after each test */ private $configCache; diff --git a/tests/src/Core/Cache/DatabaseCacheTest.php b/tests/src/Core/Cache/DatabaseCacheTest.php index 8d404b3552..55011f87cf 100644 --- a/tests/src/Core/Cache/DatabaseCacheTest.php +++ b/tests/src/Core/Cache/DatabaseCacheTest.php @@ -22,11 +22,10 @@ namespace Friendica\Test\src\Core\Cache; use Friendica\Core\Cache; -use Friendica\Factory\ConfigFactory; +use Friendica\Core\Config\Factory\ConfigFactory; use Friendica\Test\DatabaseTestTrait; use Friendica\Test\Util\Database\StaticDatabase; use Friendica\Test\Util\VFSTrait; -use Friendica\Util\ConfigFileLoader; use Friendica\Util\Profiler; use Mockery; use Psr\Log\NullLogger; diff --git a/tests/src/Core/Config/Cache/CacheTest.php b/tests/src/Core/Config/Cache/CacheTest.php new file mode 100644 index 0000000000..530b5b4826 --- /dev/null +++ b/tests/src/Core/Config/Cache/CacheTest.php @@ -0,0 +1,345 @@ +. + * + */ + +namespace Friendica\Test\src\Core\Config\Cache; + +use Friendica\Core\Config\Cache; +use Friendica\Test\MockedTest; +use ParagonIE\HiddenString\HiddenString; +use stdClass; + +class CacheTest extends MockedTest +{ + public function dataTests() + { + return [ + 'normal' => [ + 'data' => [ + 'system' => [ + 'test' => 'it', + 'boolTrue' => true, + 'boolFalse' => false, + 'int' => 235, + 'dec' => 2.456, + 'array' => ['1', 2, '3', true, false], + ], + 'config' => [ + 'a' => 'value', + ], + ] + ] + ]; + } + + private function assertConfigValues($data, Cache\Cache $configCache) + { + foreach ($data as $cat => $values) { + foreach ($values as $key => $value) { + self::assertEquals($data[$cat][$key], $configCache->get($cat, $key)); + } + } + } + + /** + * Test the loadConfigArray() method without override + * @dataProvider dataTests + */ + public function testLoadConfigArray($data) + { + $configCache = new Cache\Cache(); + $configCache->load($data); + + self::assertConfigValues($data, $configCache); + } + + /** + * Test the loadConfigArray() method with overrides + * @dataProvider dataTests + */ + public function testLoadConfigArrayOverride($data) + { + $override = [ + 'system' => [ + 'test' => 'not', + 'boolTrue' => false, + ] + ]; + + $configCache = new Cache\Cache(); + $configCache->load($data, Cache\Cache::SOURCE_DB); + // doesn't override - Low Priority due Config file + $configCache->load($override, Cache\Cache::SOURCE_FILE); + + self::assertConfigValues($data, $configCache); + + // override the value - High Prio due Server Env + $configCache->load($override, Cache\Cache::SOURCE_ENV); + + self::assertEquals($override['system']['test'], $configCache->get('system', 'test')); + self::assertEquals($override['system']['boolTrue'], $configCache->get('system', 'boolTrue')); + + // Don't overwrite server ENV variables - even in load mode + $configCache->load($data, Cache\Cache::SOURCE_DB); + + self::assertEquals($override['system']['test'], $configCache->get('system', 'test')); + self::assertEquals($override['system']['boolTrue'], $configCache->get('system', 'boolTrue')); + + // Overwrite ENV variables with ENV variables + $configCache->load($data, Cache\Cache::SOURCE_ENV); + + self::assertConfigValues($data, $configCache); + self::assertNotEquals($override['system']['test'], $configCache->get('system', 'test')); + self::assertNotEquals($override['system']['boolTrue'], $configCache->get('system', 'boolTrue')); + } + + /** + * Test the loadConfigArray() method with wrong/empty datasets + */ + public function testLoadConfigArrayWrong() + { + $configCache = new Cache\Cache(); + + // empty dataset + $configCache->load([]); + self::assertEmpty($configCache->getAll()); + + // wrong dataset + $configCache->load(['system' => 'not_array']); + self::assertEmpty($configCache->getAll()); + + // incomplete dataset (key is integer ID of the array) + $configCache->load(['system' => ['value']]); + self::assertEquals('value', $configCache->get('system', 0)); + } + + /** + * Test the getAll() method + * @dataProvider dataTests + */ + public function testGetAll($data) + { + $configCache = new Cache\Cache(); + $configCache->load($data); + + $all = $configCache->getAll(); + + self::assertContains($data['system'], $all); + self::assertContains($data['config'], $all); + } + + /** + * Test the set() and get() method + * @dataProvider dataTests + */ + public function testSetGet($data) + { + $configCache = new Cache\Cache(); + + foreach ($data as $cat => $values) { + foreach ($values as $key => $value) { + $configCache->set($cat, $key, $value); + } + } + + self::assertConfigValues($data, $configCache); + } + + /** + * Test the get() method without a value + */ + public function testGetEmpty() + { + $configCache = new Cache\Cache(); + + self::assertNull($configCache->get('something', 'value')); + } + + /** + * Test the get() method with a category + */ + public function testGetCat() + { + $configCache = new Cache\Cache([ + 'system' => [ + 'key1' => 'value1', + 'key2' => 'value2', + ], + 'config' => [ + 'key3' => 'value3', + ], + ]); + + self::assertEquals([ + 'key1' => 'value1', + 'key2' => 'value2', + ], $configCache->get('system')); + + // explicit null as key + self::assertEquals([ + 'key1' => 'value1', + 'key2' => 'value2', + ], $configCache->get('system', null)); + } + + /** + * Test the delete() method + * @dataProvider dataTests + */ + public function testDelete($data) + { + $configCache = new Cache\Cache($data); + + foreach ($data as $cat => $values) { + foreach ($values as $key => $value) { + $configCache->delete($cat, $key); + } + } + + self::assertEmpty($configCache->getAll()); + } + + /** + * Test the keyDiff() method with result + * @dataProvider dataTests + */ + public function testKeyDiffWithResult($data) + { + $configCache = new Cache\Cache($data); + + $diffConfig = [ + 'fakeCat' => [ + 'fakeKey' => 'value', + ] + ]; + + self::assertEquals($diffConfig, $configCache->keyDiff($diffConfig)); + } + + /** + * Test the keyDiff() method without result + * @dataProvider dataTests + */ + public function testKeyDiffWithoutResult($data) + { + $configCache = new Cache\Cache($data); + + $diffConfig = $configCache->getAll(); + + self::assertEmpty($configCache->keyDiff($diffConfig)); + } + + /** + * Test the default hiding of passwords inside the cache + */ + public function testPasswordHide() + { + $configCache = new Cache\Cache([ + 'database' => [ + 'password' => 'supersecure', + 'username' => 'notsecured', + ], + ]); + + self::assertEquals('supersecure', $configCache->get('database', 'password')); + self::assertNotEquals('supersecure', print_r($configCache->get('database', 'password'), true)); + self::assertEquals('notsecured', print_r($configCache->get('database', 'username'), true)); + } + + /** + * Test disabling the hiding of passwords inside the cache + */ + public function testPasswordShow() + { + $configCache = new Cache\Cache([ + 'database' => [ + 'password' => 'supersecure', + 'username' => 'notsecured', + ], + ], false); + + self::assertEquals('supersecure', $configCache->get('database', 'password')); + self::assertEquals('supersecure', print_r($configCache->get('database', 'password'), true)); + self::assertEquals('notsecured', print_r($configCache->get('database', 'username'), true)); + } + + /** + * Test a empty password + */ + public function testEmptyPassword() + { + $configCache = new Cache\Cache([ + 'database' => [ + 'password' => '', + 'username' => '', + ] + ]); + + self::assertNotEmpty($configCache->get('database', 'password')); + self::assertInstanceOf(HiddenString::class, $configCache->get('database', 'password')); + self::assertEmpty($configCache->get('database', 'username')); + } + + public function testWrongTypePassword() + { + $configCache = new Cache\Cache([ + 'database' => [ + 'password' => new stdClass(), + 'username' => '', + ] + ]); + + self::assertNotEmpty($configCache->get('database', 'password')); + self::assertEmpty($configCache->get('database', 'username')); + + $configCache = new Cache\Cache([ + 'database' => [ + 'password' => 23, + 'username' => '', + ] + ]); + + self::assertEquals(23, $configCache->get('database', 'password')); + self::assertEmpty($configCache->get('database', 'username')); + } + + /** + * Test the set() method with overrides + * @dataProvider dataTests + */ + public function testSetOverrides($data) + { + + $configCache = new Cache\Cache(); + $configCache->load($data, Cache\Cache::SOURCE_DB); + + // test with wrong override + self::assertFalse($configCache->set('system', 'test', '1234567', Cache\Cache::SOURCE_FILE)); + self::assertEquals($data['system']['test'], $configCache->get('system', 'test')); + + // test with override (equal) + self::assertTrue($configCache->set('system', 'test', '8910', Cache\Cache::SOURCE_DB)); + self::assertEquals('8910', $configCache->get('system', 'test')); + + // test with override (over) + self::assertTrue($configCache->set('system', 'test', '111213', Cache\Cache::SOURCE_ENV)); + self::assertEquals('111213', $configCache->get('system', 'test')); + } +} diff --git a/tests/src/Core/Config/Cache/ConfigFileLoaderTest.php b/tests/src/Core/Config/Cache/ConfigFileLoaderTest.php new file mode 100644 index 0000000000..ed5cfa1ef6 --- /dev/null +++ b/tests/src/Core/Config/Cache/ConfigFileLoaderTest.php @@ -0,0 +1,389 @@ +. + * + */ + +namespace Friendica\Test\src\Core\Config\Cache; + +use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Factory\ConfigFactory; +use Friendica\Test\MockedTest; +use Friendica\Test\Util\VFSTrait; +use Friendica\Core\Config\Cache\ConfigFileLoader; +use org\bovigo\vfs\vfsStream; + +class ConfigFileLoaderTest extends MockedTest +{ + use VFSTrait; + + protected function setUp(): void + { + parent::setUp(); + + $this->setUpVfsDir(); + } + + /** + * Test the loadConfigFiles() method with default values + */ + public function testLoadConfigFiles() + { + $this->delConfigFile('local.config.php'); + + $configFileLoader = new ConfigFileLoader( + $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR + ); + $configCache = new Cache\Cache(); + + $configFileLoader->setupCache($configCache); + + self::assertEquals($this->root->url(), $configCache->get('system', 'basepath')); + } + + /** + * Test the loadConfigFiles() method with a wrong local.config.php + * + */ + public function testLoadConfigWrong() + { + $this->expectExceptionMessageMatches("/Error loading config file \w+/"); + $this->expectException(\Exception::class); + $this->delConfigFile('local.config.php'); + + vfsStream::newFile('local.config.php') + ->at($this->root->getChild('config')) + ->setContent('root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR + ); + $configCache = new Cache\Cache(); + + $configFileLoader->setupCache($configCache); + } + + /** + * Test the loadConfigFiles() method with a local.config.php file + */ + public function testLoadConfigFilesLocal() + { + $this->delConfigFile('local.config.php'); + + $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + 'datasets' . DIRECTORY_SEPARATOR . + 'config' . DIRECTORY_SEPARATOR . + 'A.config.php'; + + vfsStream::newFile('local.config.php') + ->at($this->root->getChild('config')) + ->setContent(file_get_contents($file)); + + $configFileLoader = new ConfigFileLoader( + $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR + ); + $configCache = new Cache\Cache(); + + $configFileLoader->setupCache($configCache); + + self::assertEquals('testhost', $configCache->get('database', 'hostname')); + self::assertEquals('testuser', $configCache->get('database', 'username')); + self::assertEquals('testpw', $configCache->get('database', 'password')); + self::assertEquals('testdb', $configCache->get('database', 'database')); + + self::assertEquals('admin@test.it', $configCache->get('config', 'admin_email')); + self::assertEquals('Friendica Social Network', $configCache->get('config', 'sitename')); + } + + /** + * Test the loadConfigFile() method with a local.ini.php file + */ + public function testLoadConfigFilesINI() + { + $this->delConfigFile('local.config.php'); + + $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + 'datasets' . DIRECTORY_SEPARATOR . + 'config' . DIRECTORY_SEPARATOR . + 'A.ini.php'; + + vfsStream::newFile('local.ini.php') + ->at($this->root->getChild('config')) + ->setContent(file_get_contents($file)); + + $configFileLoader = new ConfigFileLoader( + $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR + ); + $configCache = new Cache\Cache(); + + $configFileLoader->setupCache($configCache); + + self::assertEquals('testhost', $configCache->get('database', 'hostname')); + self::assertEquals('testuser', $configCache->get('database', 'username')); + self::assertEquals('testpw', $configCache->get('database', 'password')); + self::assertEquals('testdb', $configCache->get('database', 'database')); + + self::assertEquals('admin@test.it', $configCache->get('config', 'admin_email')); + } + + /** + * Test the loadConfigFile() method with a .htconfig.php file + */ + public function testLoadConfigFilesHtconfig() + { + $this->delConfigFile('local.config.php'); + + $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + 'datasets' . DIRECTORY_SEPARATOR . + 'config' . DIRECTORY_SEPARATOR . + '.htconfig.php'; + + vfsStream::newFile('.htconfig.php') + ->at($this->root) + ->setContent(file_get_contents($file)); + + $configFileLoader = new ConfigFileLoader( + $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR + ); + $configCache = new Cache\Cache(); + + $configFileLoader->setupCache($configCache); + + self::assertEquals('testhost', $configCache->get('database', 'hostname')); + self::assertEquals('testuser', $configCache->get('database', 'username')); + self::assertEquals('testpw', $configCache->get('database', 'password')); + self::assertEquals('testdb', $configCache->get('database', 'database')); + self::assertEquals('anotherCharset', $configCache->get('database', 'charset')); + + self::assertEquals('/var/run/friendica.pid', $configCache->get('system', 'pidfile')); + self::assertEquals('Europe/Berlin', $configCache->get('system', 'default_timezone')); + self::assertEquals('fr', $configCache->get('system', 'language')); + + self::assertEquals('admin@test.it', $configCache->get('config', 'admin_email')); + self::assertEquals('Friendly admin', $configCache->get('config', 'admin_nickname')); + + self::assertEquals('/another/php', $configCache->get('config', 'php_path')); + self::assertEquals('999', $configCache->get('config', 'max_import_size')); + self::assertEquals('666', $configCache->get('system', 'maximagesize')); + + self::assertEquals('frio,quattro,vier,duepuntozero', $configCache->get('system', 'allowed_themes')); + self::assertEquals('1', $configCache->get('system', 'no_regfullname')); + } + + public function testLoadAddonConfig() + { + $structure = [ + 'addon' => [ + 'test' => [ + 'config' => [], + ], + ], + ]; + + vfsStream::create($structure, $this->root); + + $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + 'datasets' . DIRECTORY_SEPARATOR . + 'config' . DIRECTORY_SEPARATOR . + 'A.config.php'; + + vfsStream::newFile('test.config.php') + ->at($this->root->getChild('addon')->getChild('test')->getChild('config')) + ->setContent(file_get_contents($file)); + + $configFileLoader = new ConfigFileLoader( + $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR + ); + + $conf = $configFileLoader->loadAddonConfig('test'); + + self::assertEquals('testhost', $conf['database']['hostname']); + self::assertEquals('testuser', $conf['database']['username']); + self::assertEquals('testpw', $conf['database']['password']); + self::assertEquals('testdb', $conf['database']['database']); + + self::assertEquals('admin@test.it', $conf['config']['admin_email']); + } + + /** + * test loading multiple config files - the last config should work + */ + public function testLoadMultipleConfigs() + { + $this->delConfigFile('local.config.php'); + + $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + 'datasets' . DIRECTORY_SEPARATOR . + 'config' . DIRECTORY_SEPARATOR; + + vfsStream::newFile('A.config.php') + ->at($this->root->getChild('config')) + ->setContent(file_get_contents($fileDir . 'A.config.php')); + vfsStream::newFile('B.config.php') + ->at($this->root->getChild('config')) + ->setContent(file_get_contents($fileDir . 'B.config.php')); + + $configFileLoader = new ConfigFileLoader( + $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR + ); + $configCache = new Cache\Cache(); + + $configFileLoader->setupCache($configCache); + + self::assertEquals('admin@overwritten.local', $configCache->get('config', 'admin_email')); + self::assertEquals('newValue', $configCache->get('system', 'newKey')); + } + + /** + * test loading multiple config files - the last config should work (INI-version) + */ + public function testLoadMultipleInis() + { + $this->delConfigFile('local.config.php'); + + $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + 'datasets' . DIRECTORY_SEPARATOR . + 'config' . DIRECTORY_SEPARATOR; + + vfsStream::newFile('A.ini.php') + ->at($this->root->getChild('config')) + ->setContent(file_get_contents($fileDir . 'A.ini.php')); + vfsStream::newFile('B.ini.php') + ->at($this->root->getChild('config')) + ->setContent(file_get_contents($fileDir . 'B.ini.php')); + + $configFileLoader = new ConfigFileLoader( + $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR + ); + $configCache = new Cache\Cache(); + + $configFileLoader->setupCache($configCache); + + self::assertEquals('admin@overwritten.local', $configCache->get('config', 'admin_email')); + self::assertEquals('newValue', $configCache->get('system', 'newKey')); + } + + /** + * Test that sample-files (e.g. local-sample.config.php) is never loaded + */ + public function testNotLoadingSamples() + { + $this->delConfigFile('local.config.php'); + + $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + 'datasets' . DIRECTORY_SEPARATOR . + 'config' . DIRECTORY_SEPARATOR; + + vfsStream::newFile('A.ini.php') + ->at($this->root->getChild('config')) + ->setContent(file_get_contents($fileDir . 'A.ini.php')); + vfsStream::newFile('B-sample.ini.php') + ->at($this->root->getChild('config')) + ->setContent(file_get_contents($fileDir . 'B.ini.php')); + + $configFileLoader = new ConfigFileLoader( + $this->root->url(), + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, + $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR + ); + $configCache = new Cache\Cache(); + + $configFileLoader->setupCache($configCache); + + self::assertEquals('admin@test.it', $configCache->get('config', 'admin_email')); + self::assertEmpty($configCache->get('system', 'NewKey')); + } + + /** + * Test that using a wrong configuration directory leads to the "normal" config path + */ + public function testWrongEnvDir() + { + $this->delConfigFile('local.config.php'); + + $configFileLoader = (new ConfigFactory())->createConfigFileLoader($this->root->url(), ['FRIENDICA_CONFIG_DIR' => '/a/wrong/dir/']); + $configCache = new Cache\Cache(); + + $configFileLoader->setupCache($configCache); + + self::assertEquals($this->root->url(), $configCache->get('system', 'basepath')); + } + + /** + * Test that a different location of the configuration directory produces the expected output + */ + public function testRightEnvDir() + { + $this->delConfigFile('local.config.php'); + + $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . + 'datasets' . DIRECTORY_SEPARATOR . + 'config' . DIRECTORY_SEPARATOR; + + vfsStream::newFile('B.config.php') + ->at($this->root->getChild('config2')) + ->setContent(file_get_contents($fileDir . 'B.config.php')); + + $configFileLoader = (new ConfigFactory())->createConfigFileLoader($this->root->url(), ['FRIENDICA_CONFIG_DIR' => $this->root->getChild('config2')->url()]); + $configCache = new Cache\Cache(); + + $configFileLoader->setupCache($configCache); + + self::assertEquals('newValue', $configCache->get('system', 'newKey')); + } +} diff --git a/tests/src/Core/Config/CacheTest.php b/tests/src/Core/Config/CacheTest.php deleted file mode 100644 index 79cca7c123..0000000000 --- a/tests/src/Core/Config/CacheTest.php +++ /dev/null @@ -1,345 +0,0 @@ -. - * - */ - -namespace Friendica\Test\src\Core\Config; - -use Friendica\Core\Config\Cache; -use Friendica\Test\MockedTest; -use ParagonIE\HiddenString\HiddenString; -use stdClass; - -class CacheTest extends MockedTest -{ - public function dataTests() - { - return [ - 'normal' => [ - 'data' => [ - 'system' => [ - 'test' => 'it', - 'boolTrue' => true, - 'boolFalse' => false, - 'int' => 235, - 'dec' => 2.456, - 'array' => ['1', 2, '3', true, false], - ], - 'config' => [ - 'a' => 'value', - ], - ] - ] - ]; - } - - private function assertConfigValues($data, Cache $configCache) - { - foreach ($data as $cat => $values) { - foreach ($values as $key => $value) { - self::assertEquals($data[$cat][$key], $configCache->get($cat, $key)); - } - } - } - - /** - * Test the loadConfigArray() method without override - * @dataProvider dataTests - */ - public function testLoadConfigArray($data) - { - $configCache = new Cache(); - $configCache->load($data); - - self::assertConfigValues($data, $configCache); - } - - /** - * Test the loadConfigArray() method with overrides - * @dataProvider dataTests - */ - public function testLoadConfigArrayOverride($data) - { - $override = [ - 'system' => [ - 'test' => 'not', - 'boolTrue' => false, - ] - ]; - - $configCache = new Cache(); - $configCache->load($data, Cache::SOURCE_DB); - // doesn't override - Low Priority due Config file - $configCache->load($override, Cache::SOURCE_FILE); - - self::assertConfigValues($data, $configCache); - - // override the value - High Prio due Server Env - $configCache->load($override, Cache::SOURCE_ENV); - - self::assertEquals($override['system']['test'], $configCache->get('system', 'test')); - self::assertEquals($override['system']['boolTrue'], $configCache->get('system', 'boolTrue')); - - // Don't overwrite server ENV variables - even in load mode - $configCache->load($data, Cache::SOURCE_DB); - - self::assertEquals($override['system']['test'], $configCache->get('system', 'test')); - self::assertEquals($override['system']['boolTrue'], $configCache->get('system', 'boolTrue')); - - // Overwrite ENV variables with ENV variables - $configCache->load($data, Cache::SOURCE_ENV); - - self::assertConfigValues($data, $configCache); - self::assertNotEquals($override['system']['test'], $configCache->get('system', 'test')); - self::assertNotEquals($override['system']['boolTrue'], $configCache->get('system', 'boolTrue')); - } - - /** - * Test the loadConfigArray() method with wrong/empty datasets - */ - public function testLoadConfigArrayWrong() - { - $configCache = new Cache(); - - // empty dataset - $configCache->load([]); - self::assertEmpty($configCache->getAll()); - - // wrong dataset - $configCache->load(['system' => 'not_array']); - self::assertEmpty($configCache->getAll()); - - // incomplete dataset (key is integer ID of the array) - $configCache->load(['system' => ['value']]); - self::assertEquals('value', $configCache->get('system', 0)); - } - - /** - * Test the getAll() method - * @dataProvider dataTests - */ - public function testGetAll($data) - { - $configCache = new Cache(); - $configCache->load($data); - - $all = $configCache->getAll(); - - self::assertContains($data['system'], $all); - self::assertContains($data['config'], $all); - } - - /** - * Test the set() and get() method - * @dataProvider dataTests - */ - public function testSetGet($data) - { - $configCache = new Cache(); - - foreach ($data as $cat => $values) { - foreach ($values as $key => $value) { - $configCache->set($cat, $key, $value); - } - } - - self::assertConfigValues($data, $configCache); - } - - /** - * Test the get() method without a value - */ - public function testGetEmpty() - { - $configCache = new Cache(); - - self::assertNull($configCache->get('something', 'value')); - } - - /** - * Test the get() method with a category - */ - public function testGetCat() - { - $configCache = new Cache([ - 'system' => [ - 'key1' => 'value1', - 'key2' => 'value2', - ], - 'config' => [ - 'key3' => 'value3', - ], - ]); - - self::assertEquals([ - 'key1' => 'value1', - 'key2' => 'value2', - ], $configCache->get('system')); - - // explicit null as key - self::assertEquals([ - 'key1' => 'value1', - 'key2' => 'value2', - ], $configCache->get('system', null)); - } - - /** - * Test the delete() method - * @dataProvider dataTests - */ - public function testDelete($data) - { - $configCache = new Cache($data); - - foreach ($data as $cat => $values) { - foreach ($values as $key => $value) { - $configCache->delete($cat, $key); - } - } - - self::assertEmpty($configCache->getAll()); - } - - /** - * Test the keyDiff() method with result - * @dataProvider dataTests - */ - public function testKeyDiffWithResult($data) - { - $configCache = new Cache($data); - - $diffConfig = [ - 'fakeCat' => [ - 'fakeKey' => 'value', - ] - ]; - - self::assertEquals($diffConfig, $configCache->keyDiff($diffConfig)); - } - - /** - * Test the keyDiff() method without result - * @dataProvider dataTests - */ - public function testKeyDiffWithoutResult($data) - { - $configCache = new Cache($data); - - $diffConfig = $configCache->getAll(); - - self::assertEmpty($configCache->keyDiff($diffConfig)); - } - - /** - * Test the default hiding of passwords inside the cache - */ - public function testPasswordHide() - { - $configCache = new Cache([ - 'database' => [ - 'password' => 'supersecure', - 'username' => 'notsecured', - ], - ]); - - self::assertEquals('supersecure', $configCache->get('database', 'password')); - self::assertNotEquals('supersecure', print_r($configCache->get('database', 'password'), true)); - self::assertEquals('notsecured', print_r($configCache->get('database', 'username'), true)); - } - - /** - * Test disabling the hiding of passwords inside the cache - */ - public function testPasswordShow() - { - $configCache = new Cache([ - 'database' => [ - 'password' => 'supersecure', - 'username' => 'notsecured', - ], - ], false); - - self::assertEquals('supersecure', $configCache->get('database', 'password')); - self::assertEquals('supersecure', print_r($configCache->get('database', 'password'), true)); - self::assertEquals('notsecured', print_r($configCache->get('database', 'username'), true)); - } - - /** - * Test a empty password - */ - public function testEmptyPassword() - { - $configCache = new Cache([ - 'database' => [ - 'password' => '', - 'username' => '', - ] - ]); - - self::assertNotEmpty($configCache->get('database', 'password')); - self::assertInstanceOf(HiddenString::class, $configCache->get('database', 'password')); - self::assertEmpty($configCache->get('database', 'username')); - } - - public function testWrongTypePassword() - { - $configCache = new Cache([ - 'database' => [ - 'password' => new stdClass(), - 'username' => '', - ] - ]); - - self::assertNotEmpty($configCache->get('database', 'password')); - self::assertEmpty($configCache->get('database', 'username')); - - $configCache = new Cache([ - 'database' => [ - 'password' => 23, - 'username' => '', - ] - ]); - - self::assertEquals(23, $configCache->get('database', 'password')); - self::assertEmpty($configCache->get('database', 'username')); - } - - /** - * Test the set() method with overrides - * @dataProvider dataTests - */ - public function testSetOverrides($data) - { - - $configCache = new Cache(); - $configCache->load($data, Cache::SOURCE_DB); - - // test with wrong override - self::assertFalse($configCache->set('system', 'test', '1234567', Cache::SOURCE_FILE)); - self::assertEquals($data['system']['test'], $configCache->get('system', 'test')); - - // test with override (equal) - self::assertTrue($configCache->set('system', 'test', '8910', Cache::SOURCE_DB)); - self::assertEquals('8910', $configCache->get('system', 'test')); - - // test with override (over) - self::assertTrue($configCache->set('system', 'test', '111213', Cache::SOURCE_ENV)); - self::assertEquals('111213', $configCache->get('system', 'test')); - } -} diff --git a/tests/src/Core/Config/ConfigTest.php b/tests/src/Core/Config/ConfigTest.php index 734f6bff79..e770859875 100644 --- a/tests/src/Core/Config/ConfigTest.php +++ b/tests/src/Core/Config/ConfigTest.php @@ -23,7 +23,7 @@ namespace Friendica\Test\src\Core\Config; use Friendica\Core\Config\Cache; use Friendica\Core\Config\IConfig; -use Friendica\Model\Config\Config as ConfigModel; +use Friendica\Core\Config\Model\Config as ConfigModel; use Friendica\Test\MockedTest; use Mockery\MockInterface; use Mockery; @@ -33,7 +33,7 @@ abstract class ConfigTest extends MockedTest /** @var ConfigModel|MockInterface */ protected $configModel; - /** @var Cache */ + /** @var Cache\Cache */ protected $configCache; /** @var IConfig */ @@ -61,7 +61,7 @@ abstract class ConfigTest extends MockedTest // Create the config model $this->configModel = Mockery::mock(ConfigModel::class); - $this->configCache = new Cache(); + $this->configCache = new Cache\Cache(); } /** @@ -161,7 +161,7 @@ abstract class ConfigTest extends MockedTest ->once(); $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); // assert config is loaded everytime self::assertConfig('config', $data['config']); @@ -176,7 +176,7 @@ abstract class ConfigTest extends MockedTest public function testLoad(array $data, array $load) { $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); foreach ($load as $loadedCats) { $this->testedConfig->load($loadedCats); @@ -257,7 +257,7 @@ abstract class ConfigTest extends MockedTest public function testCacheLoadDouble(array $data1, array $data2, array $expect = []) { $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); foreach ($data1 as $cat => $data) { $this->testedConfig->load($cat); @@ -282,7 +282,7 @@ abstract class ConfigTest extends MockedTest $this->configModel->shouldReceive('load')->withAnyArgs()->andReturn([])->once(); $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); self::assertEmpty($this->testedConfig->getCache()->getAll()); } @@ -299,7 +299,7 @@ abstract class ConfigTest extends MockedTest ->times(3); $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); self::assertTrue($this->testedConfig->set('test', 'it', $data)); @@ -317,7 +317,7 @@ abstract class ConfigTest extends MockedTest $this->configModel->shouldReceive('set')->with('test', 'it', $data)->andReturn(true)->once(); $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); self::assertTrue($this->testedConfig->set('test', 'it', $data)); @@ -331,7 +331,7 @@ abstract class ConfigTest extends MockedTest public function testGetWrongWithoutDB() { $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); // without refresh self::assertNull($this->testedConfig->get('test', 'it')); @@ -353,10 +353,10 @@ abstract class ConfigTest extends MockedTest */ public function testGetWithRefresh($data) { - $this->configCache->load(['test' => ['it' => 'now']], Cache::SOURCE_FILE); + $this->configCache->load(['test' => ['it' => 'now']], Cache\Cache::SOURCE_FILE); $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); // without refresh self::assertEquals('now', $this->testedConfig->get('test', 'it')); @@ -378,10 +378,10 @@ abstract class ConfigTest extends MockedTest */ public function testDeleteWithoutDB($data) { - $this->configCache->load(['test' => ['it' => $data]], Cache::SOURCE_FILE); + $this->configCache->load(['test' => ['it' => $data]], Cache\Cache::SOURCE_FILE); $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); self::assertEquals($data, $this->testedConfig->get('test', 'it')); self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it')); @@ -398,7 +398,7 @@ abstract class ConfigTest extends MockedTest */ public function testDeleteWithDB() { - $this->configCache->load(['test' => ['it' => 'now', 'quarter' => 'true']], Cache::SOURCE_FILE); + $this->configCache->load(['test' => ['it' => 'now', 'quarter' => 'true']], Cache\Cache::SOURCE_FILE); $this->configModel->shouldReceive('delete') ->with('test', 'it') @@ -418,7 +418,7 @@ abstract class ConfigTest extends MockedTest ->once(); $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); // directly set the value to the cache $this->testedConfig->getCache()->set('test', 'it', 'now'); @@ -444,9 +444,9 @@ abstract class ConfigTest extends MockedTest public function testSetGetHighPrio() { $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); - $this->testedConfig->getCache()->set('config', 'test', 'prio', Cache::SOURCE_FILE); + $this->testedConfig->getCache()->set('config', 'test', 'prio', Cache\Cache::SOURCE_FILE); self::assertEquals('prio', $this->testedConfig->get('config', 'test')); // now you have to get the new variable entry because of the new set the get refresh succeed as well @@ -460,10 +460,10 @@ abstract class ConfigTest extends MockedTest public function testSetGetLowPrio() { $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); self::assertEquals('it', $this->testedConfig->get('config', 'test')); - $this->testedConfig->getCache()->set('config', 'test', 'prio', Cache::SOURCE_ENV); + $this->testedConfig->getCache()->set('config', 'test', 'prio', Cache\Cache::SOURCE_ENV); // now you have to get the env variable entry as output, even with a new set (which failed) and a get refresh self::assertFalse($this->testedConfig->set('config', 'test', '123')); self::assertEquals('prio', $this->testedConfig->get('config', 'test', '', true)); diff --git a/tests/src/Core/Config/JitConfigTest.php b/tests/src/Core/Config/JitConfigTest.php index 62c5effda6..5c923beec7 100644 --- a/tests/src/Core/Config/JitConfigTest.php +++ b/tests/src/Core/Config/JitConfigTest.php @@ -21,7 +21,7 @@ namespace Friendica\Test\src\Core\Config; -use Friendica\Core\Config\JitConfig; +use Friendica\Core\Config\Type\JitConfig; class JitConfigTest extends ConfigTest { diff --git a/tests/src/Core/Config/PreloadConfigTest.php b/tests/src/Core/Config/PreloadConfigTest.php index d12f2dcd59..9ce6f4e1ba 100644 --- a/tests/src/Core/Config/PreloadConfigTest.php +++ b/tests/src/Core/Config/PreloadConfigTest.php @@ -21,7 +21,7 @@ namespace Friendica\Test\src\Core\Config; -use Friendica\Core\Config\PreloadConfig; +use Friendica\Core\Config\Type\PreloadConfig; class PreloadConfigTest extends ConfigTest { diff --git a/tests/src/Core/InstallerTest.php b/tests/src/Core/InstallerTest.php index 1263fe7e67..bdb1d53c0b 100644 --- a/tests/src/Core/InstallerTest.php +++ b/tests/src/Core/InstallerTest.php @@ -23,7 +23,7 @@ namespace Friendica\Core; use Dice\Dice; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\DI; use Friendica\Network\IHTTPResult; use Friendica\Network\IHTTPClient; diff --git a/tests/src/Core/Lock/DatabaseLockDriverTest.php b/tests/src/Core/Lock/DatabaseLockDriverTest.php index c51d153efc..86209d5c7d 100644 --- a/tests/src/Core/Lock/DatabaseLockDriverTest.php +++ b/tests/src/Core/Lock/DatabaseLockDriverTest.php @@ -22,11 +22,10 @@ namespace Friendica\Test\src\Core\Lock; use Friendica\Core\Lock\DatabaseLock; -use Friendica\Factory\ConfigFactory; +use Friendica\Core\Config\Factory\ConfigFactory; use Friendica\Test\DatabaseTestTrait; use Friendica\Test\Util\Database\StaticDatabase; use Friendica\Test\Util\VFSTrait; -use Friendica\Util\ConfigFileLoader; use Friendica\Util\Profiler; use Mockery; use Psr\Log\NullLogger; diff --git a/tests/src/Core/Lock/SemaphoreLockTest.php b/tests/src/Core/Lock/SemaphoreLockTest.php index 87d8b2cd2f..89a3ec633c 100644 --- a/tests/src/Core/Lock/SemaphoreLockTest.php +++ b/tests/src/Core/Lock/SemaphoreLockTest.php @@ -24,7 +24,7 @@ namespace Friendica\Test\src\Core\Lock; use Dice\Dice; use Friendica\App; use Friendica\Core\Config\IConfig; -use Friendica\Core\Config\JitConfig; +use Friendica\Core\Config\Type\JitConfig; use Friendica\Core\Lock\SemaphoreLock; use Friendica\DI; use Mockery; diff --git a/tests/src/Core/PConfig/Cache/CacheTest.php b/tests/src/Core/PConfig/Cache/CacheTest.php new file mode 100644 index 0000000000..99e0e914da --- /dev/null +++ b/tests/src/Core/PConfig/Cache/CacheTest.php @@ -0,0 +1,292 @@ +. + * + */ + +namespace Friendica\Test\src\Core\PConfig\Cache; + +use Friendica\Core\PConfig\Cache; +use Friendica\Test\MockedTest; + +class CacheTest extends MockedTest +{ + public function dataTests() + { + return [ + 'normal' => [ + 'data' => [ + 'system' => [ + 'test' => 'it', + 'boolTrue' => true, + 'boolFalse' => false, + 'int' => 235, + 'dec' => 2.456, + 'array' => ['1', 2, '3', true, false], + ], + 'config' => [ + 'a' => 'value', + ], + ] + ] + ]; + } + + private function assertConfigValues($data, Cache\Cache $configCache, $uid) + { + foreach ($data as $cat => $values) { + foreach ($values as $key => $value) { + self::assertEquals($data[$cat][$key], $configCache->get($uid, $cat, $key)); + } + } + } + + /** + * Test the setP() and getP() methods + * + * @dataProvider dataTests + */ + public function testSetGet($data) + { + $configCache = new Cache\Cache(); + $uid = 345; + + foreach ($data as $cat => $values) { + foreach ($values as $key => $value) { + $configCache->set($uid, $cat, $key, $value); + } + } + + self::assertConfigValues($data, $configCache, $uid); + } + + + /** + * Test the getP() method with a category + */ + public function testGetCat() + { + $configCache = new Cache\Cache(); + $uid = 345; + + $configCache->load($uid, [ + 'system' => [ + 'key1' => 'value1', + 'key2' => 'value2', + ], + 'config' => [ + 'key3' => 'value3', + ], + ]); + + self::assertEquals([ + 'key1' => 'value1', + 'key2' => 'value2', + ], $configCache->get($uid, 'system')); + + // test explicit cat with null as key + self::assertEquals([ + 'key1' => 'value1', + 'key2' => 'value2', + ], $configCache->get($uid, 'system', null)); + } + + /** + * Test the deleteP() method + * + * @dataProvider dataTests + */ + public function testDelete($data) + { + $configCache = new Cache\Cache(); + $uid = 345; + + foreach ($data as $cat => $values) { + foreach ($values as $key => $value) { + $configCache->set($uid, $cat, $key, $value); + } + } + + foreach ($data as $cat => $values) { + foreach ($values as $key => $value) { + $configCache->delete($uid, $cat, $key); + } + } + + self::assertEmpty($configCache->getAll()); + } + + /** + * Test the keyDiff() method with result + */ + public function testKeyDiffWithResult() + { + $configCache = new Cache\Cache(); + + $diffConfig = [ + 'fakeCat' => [ + 'fakeKey' => 'value', + ] + ]; + + self::assertEquals($diffConfig, $configCache->keyDiff($diffConfig)); + } + + /** + * Test the keyDiff() method without result + * + * @dataProvider dataTests + */ + public function testKeyDiffWithoutResult($data) + { + $configCache = new Cache\Cache(); + + $configCache->load(1, $data); + + $diffConfig = $configCache->getAll(); + + self::assertEmpty($configCache->keyDiff($diffConfig)); + } + + /** + * Test the default hiding of passwords inside the cache + */ + public function testPasswordHide() + { + $configCache = new Cache\Cache(); + + $configCache->load(1, [ + 'database' => [ + 'password' => 'supersecure', + 'username' => 'notsecured', + ] + ]); + + self::assertEquals('supersecure', $configCache->get(1, 'database', 'password')); + self::assertNotEquals('supersecure', print_r($configCache->get(1, 'database', 'password'), true)); + self::assertEquals('notsecured', print_r($configCache->get(1, 'database', 'username'), true)); + } + + /** + * Test disabling the hiding of passwords inside the cache + */ + public function testPasswordShow() + { + $configCache = new Cache\Cache(false); + + $configCache->load(1, [ + 'database' => [ + 'password' => 'supersecure', + 'username' => 'notsecured', + ] + ]); + + self::assertEquals('supersecure', $configCache->get(1, 'database', 'password')); + self::assertEquals('supersecure', print_r($configCache->get(1, 'database', 'password'), true)); + self::assertEquals('notsecured', print_r($configCache->get(1, 'database', 'username'), true)); + } + + /** + * Test a empty password + */ + public function testEmptyPassword() + { + $configCache = new Cache\Cache(); + + $configCache->load(1, [ + 'database' => [ + 'password' => '', + 'username' => '', + ] + ]); + + self::assertEmpty($configCache->get(1, 'database', 'password')); + self::assertEmpty($configCache->get(1, 'database', 'username')); + } + + public function testWrongTypePassword() + { + $configCache = new Cache\Cache(); + + $configCache->load(1, [ + 'database' => [ + 'password' => new \stdClass(), + 'username' => '', + ] + ]); + + self::assertNotEmpty($configCache->get(1, 'database', 'password')); + self::assertEmpty($configCache->get(1, 'database', 'username')); + + $configCache = new Cache\Cache(); + + $configCache->load(1, [ + 'database' => [ + 'password' => 23, + 'username' => '', + ], + ]); + + self::assertEquals(23, $configCache->get(1, 'database', 'password')); + self::assertEmpty($configCache->get(1, 'database', 'username')); + } + + /** + * Test two different UID configs and make sure that there is no overlapping possible + */ + public function testTwoUid() + { + $configCache = new Cache\Cache(); + + $configCache->load(1, [ + 'cat1' => [ + 'key1' => 'value1', + ], + ]); + + + $configCache->load(2, [ + 'cat2' => [ + 'key2' => 'value2', + ], + ]); + + self::assertEquals('value1', $configCache->get(1, 'cat1', 'key1')); + self::assertEquals('value2', $configCache->get(2, 'cat2', 'key2')); + + self::assertNull($configCache->get(1, 'cat2', 'key2')); + self::assertNull($configCache->get(2, 'cat1', 'key1')); + } + + /** + * Test when using an invalid UID + * @todo check it the clean way before using the config class + */ + public function testInvalidUid() + { + // bad UID! + $uid = null; + + $configCache = new Cache\Cache(); + + self::assertNull($configCache->get($uid, 'cat1', 'cat2')); + + self::assertFalse($configCache->set($uid, 'cat1', 'key1', 'doesn\'t matter!')); + self::assertFalse($configCache->delete($uid, 'cat1', 'key1')); + } +} diff --git a/tests/src/Core/PConfig/CacheTest.php b/tests/src/Core/PConfig/CacheTest.php deleted file mode 100644 index 77f6140bd8..0000000000 --- a/tests/src/Core/PConfig/CacheTest.php +++ /dev/null @@ -1,292 +0,0 @@ -. - * - */ - -namespace Friendica\Test\src\Core\PConfig; - -use Friendica\Core\PConfig\Cache; -use Friendica\Test\MockedTest; - -class CacheTest extends MockedTest -{ - public function dataTests() - { - return [ - 'normal' => [ - 'data' => [ - 'system' => [ - 'test' => 'it', - 'boolTrue' => true, - 'boolFalse' => false, - 'int' => 235, - 'dec' => 2.456, - 'array' => ['1', 2, '3', true, false], - ], - 'config' => [ - 'a' => 'value', - ], - ] - ] - ]; - } - - private function assertConfigValues($data, Cache $configCache, $uid) - { - foreach ($data as $cat => $values) { - foreach ($values as $key => $value) { - self::assertEquals($data[$cat][$key], $configCache->get($uid, $cat, $key)); - } - } - } - - /** - * Test the setP() and getP() methods - * - * @dataProvider dataTests - */ - public function testSetGet($data) - { - $configCache = new Cache(); - $uid = 345; - - foreach ($data as $cat => $values) { - foreach ($values as $key => $value) { - $configCache->set($uid, $cat, $key, $value); - } - } - - self::assertConfigValues($data, $configCache, $uid); - } - - - /** - * Test the getP() method with a category - */ - public function testGetCat() - { - $configCache = new Cache(); - $uid = 345; - - $configCache->load($uid, [ - 'system' => [ - 'key1' => 'value1', - 'key2' => 'value2', - ], - 'config' => [ - 'key3' => 'value3', - ], - ]); - - self::assertEquals([ - 'key1' => 'value1', - 'key2' => 'value2', - ], $configCache->get($uid, 'system')); - - // test explicit cat with null as key - self::assertEquals([ - 'key1' => 'value1', - 'key2' => 'value2', - ], $configCache->get($uid, 'system', null)); - } - - /** - * Test the deleteP() method - * - * @dataProvider dataTests - */ - public function testDelete($data) - { - $configCache = new Cache(); - $uid = 345; - - foreach ($data as $cat => $values) { - foreach ($values as $key => $value) { - $configCache->set($uid, $cat, $key, $value); - } - } - - foreach ($data as $cat => $values) { - foreach ($values as $key => $value) { - $configCache->delete($uid, $cat, $key); - } - } - - self::assertEmpty($configCache->getAll()); - } - - /** - * Test the keyDiff() method with result - */ - public function testKeyDiffWithResult() - { - $configCache = new Cache(); - - $diffConfig = [ - 'fakeCat' => [ - 'fakeKey' => 'value', - ] - ]; - - self::assertEquals($diffConfig, $configCache->keyDiff($diffConfig)); - } - - /** - * Test the keyDiff() method without result - * - * @dataProvider dataTests - */ - public function testKeyDiffWithoutResult($data) - { - $configCache = new Cache(); - - $configCache->load(1, $data); - - $diffConfig = $configCache->getAll(); - - self::assertEmpty($configCache->keyDiff($diffConfig)); - } - - /** - * Test the default hiding of passwords inside the cache - */ - public function testPasswordHide() - { - $configCache = new Cache(); - - $configCache->load(1, [ - 'database' => [ - 'password' => 'supersecure', - 'username' => 'notsecured', - ] - ]); - - self::assertEquals('supersecure', $configCache->get(1, 'database', 'password')); - self::assertNotEquals('supersecure', print_r($configCache->get(1, 'database', 'password'), true)); - self::assertEquals('notsecured', print_r($configCache->get(1, 'database', 'username'), true)); - } - - /** - * Test disabling the hiding of passwords inside the cache - */ - public function testPasswordShow() - { - $configCache = new Cache(false); - - $configCache->load(1, [ - 'database' => [ - 'password' => 'supersecure', - 'username' => 'notsecured', - ] - ]); - - self::assertEquals('supersecure', $configCache->get(1, 'database', 'password')); - self::assertEquals('supersecure', print_r($configCache->get(1, 'database', 'password'), true)); - self::assertEquals('notsecured', print_r($configCache->get(1, 'database', 'username'), true)); - } - - /** - * Test a empty password - */ - public function testEmptyPassword() - { - $configCache = new Cache(); - - $configCache->load(1, [ - 'database' => [ - 'password' => '', - 'username' => '', - ] - ]); - - self::assertEmpty($configCache->get(1, 'database', 'password')); - self::assertEmpty($configCache->get(1, 'database', 'username')); - } - - public function testWrongTypePassword() - { - $configCache = new Cache(); - - $configCache->load(1, [ - 'database' => [ - 'password' => new \stdClass(), - 'username' => '', - ] - ]); - - self::assertNotEmpty($configCache->get(1, 'database', 'password')); - self::assertEmpty($configCache->get(1, 'database', 'username')); - - $configCache = new Cache(); - - $configCache->load(1, [ - 'database' => [ - 'password' => 23, - 'username' => '', - ], - ]); - - self::assertEquals(23, $configCache->get(1, 'database', 'password')); - self::assertEmpty($configCache->get(1, 'database', 'username')); - } - - /** - * Test two different UID configs and make sure that there is no overlapping possible - */ - public function testTwoUid() - { - $configCache = new Cache(); - - $configCache->load(1, [ - 'cat1' => [ - 'key1' => 'value1', - ], - ]); - - - $configCache->load(2, [ - 'cat2' => [ - 'key2' => 'value2', - ], - ]); - - self::assertEquals('value1', $configCache->get(1, 'cat1', 'key1')); - self::assertEquals('value2', $configCache->get(2, 'cat2', 'key2')); - - self::assertNull($configCache->get(1, 'cat2', 'key2')); - self::assertNull($configCache->get(2, 'cat1', 'key1')); - } - - /** - * Test when using an invalid UID - * @todo check it the clean way before using the config class - */ - public function testInvalidUid() - { - // bad UID! - $uid = null; - - $configCache = new Cache(); - - self::assertNull($configCache->get($uid, 'cat1', 'cat2')); - - self::assertFalse($configCache->set($uid, 'cat1', 'key1', 'doesn\'t matter!')); - self::assertFalse($configCache->delete($uid, 'cat1', 'key1')); - } -} diff --git a/tests/src/Core/PConfig/JitPConfigTest.php b/tests/src/Core/PConfig/JitPConfigTest.php index f43b9cd762..34428cb317 100644 --- a/tests/src/Core/PConfig/JitPConfigTest.php +++ b/tests/src/Core/PConfig/JitPConfigTest.php @@ -21,7 +21,7 @@ namespace Friendica\Test\src\Core\PConfig; -use Friendica\Core\PConfig\JitPConfig; +use Friendica\Core\PConfig\Type\JitPConfig; class JitPConfigTest extends PConfigTest { diff --git a/tests/src/Core/PConfig/PConfigTest.php b/tests/src/Core/PConfig/PConfigTest.php index f35aa10d98..9288b10585 100644 --- a/tests/src/Core/PConfig/PConfigTest.php +++ b/tests/src/Core/PConfig/PConfigTest.php @@ -22,8 +22,8 @@ namespace Friendica\Test\src\Core\PConfig; use Friendica\Core\PConfig\Cache; -use Friendica\Core\BasePConfig; -use Friendica\Model\Config\PConfig as PConfigModel; +use Friendica\Core\PConfig\Type\BasePConfig; +use Friendica\Core\PConfig\Model\PConfig as PConfigModel; use Friendica\Test\MockedTest; use Mockery; use Mockery\MockInterface; @@ -33,7 +33,7 @@ abstract class PConfigTest extends MockedTest /** @var PConfigModel|MockInterface */ protected $configModel; - /** @var Cache */ + /** @var Cache\Cache */ protected $configCache; /** @var BasePConfig */ @@ -63,11 +63,11 @@ abstract class PConfigTest extends MockedTest // Create the config model $this->configModel = Mockery::mock(PConfigModel::class); - $this->configCache = new Cache(); + $this->configCache = new Cache\Cache(); } /** - * @return BasePConfig + * @return \Friendica\Core\PConfig\Type\BasePConfig */ abstract public function getInstance(); @@ -163,7 +163,7 @@ abstract class PConfigTest extends MockedTest public function testSetUp() { $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); self::assertEmpty($this->testedConfig->getCache()->getAll()); } @@ -174,7 +174,7 @@ abstract class PConfigTest extends MockedTest public function testLoad(int $uid, array $data, array $possibleCats, array $load) { $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); foreach ($load as $loadedCats) { $this->testedConfig->load($uid, $loadedCats); @@ -257,7 +257,7 @@ abstract class PConfigTest extends MockedTest public function testCacheLoadDouble(int $uid, array $data1, array $data2, array $expect) { $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); foreach ($data1 as $cat => $data) { $this->testedConfig->load($uid, $cat); @@ -281,7 +281,7 @@ abstract class PConfigTest extends MockedTest public function testSetGetWithoutDB(int $uid, $data) { $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); self::assertTrue($this->testedConfig->set($uid, 'test', 'it', $data)); @@ -302,7 +302,7 @@ abstract class PConfigTest extends MockedTest ->once(); $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); self::assertTrue($this->testedConfig->set($uid, 'test', 'it', $data)); @@ -316,7 +316,7 @@ abstract class PConfigTest extends MockedTest public function testGetWrongWithoutDB() { $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); // without refresh self::assertNull($this->testedConfig->get(0, 'test', 'it')); @@ -341,7 +341,7 @@ abstract class PConfigTest extends MockedTest $this->configCache->load($uid, ['test' => ['it' => 'now']]); $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); // without refresh self::assertEquals('now', $this->testedConfig->get($uid, 'test', 'it')); @@ -366,7 +366,7 @@ abstract class PConfigTest extends MockedTest $this->configCache->load($uid, ['test' => ['it' => $data]]); $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); self::assertEquals($data, $this->testedConfig->get($uid, 'test', 'it')); self::assertEquals($data, $this->testedConfig->getCache()->get($uid, 'test', 'it')); @@ -405,7 +405,7 @@ abstract class PConfigTest extends MockedTest ->once(); $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); // directly set the value to the cache $this->testedConfig->getCache()->set($uid, 'test', 'it', 'now'); @@ -465,7 +465,7 @@ abstract class PConfigTest extends MockedTest $this->configCache->load($data2['uid'], $data2['data']); $this->testedConfig = $this->getInstance(); - self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); + self::assertInstanceOf(Cache\Cache::class, $this->testedConfig->getCache()); self::assertConfig($data1['uid'], 'cat1', $data1['data']['cat1']); self::assertConfig($data1['uid'], 'cat2', $data1['data']['cat2']); diff --git a/tests/src/Core/PConfig/PreloadPConfigTest.php b/tests/src/Core/PConfig/PreloadPConfigTest.php index aa4c2f70b1..6ffee63f76 100644 --- a/tests/src/Core/PConfig/PreloadPConfigTest.php +++ b/tests/src/Core/PConfig/PreloadPConfigTest.php @@ -21,13 +21,13 @@ namespace Friendica\Test\src\Core\PConfig; -use Friendica\Core\PConfig\PreloadPConfig; +use Friendica\Core\PConfig\Type\PreloadPConfig; class PreloadPConfigTest extends PConfigTest { public function getInstance() { - return new PreloadPConfig($this->configCache, $this->configModel); + return new \Friendica\Core\PConfig\Type\PreloadPConfig($this->configCache, $this->configModel); } /** diff --git a/tests/src/Core/StorageManagerTest.php b/tests/src/Core/StorageManagerTest.php index 77e4946bdf..acab50ce42 100644 --- a/tests/src/Core/StorageManagerTest.php +++ b/tests/src/Core/StorageManagerTest.php @@ -23,22 +23,22 @@ namespace Friendica\Test\src\Core; use Dice\Dice; use Friendica\Core\Config\IConfig; -use Friendica\Core\Config\PreloadConfig; +use Friendica\Core\Config\Type\PreloadConfig; use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Session\ISession; use Friendica\Core\StorageManager; use Friendica\Database\Database; use Friendica\DI; -use Friendica\Factory\ConfigFactory; -use Friendica\Model\Config\Config; +use Friendica\Core\Config\Factory\ConfigFactory; +use Friendica\Core\Config\Model\Config; use Friendica\Model\Storage; use Friendica\Core\Session; use Friendica\Network\HTTPClient; use Friendica\Test\DatabaseTest; use Friendica\Test\Util\Database\StaticDatabase; use Friendica\Test\Util\VFSTrait; -use Friendica\Util\ConfigFileLoader; +use Friendica\Core\Config\Cache\ConfigFileLoader; use Friendica\Util\Profiler; use org\bovigo\vfs\vfsStream; use Psr\Log\LoggerInterface; diff --git a/tests/src/Model/ProcessTest.php b/tests/src/Model/ProcessTest.php index a4739d7f5b..ecb4d52d49 100644 --- a/tests/src/Model/ProcessTest.php +++ b/tests/src/Model/ProcessTest.php @@ -2,12 +2,11 @@ namespace Friendica\Test\src\Model; -use Friendica\Factory\ConfigFactory; +use Friendica\Core\Config\Factory\ConfigFactory; use Friendica\Model\Process; use Friendica\Test\DatabaseTest; use Friendica\Test\Util\Database\StaticDatabase; use Friendica\Test\Util\VFSTrait; -use Friendica\Util\ConfigFileLoader; use Friendica\Util\Profiler; use Psr\Log\NullLogger; diff --git a/tests/src/Model/Storage/DatabaseStorageTest.php b/tests/src/Model/Storage/DatabaseStorageTest.php index e1dfef9a18..e92dd21352 100644 --- a/tests/src/Model/Storage/DatabaseStorageTest.php +++ b/tests/src/Model/Storage/DatabaseStorageTest.php @@ -21,7 +21,7 @@ namespace Friendica\Test\src\Model\Storage; -use Friendica\Factory\ConfigFactory; +use Friendica\Core\Config\Factory\ConfigFactory; use Friendica\Model\Storage\Database; use Friendica\Test\DatabaseTestTrait; use Friendica\Test\Util\Database\StaticDatabase; diff --git a/tests/src/Util/Config/ConfigFileLoaderTest.php b/tests/src/Util/Config/ConfigFileLoaderTest.php deleted file mode 100644 index cb3ae840ce..0000000000 --- a/tests/src/Util/Config/ConfigFileLoaderTest.php +++ /dev/null @@ -1,381 +0,0 @@ -. - * - */ - -namespace Friendica\Test\src\Util\Config; - -use Friendica\Core\Config\Cache; -use Friendica\Factory\ConfigFactory; -use Friendica\Test\MockedTest; -use Friendica\Test\Util\VFSTrait; -use Friendica\Util\ConfigFileLoader; -use org\bovigo\vfs\vfsStream; - -class ConfigFileLoaderTest extends MockedTest -{ - use VFSTrait; - - protected function setUp(): void - { - parent::setUp(); - - $this->setUpVfsDir(); - } - - /** - * Test the loadConfigFiles() method with default values - */ - public function testLoadConfigFiles() - { - $this->delConfigFile('local.config.php'); - - $configFileLoader = new ConfigFileLoader( - $this->root->url(), - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR - ); - $configCache = new Cache(); - - $configFileLoader->setupCache($configCache); - - self::assertEquals($this->root->url(), $configCache->get('system', 'basepath')); - } - - /** - * Test the loadConfigFiles() method with a wrong local.config.php - * - */ - public function testLoadConfigWrong() - { - $this->expectExceptionMessageMatches("/Error loading config file \w+/"); - $this->expectException(\Exception::class); - $this->delConfigFile('local.config.php'); - - vfsStream::newFile('local.config.php') - ->at($this->root->getChild('config')) - ->setContent('root->url(), - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR - ); - $configCache = new Cache(); - - $configFileLoader->setupCache($configCache); - } - - /** - * Test the loadConfigFiles() method with a local.config.php file - */ - public function testLoadConfigFilesLocal() - { - $this->delConfigFile('local.config.php'); - - $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - 'datasets' . DIRECTORY_SEPARATOR . - 'config' . DIRECTORY_SEPARATOR . - 'A.config.php'; - - vfsStream::newFile('local.config.php') - ->at($this->root->getChild('config')) - ->setContent(file_get_contents($file)); - - $configFileLoader = new ConfigFileLoader( - $this->root->url(), - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR - ); - $configCache = new Cache(); - - $configFileLoader->setupCache($configCache); - - self::assertEquals('testhost', $configCache->get('database', 'hostname')); - self::assertEquals('testuser', $configCache->get('database', 'username')); - self::assertEquals('testpw', $configCache->get('database', 'password')); - self::assertEquals('testdb', $configCache->get('database', 'database')); - - self::assertEquals('admin@test.it', $configCache->get('config', 'admin_email')); - self::assertEquals('Friendica Social Network', $configCache->get('config', 'sitename')); - } - - /** - * Test the loadConfigFile() method with a local.ini.php file - */ - public function testLoadConfigFilesINI() - { - $this->delConfigFile('local.config.php'); - - $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - 'datasets' . DIRECTORY_SEPARATOR . - 'config' . DIRECTORY_SEPARATOR . - 'A.ini.php'; - - vfsStream::newFile('local.ini.php') - ->at($this->root->getChild('config')) - ->setContent(file_get_contents($file)); - - $configFileLoader = new ConfigFileLoader( - $this->root->url(), - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR - ); - $configCache = new Cache(); - - $configFileLoader->setupCache($configCache); - - self::assertEquals('testhost', $configCache->get('database', 'hostname')); - self::assertEquals('testuser', $configCache->get('database', 'username')); - self::assertEquals('testpw', $configCache->get('database', 'password')); - self::assertEquals('testdb', $configCache->get('database', 'database')); - - self::assertEquals('admin@test.it', $configCache->get('config', 'admin_email')); - } - - /** - * Test the loadConfigFile() method with a .htconfig.php file - */ - public function testLoadConfigFilesHtconfig() - { - $this->delConfigFile('local.config.php'); - - $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - 'datasets' . DIRECTORY_SEPARATOR . - 'config' . DIRECTORY_SEPARATOR . - '.htconfig.php'; - - vfsStream::newFile('.htconfig.php') - ->at($this->root) - ->setContent(file_get_contents($file)); - - $configFileLoader = new ConfigFileLoader( - $this->root->url(), - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR - ); - $configCache = new Cache(); - - $configFileLoader->setupCache($configCache); - - self::assertEquals('testhost', $configCache->get('database', 'hostname')); - self::assertEquals('testuser', $configCache->get('database', 'username')); - self::assertEquals('testpw', $configCache->get('database', 'password')); - self::assertEquals('testdb', $configCache->get('database', 'database')); - self::assertEquals('anotherCharset', $configCache->get('database', 'charset')); - - self::assertEquals('/var/run/friendica.pid', $configCache->get('system', 'pidfile')); - self::assertEquals('Europe/Berlin', $configCache->get('system', 'default_timezone')); - self::assertEquals('fr', $configCache->get('system', 'language')); - - self::assertEquals('admin@test.it', $configCache->get('config', 'admin_email')); - self::assertEquals('Friendly admin', $configCache->get('config', 'admin_nickname')); - - self::assertEquals('/another/php', $configCache->get('config', 'php_path')); - self::assertEquals('999', $configCache->get('config', 'max_import_size')); - self::assertEquals('666', $configCache->get('system', 'maximagesize')); - - self::assertEquals('frio,quattro,vier,duepuntozero', $configCache->get('system', 'allowed_themes')); - self::assertEquals('1', $configCache->get('system', 'no_regfullname')); - } - - public function testLoadAddonConfig() - { - $structure = [ - 'addon' => [ - 'test' => [ - 'config' => [], - ], - ], - ]; - - vfsStream::create($structure, $this->root); - - $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - 'datasets' . DIRECTORY_SEPARATOR . - 'config' . DIRECTORY_SEPARATOR . - 'A.config.php'; - - vfsStream::newFile('test.config.php') - ->at($this->root->getChild('addon')->getChild('test')->getChild('config')) - ->setContent(file_get_contents($file)); - - $configFileLoader = new ConfigFileLoader( - $this->root->url(), - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR - ); - - $conf = $configFileLoader->loadAddonConfig('test'); - - self::assertEquals('testhost', $conf['database']['hostname']); - self::assertEquals('testuser', $conf['database']['username']); - self::assertEquals('testpw', $conf['database']['password']); - self::assertEquals('testdb', $conf['database']['database']); - - self::assertEquals('admin@test.it', $conf['config']['admin_email']); - } - - /** - * test loading multiple config files - the last config should work - */ - public function testLoadMultipleConfigs() - { - $this->delConfigFile('local.config.php'); - - $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - 'datasets' . DIRECTORY_SEPARATOR . - 'config' . DIRECTORY_SEPARATOR; - - vfsStream::newFile('A.config.php') - ->at($this->root->getChild('config')) - ->setContent(file_get_contents($fileDir . 'A.config.php')); - vfsStream::newFile('B.config.php') - ->at($this->root->getChild('config')) - ->setContent(file_get_contents($fileDir . 'B.config.php')); - - $configFileLoader = new ConfigFileLoader( - $this->root->url(), - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR - ); - $configCache = new Cache(); - - $configFileLoader->setupCache($configCache); - - self::assertEquals('admin@overwritten.local', $configCache->get('config', 'admin_email')); - self::assertEquals('newValue', $configCache->get('system', 'newKey')); - } - - /** - * test loading multiple config files - the last config should work (INI-version) - */ - public function testLoadMultipleInis() - { - $this->delConfigFile('local.config.php'); - - $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - 'datasets' . DIRECTORY_SEPARATOR . - 'config' . DIRECTORY_SEPARATOR; - - vfsStream::newFile('A.ini.php') - ->at($this->root->getChild('config')) - ->setContent(file_get_contents($fileDir . 'A.ini.php')); - vfsStream::newFile('B.ini.php') - ->at($this->root->getChild('config')) - ->setContent(file_get_contents($fileDir . 'B.ini.php')); - - $configFileLoader = new ConfigFileLoader( - $this->root->url(), - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR - ); - $configCache = new Cache(); - - $configFileLoader->setupCache($configCache); - - self::assertEquals('admin@overwritten.local', $configCache->get('config', 'admin_email')); - self::assertEquals('newValue', $configCache->get('system', 'newKey')); - } - - /** - * Test that sample-files (e.g. local-sample.config.php) is never loaded - */ - public function testNotLoadingSamples() - { - $this->delConfigFile('local.config.php'); - - $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - 'datasets' . DIRECTORY_SEPARATOR . - 'config' . DIRECTORY_SEPARATOR; - - vfsStream::newFile('A.ini.php') - ->at($this->root->getChild('config')) - ->setContent(file_get_contents($fileDir . 'A.ini.php')); - vfsStream::newFile('B-sample.ini.php') - ->at($this->root->getChild('config')) - ->setContent(file_get_contents($fileDir . 'B.ini.php')); - - $configFileLoader = new ConfigFileLoader( - $this->root->url(), - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::CONFIG_DIR, - $this->root->url() . DIRECTORY_SEPARATOR . ConfigFactory::STATIC_DIR - ); - $configCache = new Cache(); - - $configFileLoader->setupCache($configCache); - - self::assertEquals('admin@test.it', $configCache->get('config', 'admin_email')); - self::assertEmpty($configCache->get('system', 'NewKey')); - } - - /** - * Test that using a wrong configuration directory leads to the "normal" config path - */ - public function testWrongEnvDir() - { - $this->delConfigFile('local.config.php'); - - $configFileLoader = (new ConfigFactory())->createConfigFileLoader($this->root->url(), ['FRIENDICA_CONFIG_DIR' => '/a/wrong/dir/']); - $configCache = new Cache(); - - $configFileLoader->setupCache($configCache); - - self::assertEquals($this->root->url(), $configCache->get('system', 'basepath')); - } - - /** - * Test that a different location of the configuration directory produces the expected output - */ - public function testRightEnvDir() - { - $this->delConfigFile('local.config.php'); - - $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - '..' . DIRECTORY_SEPARATOR . - 'datasets' . DIRECTORY_SEPARATOR . - 'config' . DIRECTORY_SEPARATOR; - - vfsStream::newFile('B.config.php') - ->at($this->root->getChild('config2')) - ->setContent(file_get_contents($fileDir . 'B.config.php')); - - $configFileLoader = (new ConfigFactory())->createConfigFileLoader($this->root->url(), ['FRIENDICA_CONFIG_DIR' => $this->root->getChild('config2')->url()]); - $configCache = new Cache(); - - $configFileLoader->setupCache($configCache); - - self::assertEquals('newValue', $configCache->get('system', 'newKey')); - } -} diff --git a/tests/src/Util/ProfilerTest.php b/tests/src/Util/ProfilerTest.php index 3178f7d17a..4c55c419b8 100644 --- a/tests/src/Util/ProfilerTest.php +++ b/tests/src/Util/ProfilerTest.php @@ -21,7 +21,7 @@ namespace Friendica\Test\src\Util; -use Friendica\Core\Config\Cache; +use Friendica\Core\Config\Cache\Cache; use Friendica\Core\Config\IConfig; use Friendica\Test\MockedTest; use Friendica\Util\Profiler;