From eafcf3592db02392770cdc88bed9ddb000cb44f2 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 10 Feb 2019 19:52:21 +0100 Subject: [PATCH] Config FollowUp - New Configuration (Config is now only holding the instance) - New PConfiguration (PConfig is now only holding the instance) - Config & PConfig-Adapter don't need "ConfigCache" anymore - DB-Connection is now outside App->reload() for better dependency-chaining --- bin/auth_ejabberd.php | 9 +- bin/console.php | 9 +- bin/daemon.php | 10 +- bin/worker.php | 8 +- index.php | 9 +- src/App.php | 72 +----- src/Core/Config.php | 80 ++----- .../AbstractDbaConfigAdapter.php | 9 +- .../Config/{ => Adapter}/IConfigAdapter.php | 22 +- .../Config/{ => Adapter}/IPConfigAdapter.php | 29 ++- src/Core/Config/Adapter/JITConfigAdapter.php | 123 ++++++++++ src/Core/Config/Adapter/JITPConfigAdapter.php | 126 ++++++++++ .../Config/Adapter/PreloadConfigAdapter.php | 104 +++++++++ .../Config/Adapter/PreloadPConfigAdapter.php | 126 ++++++++++ src/Core/Config/{ => Cache}/ConfigCache.php | 132 ++++++----- .../Config/{ => Cache}/ConfigCacheLoader.php | 12 +- src/Core/Config/Cache/IConfigCache.php | 65 ++++++ src/Core/Config/Cache/IPConfigCache.php | 70 ++++++ src/Core/Config/Configuration.php | 154 +++++++++++++ src/Core/Config/IConfigCache.php | 39 ---- src/Core/Config/IPConfigCache.php | 44 ---- src/Core/Config/JITConfigAdapter.php | 172 -------------- src/Core/Config/JITPConfigAdapter.php | 136 ----------- src/Core/Config/PConfiguration.php | 150 ++++++++++++ src/Core/Config/PreloadConfigAdapter.php | 123 ---------- src/Core/Config/PreloadPConfigAdapter.php | 125 ---------- src/Core/Console/AutomaticInstallation.php | 10 +- src/Core/Console/Config.php | 6 +- src/Core/Console/Typo.php | 2 +- src/Core/Installer.php | 6 +- src/Core/PConfig.php | 89 ++------ src/Database/DBA.php | 2 +- src/Factory/ConfigFactory.php | 53 +++-- src/Factory/DBFactory.php | 48 ++++ src/Factory/LoggerFactory.php | 8 +- src/Module/Install.php | 4 +- tests/DatabaseTest.php | 4 +- tests/Util/AppMockTrait.php | 19 +- tests/include/ApiTest.php | 8 +- tests/src/App/ModeTest.php | 18 +- tests/src/BaseObjectTest.php | 2 +- tests/src/Core/Cache/CacheTest.php | 2 +- .../Core/Cache/MemcacheCacheDriverTest.php | 4 +- .../Core/Cache/MemcachedCacheDriverTest.php | 2 +- tests/src/Core/Cache/RedisCacheDriverTest.php | 4 +- .../{ => Cache}/ConfigCacheLoaderTest.php | 10 +- .../Config/{ => Cache}/ConfigCacheTest.php | 83 ++++++- tests/src/Core/Config/ConfigurationTest.php | 215 ++++++++++++++++++ tests/src/Core/Config/PConfigurationTest.php | 186 +++++++++++++++ .../AutomaticInstallationConsoleTest.php | 2 +- tests/src/Core/Console/ConfigConsoleTest.php | 12 +- tests/src/Core/Console/ConsoleTest.php | 4 +- tests/src/Core/Lock/LockTest.php | 2 +- .../Core/Lock/MemcacheCacheLockDriverTest.php | 4 +- .../Lock/MemcachedCacheLockDriverTest.php | 2 +- .../Core/Lock/RedisCacheLockDriverTest.php | 4 +- .../src/Core/Lock/SemaphoreLockDriverTest.php | 2 +- tests/src/Database/DBATest.php | 8 +- tests/src/Database/DBStructureTest.php | 9 +- 59 files changed, 1754 insertions(+), 1038 deletions(-) rename src/Core/Config/{ => Adapter}/AbstractDbaConfigAdapter.php (52%) rename src/Core/Config/{ => Adapter}/IConfigAdapter.php (59%) rename src/Core/Config/{ => Adapter}/IPConfigAdapter.php (65%) create mode 100644 src/Core/Config/Adapter/JITConfigAdapter.php create mode 100644 src/Core/Config/Adapter/JITPConfigAdapter.php create mode 100644 src/Core/Config/Adapter/PreloadConfigAdapter.php create mode 100644 src/Core/Config/Adapter/PreloadPConfigAdapter.php rename src/Core/Config/{ => Cache}/ConfigCache.php (56%) rename src/Core/Config/{ => Cache}/ConfigCacheLoader.php (93%) create mode 100644 src/Core/Config/Cache/IConfigCache.php create mode 100644 src/Core/Config/Cache/IPConfigCache.php create mode 100644 src/Core/Config/Configuration.php delete mode 100644 src/Core/Config/IConfigCache.php delete mode 100644 src/Core/Config/IPConfigCache.php delete mode 100644 src/Core/Config/JITConfigAdapter.php delete mode 100644 src/Core/Config/JITPConfigAdapter.php create mode 100644 src/Core/Config/PConfiguration.php delete mode 100644 src/Core/Config/PreloadConfigAdapter.php delete mode 100644 src/Core/Config/PreloadPConfigAdapter.php create mode 100644 src/Factory/DBFactory.php rename tests/src/Core/Config/{ => Cache}/ConfigCacheLoaderTest.php (95%) rename tests/src/Core/Config/{ => Cache}/ConfigCacheTest.php (62%) create mode 100644 tests/src/Core/Config/ConfigurationTest.php create mode 100644 tests/src/Core/Config/PConfigurationTest.php diff --git a/bin/auth_ejabberd.php b/bin/auth_ejabberd.php index cc2517644c..7682674d7c 100755 --- a/bin/auth_ejabberd.php +++ b/bin/auth_ejabberd.php @@ -33,7 +33,7 @@ */ use Friendica\App; -use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Factory; use Friendica\Util\BasePath; use Friendica\Util\ExAuth; @@ -55,8 +55,11 @@ chdir($directory); require dirname(__DIR__) . '/vendor/autoload.php'; $basedir = BasePath::create(dirname(__DIR__), $_SERVER); -$configLoader = new Config\ConfigCacheLoader($basedir); -$config = Factory\ConfigFactory::createCache($configLoader); +$configLoader = new Cache\ConfigCacheLoader($basedir); +$configCache = Factory\ConfigFactory::createCache($configLoader); +Factory\DBFactory::init($configCache, $_SERVER); +$config = Factory\ConfigFactory::createConfig($configCache); +$pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('auth_ejabberd', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); diff --git a/bin/console.php b/bin/console.php index 757af31d5d..9fee605b2f 100755 --- a/bin/console.php +++ b/bin/console.php @@ -3,13 +3,16 @@ require dirname(__DIR__) . '/vendor/autoload.php'; -use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Factory; use Friendica\Util\BasePath; $basedir = BasePath::create(dirname(__DIR__), $_SERVER); -$configLoader = new Config\ConfigCacheLoader($basedir); -$config = Factory\ConfigFactory::createCache($configLoader); +$configLoader = new Cache\ConfigCacheLoader($basedir); +$configCache = Factory\ConfigFactory::createCache($configLoader); +Factory\DBFactory::init($configCache, $_SERVER); +$config = Factory\ConfigFactory::createConfig($configCache); +$pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('console', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); diff --git a/bin/daemon.php b/bin/daemon.php index da4bc19925..2b106b62d8 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -9,6 +9,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\Factory; @@ -34,8 +35,11 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) { require dirname(__DIR__) . '/vendor/autoload.php'; $basedir = BasePath::create(dirname(__DIR__), $_SERVER); -$configLoader = new Config\ConfigCacheLoader($basedir); -$config = Factory\ConfigFactory::createCache($configLoader); +$configLoader = new Cache\ConfigCacheLoader($basedir); +$configCache = Factory\ConfigFactory::createCache($configLoader); +Factory\DBFactory::init($configCache, $_SERVER); +$config = Factory\ConfigFactory::createConfig($configCache); +$pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('daemon', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); @@ -151,7 +155,7 @@ if (!$foreground) { file_put_contents($pidfile, $pid); // We lose the database connection upon forking - $a->loadDatabase(); + Factory\DBFactory::init($configCache, $_SERVER); } Config::set('system', 'worker_daemon_mode', true); diff --git a/bin/worker.php b/bin/worker.php index 9b396c6f9c..0a9b4cb38b 100755 --- a/bin/worker.php +++ b/bin/worker.php @@ -7,6 +7,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Core\Update; use Friendica\Core\Worker; use Friendica\Factory; @@ -32,8 +33,11 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) { require dirname(__DIR__) . '/vendor/autoload.php'; $basedir = BasePath::create(dirname(__DIR__), $_SERVER); -$configLoader = new Config\ConfigCacheLoader($basedir); -$config = Factory\ConfigFactory::createCache($configLoader); +$configLoader = new Cache\ConfigCacheLoader($basedir); +$configCache = Factory\ConfigFactory::createCache($configLoader); +Factory\DBFactory::init($configCache, $_SERVER); +$config = Factory\ConfigFactory::createConfig($configCache); +$pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('worker', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); diff --git a/index.php b/index.php index 216fbe90ad..9ef9490b37 100644 --- a/index.php +++ b/index.php @@ -5,7 +5,7 @@ */ use Friendica\App; -use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Factory; use Friendica\Util\BasePath; @@ -16,8 +16,11 @@ if (!file_exists(__DIR__ . '/vendor/autoload.php')) { require __DIR__ . '/vendor/autoload.php'; $basedir = BasePath::create(__DIR__, $_SERVER); -$configLoader = new Config\ConfigCacheLoader($basedir); -$config = Factory\ConfigFactory::createCache($configLoader); +$configLoader = new Cache\ConfigCacheLoader($basedir); +$configCache = Factory\ConfigFactory::createCache($configLoader); +Factory\DBFactory::init($configCache, $_SERVER); +$config = Factory\ConfigFactory::createConfig($configCache); +$pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('index', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); diff --git a/src/App.php b/src/App.php index e61b8dbae4..e715e6ced6 100644 --- a/src/App.php +++ b/src/App.php @@ -8,8 +8,9 @@ use Detection\MobileDetect; use DOMDocument; use DOMXPath; use Exception; -use Friendica\Core\Config\ConfigCache; -use Friendica\Core\Config\ConfigCacheLoader; +use Friendica\Core\Config\Cache\ConfigCacheLoader; +use Friendica\Core\Config\Cache\IConfigCache; +use Friendica\Core\Config\Configuration; use Friendica\Database\DBA; use Friendica\Factory\ConfigFactory; use Friendica\Network\HTTPException\InternalServerErrorException; @@ -114,7 +115,7 @@ class App private $logger; /** - * @var ConfigCache The cached config + * @var Configuration The config */ private $config; @@ -126,11 +127,11 @@ class App /** * Returns the current config cache of this node * - * @return ConfigCache + * @return IConfigCache */ - public function getConfig() + public function getConfigCache() { - return $this->config; + return $this->config->getCache(); } /** @@ -195,14 +196,14 @@ class App /** * @brief App constructor. * - * @param ConfigCache $config The Cached Config + * @param Configuration $config The Configuration * @param LoggerInterface $logger Logger of this application * @param Profiler $profiler The profiler of this application * @param bool $isBackend Whether it is used for backend or frontend (Default true=backend) * * @throws Exception if the Basepath is not usable */ - public function __construct(ConfigCache $config, LoggerInterface $logger, Profiler $profiler, $isBackend = true) + public function __construct(Configuration $config, LoggerInterface $logger, Profiler $profiler, $isBackend = true) { $this->config = $config; $this->logger = $logger; @@ -358,21 +359,11 @@ class App */ public function reload() { - Core\Config::init($this->config); - Core\PConfig::init($this->config); - - $this->loadDatabase(); - $this->getMode()->determine($this->basePath); $this->determineURLPath(); if ($this->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - $adapterType = $this->config->get('system', 'config_adapter'); - $adapter = ConfigFactory::createConfig($adapterType, $this->config); - Core\Config::setAdapter($adapter); - $adapterP = ConfigFactory::createPConfig($adapterType, $this->config); - Core\PConfig::setAdapter($adapterP); Core\Config::load(); } @@ -383,7 +374,7 @@ class App Core\Hook::loadHooks(); $loader = new ConfigCacheLoader($this->basePath); Core\Hook::callAll('load_config', $loader); - $this->config->loadConfigArray($loader->loadCoreConfig('addon'), true); + $this->config->getCache()->load($loader->loadCoreConfig('addon'), true); } $this->loadDefaultTimezone(); @@ -453,49 +444,6 @@ class App } } - public function loadDatabase() - { - if (DBA::connected()) { - return; - } - - $db_host = $this->config->get('database', 'hostname'); - $db_user = $this->config->get('database', 'username'); - $db_pass = $this->config->get('database', 'password'); - $db_data = $this->config->get('database', 'database'); - $charset = $this->config->get('database', 'charset'); - - // Use environment variables for mysql if they are set beforehand - if (!empty(getenv('MYSQL_HOST')) - && !empty(getenv('MYSQL_USERNAME') || !empty(getenv('MYSQL_USER'))) - && getenv('MYSQL_PASSWORD') !== false - && !empty(getenv('MYSQL_DATABASE'))) - { - $db_host = getenv('MYSQL_HOST'); - if (!empty(getenv('MYSQL_PORT'))) { - $db_host .= ':' . getenv('MYSQL_PORT'); - } - if (!empty(getenv('MYSQL_USERNAME'))) { - $db_user = getenv('MYSQL_USERNAME'); - } else { - $db_user = getenv('MYSQL_USER'); - } - $db_pass = (string) getenv('MYSQL_PASSWORD'); - $db_data = getenv('MYSQL_DATABASE'); - } - - $stamp1 = microtime(true); - - if (DBA::connect($this->config, $this->profiler, $db_host, $db_user, $db_pass, $db_data, $charset)) { - // Loads DB_UPDATE_VERSION constant - Database\DBStructure::definition($this->basePath, false); - } - - unset($db_host, $db_user, $db_pass, $db_data, $charset); - - $this->profiler->saveTimestamp($stamp1, 'network', Core\System::callstack()); - } - public function getScheme() { return $this->scheme; diff --git a/src/Core/Config.php b/src/Core/Config.php index 559ee83ece..405d14d126 100644 --- a/src/Core/Config.php +++ b/src/Core/Config.php @@ -22,116 +22,76 @@ use Friendica\Core\Config\IConfigCache; class Config { /** - * @var Config\IConfigAdapter|null + * @var Config\Configuration */ - private static $adapter; + private static $config; /** - * @var Config\IConfigCache - */ - private static $cache; - - /** - * Initialize the config with only the cache + * Initialize the config * - * @param Config\IConfigCache $cache The configuration cache + * @param Config\Configuration $config */ - public static function init(Config\IConfigCache $cache) + public static function init(Config\Configuration $config) { - self::$cache = $cache; - } - - /** - * Add the adapter for DB-backend - * - * @param Config\IConfigAdapter $adapter - */ - public static function setAdapter(Config\IConfigAdapter $adapter) - { - self::$adapter = $adapter; + self::$config = $config; } /** * @brief Loads all configuration values of family into a cached storage. * - * All configuration values of the system are stored in the cache ( @see IConfigCache ) - * - * @param string $family The category of the configuration value + * @param string $cat The category of the configuration value * * @return void */ - public static function load($family = "config") + public static function load($cat = "config") { - if (!isset(self::$adapter) || !self::$adapter->isConnected()) { - return; - } - - self::$adapter->load($family); + self::$config->load($cat); } /** * @brief Get a particular user's config variable given the category name * ($family) and a key. * - * Get a particular config value from the given category ($family) - * and the $key from a cached storage either from the self::$adapter - * (@see IConfigAdapter ) or from the static::$cache (@see IConfigCache ). - * - * @param string $family The category of the configuration value + * @param string $cat The category of the configuration value * @param string $key The configuration key to query * @param mixed $default_value optional, The value to return if key is not set (default: null) * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false) * * @return mixed Stored value or null if it does not exist */ - public static function get($family, $key, $default_value = null, $refresh = false) + public static function get($cat, $key, $default_value = null, $refresh = false) { - if (!isset(self::$adapter) || !self::$adapter->isConnected()) { - return self::$cache->get($family, $key, $default_value); - } - - return self::$adapter->get($family, $key, $default_value, $refresh); + return self::$config->get($cat, $key, $default_value, $refresh); } /** * @brief Sets a configuration value for system config * - * Stores a config value ($value) in the category ($family) under the key ($key) + * 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 $family The category of the configuration value + * @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 */ - public static function set($family, $key, $value) + public static function set($cat, $key, $value) { - if (!isset(self::$adapter) || !self::$adapter->isConnected()) { - return self::$cache->set($family, $key, $value); - } - - return self::$adapter->set($family, $key, $value); + return self::$config->set($cat, $key, $value); } /** * @brief Deletes the given key from the system configuration. * - * Removes the configured value from the stored cache in self::$config - * (@see ConfigCache ) and removes it from the database (@see IConfigAdapter ). - * - * @param string $family The category of the configuration value + * @param string $cat The category of the configuration value * @param string $key The configuration key to delete * - * @return mixed + * @return bool */ - public static function delete($family, $key) + public static function delete($cat, $key) { - if (!isset(self::$adapter) || !self::$adapter->isConnected()) { - self::$cache->delete($family, $key); - } - - return self::$adapter->delete($family, $key); + return self::$config->delete($cat, $key); } } diff --git a/src/Core/Config/AbstractDbaConfigAdapter.php b/src/Core/Config/Adapter/AbstractDbaConfigAdapter.php similarity index 52% rename from src/Core/Config/AbstractDbaConfigAdapter.php rename to src/Core/Config/Adapter/AbstractDbaConfigAdapter.php index bae75122a3..770dfd2c95 100644 --- a/src/Core/Config/AbstractDbaConfigAdapter.php +++ b/src/Core/Config/Adapter/AbstractDbaConfigAdapter.php @@ -1,12 +1,19 @@ connected = DBA::connected(); + } + public function isConnected() { return $this->connected; diff --git a/src/Core/Config/IConfigAdapter.php b/src/Core/Config/Adapter/IConfigAdapter.php similarity index 59% rename from src/Core/Config/IConfigAdapter.php rename to src/Core/Config/Adapter/IConfigAdapter.php index 70e141484e..3bbbbbe94c 100644 --- a/src/Core/Config/IConfigAdapter.php +++ b/src/Core/Config/Adapter/IConfigAdapter.php @@ -1,6 +1,6 @@ !" if it does not exist */ - public function get($cat, $k, $default_value = null, $refresh = false); + public function get($cat, $key); /** * Stores a config value ($value) in the category ($family) under the key ($key) @@ -37,23 +35,23 @@ interface IConfigAdapter * Note: Please do not store booleans - convert to 0/1 integer values! * * @param string $cat The category of the configuration value - * @param string $k The configuration key to set + * @param string $key The configuration key to set * @param mixed $value The value to store * * @return bool Operation success */ - public function set($cat, $k, $value); + public function set($cat, $key, $value); /** * Removes the configured value from the stored cache * and removes it from the database. * * @param string $cat The category of the configuration value - * @param string $k The configuration key to delete + * @param string $key The configuration key to delete * * @return mixed */ - public function delete($cat, $k); + public function delete($cat, $key); /** * Checks, if the current adapter is connected to the backend diff --git a/src/Core/Config/IPConfigAdapter.php b/src/Core/Config/Adapter/IPConfigAdapter.php similarity index 65% rename from src/Core/Config/IPConfigAdapter.php rename to src/Core/Config/Adapter/IPConfigAdapter.php index e62fc9c93f..3e821efa02 100644 --- a/src/Core/Config/IPConfigAdapter.php +++ b/src/Core/Config/Adapter/IPConfigAdapter.php @@ -6,7 +6,7 @@ * and open the template in the editor. */ -namespace Friendica\Core\Config; +namespace Friendica\Core\Config\Adapter; /** * @@ -20,7 +20,7 @@ interface IPConfigAdapter * @param string $uid The user_id * @param string $cat The category of the configuration value * - * @return void + * @return array */ public function load($uid, $cat); @@ -30,13 +30,11 @@ interface IPConfigAdapter * * @param string $uid The user_id * @param string $cat The category of the configuration value - * @param string $k The configuration key to query - * @param mixed $default_value optional, The value to return if key is not set (default: null) - * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false) + * @param string $key The configuration key to query * - * @return mixed Stored value or null if it does not exist + * @return mixed Stored value or "!!" if it does not exist */ - public function get($uid, $cat, $k, $default_value = null, $refresh = false); + public function get($uid, $cat, $key); /** * Stores a config value ($value) in the category ($family) under the key ($key) @@ -46,12 +44,12 @@ interface IPConfigAdapter * * @param string $uid The user_id * @param string $cat The category of the configuration value - * @param string $k The configuration key to set + * @param string $key The configuration key to set * @param string $value The value to store * * @return bool Operation success */ - public function set($uid, $cat, $k, $value); + public function set($uid, $cat, $key, $value); /** * Removes the configured value from the stored cache @@ -59,9 +57,16 @@ interface IPConfigAdapter * * @param string $uid The user_id * @param string $cat The category of the configuration value - * @param string $k The configuration key to delete + * @param string $key The configuration key to delete * - * @return mixed + * @return bool */ - public function delete($uid, $cat, $k); + public function delete($uid, $cat, $key); + + /** + * Checks, if the current adapter is connected to the backend + * + * @return bool + */ + public function isConnected(); } diff --git a/src/Core/Config/Adapter/JITConfigAdapter.php b/src/Core/Config/Adapter/JITConfigAdapter.php new file mode 100644 index 0000000000..8dadfff688 --- /dev/null +++ b/src/Core/Config/Adapter/JITConfigAdapter.php @@ -0,0 +1,123 @@ + + */ +class JITConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter +{ + private $in_db; + + /** + * {@inheritdoc} + */ + public function load($cat = "config") + { + $return = []; + + if (!$this->isConnected()) { + return $return; + } + + // We don't preload "system" anymore. + // This reduces the number of database reads a lot. + if ($cat === 'system') { + return $return; + } + + $configs = DBA::select('config', ['v', 'k'], ['cat' => $cat]); + while ($config = DBA::fetch($configs)) { + $key = $config['k']; + + $return[$key] = $config['v']; + $this->in_db[$cat][$key] = true; + } + DBA::close($configs); + + return [$cat => $config]; + } + + /** + * {@inheritdoc} + */ + public function get($cat, $key) + { + if (!$this->isConnected()) { + return '!!'; + } + + $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]); + if (DBA::isResult($config)) { + // manage array value + $value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']); + + $this->in_db[$cat][$key] = true; + return $value; + } else { + + $this->in_db[$cat][$key] = false; + return '!!'; + } + } + + /** + * {@inheritdoc} + */ + public function set($cat, $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. + $dbvalue = (!is_array($value) ? (string)$value : $value); + + $stored = $this->get($cat, $key); + + if (!isset($this->in_db[$cat])) { + $this->in_db[$cat] = []; + } + if (!isset($this->in_db[$cat][$key])) { + $this->in_db[$cat][$key] = false; + } + + if (($stored === $dbvalue) && $this->in_db[$cat][$key]) { + return true; + } + + // manage array value + $dbvalue = (is_array($value) ? serialize($value) : $dbvalue); + + $result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true); + + $this->in_db[$cat][$key] = $result; + + return $result; + } + + /** + * {@inheritdoc} + */ + public function delete($cat, $key) + { + if (!$this->isConnected()) { + return false; + } + + if (isset($this->cache[$cat][$key])) { + unset($this->in_db[$cat][$key]); + } + + $result = DBA::delete('config', ['cat' => $cat, 'k' => $key]); + + return $result; + } +} diff --git a/src/Core/Config/Adapter/JITPConfigAdapter.php b/src/Core/Config/Adapter/JITPConfigAdapter.php new file mode 100644 index 0000000000..950dd58bd8 --- /dev/null +++ b/src/Core/Config/Adapter/JITPConfigAdapter.php @@ -0,0 +1,126 @@ + + */ +class JITPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdapter +{ + private $in_db; + + /** + * {@inheritdoc} + */ + public function load($uid, $cat) + { + $return = []; + + if (!$this->isConnected()) { + return $return; + } + + $pconfigs = DBA::select('pconfig', ['v', 'k'], ['cat' => $cat, 'uid' => $uid]); + if (DBA::isResult($pconfigs)) { + while ($pconfig = DBA::fetch($pconfigs)) { + $key = $pconfig['k']; + + $return[$key] = $pconfig['v']; + + $this->in_db[$uid][$cat][$key] = true; + } + } else if ($cat != 'config') { + // Negative caching + $return[null] = "!!"; + } + DBA::close($pconfigs); + + return [$cat => $return]; + } + + /** + * {@inheritdoc} + */ + public function get($uid, $cat, $key) + { + if (!$this->isConnected()) { + return null; + } + + $pconfig = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]); + if (DBA::isResult($pconfig)) { + // manage array value + $value = (preg_match("|^a:[0-9]+:{.*}$|s", $pconfig['v']) ? unserialize($pconfig['v']) : $pconfig['v']); + + $this->in_db[$uid][$cat][$key] = true; + return $value; + } else { + + $this->in_db[$uid][$cat][$key] = false; + return '!!'; + } + } + + /** + * {@inheritdoc} + */ + public function set($uid, $cat, $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. + $dbvalue = (!is_array($value) ? (string)$value : $value); + + $stored = $this->get($uid, $cat, $key); + + if (!isset($this->in_db[$uid])) { + $this->in_db[$uid] = []; + } + if (!isset($this->in_db[$uid][$cat])) { + $this->in_db[$uid][$cat] = []; + } + if (!isset($this->in_db[$uid][$cat][$key])) { + $this->in_db[$uid][$cat][$key] = false; + } + + if (($stored === $dbvalue) && $this->in_db[$uid][$cat][$key]) { + return true; + } + + // manage array value + $dbvalue = (is_array($value) ? serialize($value) : $dbvalue); + + $result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true); + + $this->in_db[$uid][$cat][$key] = $result; + + return $result; + } + + /** + * {@inheritdoc} + */ + public function delete($uid, $cat, $key) + { + if (!$this->isConnected()) { + return false; + } + + if (!empty($this->in_db[$uid][$cat][$key])) { + unset($this->in_db[$uid][$cat][$key]); + } + + $result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]); + + return $result; + } +} diff --git a/src/Core/Config/Adapter/PreloadConfigAdapter.php b/src/Core/Config/Adapter/PreloadConfigAdapter.php new file mode 100644 index 0000000000..8cad5c5557 --- /dev/null +++ b/src/Core/Config/Adapter/PreloadConfigAdapter.php @@ -0,0 +1,104 @@ + + */ +class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter +{ + private $config_loaded = false; + + /** + * {@inheritdoc} + */ + public function load($cat = 'config') + { + $return = []; + + if (!$this->isConnected()) { + return $return; + } + + if ($this->config_loaded) { + return $return; + } + + $configs = DBA::select('config', ['cat', 'v', 'k']); + while ($config = DBA::fetch($configs)) { + $return[$config['k']] = $config['v']; + } + DBA::close($configs); + + $this->config_loaded = true; + + return [$cat => $return]; + } + + /** + * {@inheritdoc} + */ + public function get($cat, $key) + { + if (!$this->isConnected()) { + return null; + } + + $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]); + if (DBA::isResult($config)) { + // manage array value + $value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']); + + return $value; + } else { + + return '!!'; + } + } + + /** + * {@inheritdoc} + */ + public function set($cat, $key, $value) + { + if (!$this->isConnected()) { + return false; + } + + // We store our setting values as strings. + // 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; + + if ($this->get($cat, $key) === $compare_value) { + return true; + } + + // manage array value + $dbvalue = is_array($value) ? serialize($value) : $value; + + $result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true); + + return $result; + } + + /** + * {@inheritdoc} + */ + public function delete($cat, $key) + { + if (!$this->isConnected()) { + return false; + } + + $result = DBA::delete('config', ['cat' => $cat, 'k' => $key]); + + return $result; + } +} diff --git a/src/Core/Config/Adapter/PreloadPConfigAdapter.php b/src/Core/Config/Adapter/PreloadPConfigAdapter.php new file mode 100644 index 0000000000..d117ed3542 --- /dev/null +++ b/src/Core/Config/Adapter/PreloadPConfigAdapter.php @@ -0,0 +1,126 @@ + + */ +class PreloadPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdapter +{ + private $config_loaded = false; + + /** + * @param int $uid The UID of the current user + */ + public function __construct($uid = null) + { + parent::__construct(); + + if (isset($uid)) { + $this->load($uid, 'config'); + } + } + + /** + * {@inheritdoc} + */ + public function load($uid, $cat) + { + $return = []; + + if ($this->config_loaded) { + return $return; + } + + if (empty($uid)) { + return $return; + } + + $pconfigs = DBA::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]); + while ($pconfig = DBA::fetch($pconfigs)) { + $return[$pconfig['k']] = $pconfig['v']; + } + DBA::close($pconfigs); + + $this->config_loaded = true; + + return [$cat => $return]; + } + + /** + * {@inheritdoc} + */ + public function get($uid, $cat, $key) + { + if (!$this->isConnected()) { + return null; + } + + if (!$this->config_loaded) { + $this->load($uid, $cat); + } + + $config = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]); + if (DBA::isResult($config)) { + // manage array value + $value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']); + + return $value; + } else { + return '!!'; + } + } + + /** + * {@inheritdoc} + */ + public function set($uid, $cat, $key, $value) + { + if (!$this->isConnected()) { + return false; + } + + if (!$this->config_loaded) { + $this->load($uid, $cat); + } + // We store our setting values as strings. + // 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; + + if ($this->get($uid, $cat, $key) === $compare_value) { + return true; + } + + // manage array value + $dbvalue = is_array($value) ? serialize($value) : $value; + + $result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true); + + return $result; + } + + /** + * {@inheritdoc} + */ + public function delete($uid, $cat, $key) + { + if (!$this->isConnected()) { + return false; + } + + if (!$this->config_loaded) { + $this->load($uid, $cat); + } + + $result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]); + + return $result; + } +} diff --git a/src/Core/Config/ConfigCache.php b/src/Core/Config/Cache/ConfigCache.php similarity index 56% rename from src/Core/Config/ConfigCache.php rename to src/Core/Config/Cache/ConfigCache.php index b86ec3860a..b1172c0c82 100644 --- a/src/Core/Config/ConfigCache.php +++ b/src/Core/Config/Cache/ConfigCache.php @@ -1,6 +1,6 @@ loadConfigArray($config); + $this->load($config); } /** - * Tries to load the specified configuration array into the App->config array. - * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config. - * - * @param array $config - * @param bool $overwrite Force value overwrite if the config key already exists + * {@inheritdoc} */ - public function loadConfigArray(array $config, $overwrite = false) + public function load(array $config, $overwrite = false) { - foreach ($config as $category => $values) { - foreach ($values as $key => $value) { - if ($overwrite) { - $this->set($category, $key, $value); - } else { - $this->setDefault($category, $key, $value); + $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) { + if (isset($config[$category][$key])) { + if ($overwrite) { + $this->set($category, $key, $config[$category][$key]); + } else { + $this->setDefault($category, $key, $config[$category][$key]); + } + } } } } @@ -44,23 +51,22 @@ class ConfigCache implements IConfigCache, IPConfigCache /** * {@inheritdoc} */ - public function get($cat, $key = null, $default = null) + public function get($cat, $key = null) { - $return = $default; - - if ($cat === 'config') { - if (isset($this->config[$key])) { - $return = $this->config[$key]; - } + if (isset($this->config[$cat][$key])) { + return $this->config[$cat][$key]; } else { - if (isset($this->config[$cat][$key])) { - $return = $this->config[$cat][$key]; - } elseif ($key == null && isset($this->config[$cat])) { - $return = $this->config[$cat]; - } + return '!!'; } + } - return $return; + /** + * {@inheritdoc} + */ + public function has($cat, $key = null) + { + return isset($this->config[$cat][$key]) + && $this->config[$cat][$key] !== '!!'; } /** @@ -85,34 +91,48 @@ class ConfigCache implements IConfigCache, IPConfigCache // Only arrays are serialized in database, so we have to unserialize sparingly $value = is_string($value) && preg_match("|^a:[0-9]+:{.*}$|s", $value) ? unserialize($value) : $value; - if ($cat === 'config') { - $this->config[$key] = $value; - } else { - if (!isset($this->config[$cat])) { - $this->config[$cat] = []; - } - - $this->config[$cat][$key] = $value; + if (!isset($this->config[$cat])) { + $this->config[$cat] = []; } + $this->config[$cat][$key] = $value; + return true; } + /** + * {@inheritdoc} + */ + public function hasP($uid, $cat, $key = null) + { + return isset($this->config[$uid][$cat][$key]) + && $this->config[$uid][$cat][$key] !== '!!'; + } + /** * {@inheritdoc} */ public function delete($cat, $key) { - if ($cat === 'config') { - if (isset($this->config[$key])) { - unset($this->config[$key]); + if (isset($this->config[$cat][$key])) { + unset($this->config[$cat][$key]); + if (count($this->config[$cat]) == 0) { + unset($this->config[$cat]); } + return true; } else { - if (isset($this->config[$cat][$key])) { - unset($this->config[$cat][$key]); - if (count($this->config[$cat]) == 0) { - unset($this->config[$cat]); - } + return false; + } + } + + /** + * {@inheritdoc} + */ + public function loadP($uid, array $config) + { + foreach ($config as $category => $values) { + foreach ($values as $key => $value) { + $this->setP($uid, $category, $key, $value); } } } @@ -120,17 +140,13 @@ class ConfigCache implements IConfigCache, IPConfigCache /** * {@inheritdoc} */ - public function getP($uid, $cat, $key = null, $default = null) + public function getP($uid, $cat, $key = null) { - $return = $default; - if (isset($this->config[$uid][$cat][$key])) { - $return = $this->config[$uid][$cat][$key]; - } elseif ($key === null && isset($this->config[$uid][$cat])) { - $return = $this->config[$uid][$cat]; + return $this->config[$uid][$cat][$key]; + } else { + return '!!'; } - - return $return; } /** @@ -145,15 +161,13 @@ class ConfigCache implements IConfigCache, IPConfigCache $this->config[$uid] = []; } - if (!isset($this->config[$uid][$cat]) || !is_array($this->config[$uid][$cat])) { + if (!isset($this->config[$uid][$cat])) { $this->config[$uid][$cat] = []; } - if ($key === null) { - $this->config[$uid][$cat] = $value; - } else { - $this->config[$uid][$cat][$key] = $value; - } + $this->config[$uid][$cat][$key] = $value; + + return true; } /** @@ -169,6 +183,10 @@ class ConfigCache implements IConfigCache, IPConfigCache unset($this->config[$uid]); } } + + return true; + } else { + return false; } } diff --git a/src/Core/Config/ConfigCacheLoader.php b/src/Core/Config/Cache/ConfigCacheLoader.php similarity index 93% rename from src/Core/Config/ConfigCacheLoader.php rename to src/Core/Config/Cache/ConfigCacheLoader.php index 3a6a3c803e..b728d10821 100644 --- a/src/Core/Config/ConfigCacheLoader.php +++ b/src/Core/Config/Cache/ConfigCacheLoader.php @@ -1,6 +1,6 @@ set('system', 'basepath', $this->baseDir); - $config->loadConfigArray($this->loadCoreConfig('defaults')); - $config->loadConfigArray($this->loadCoreConfig('settings')); + $config->load($this->loadCoreConfig('defaults')); + $config->load($this->loadCoreConfig('settings')); - $config->loadConfigArray($this->loadLegacyConfig('htpreconfig'), true); - $config->loadConfigArray($this->loadLegacyConfig('htconfig'), true); + $config->load($this->loadLegacyConfig('htpreconfig'), true); + $config->load($this->loadLegacyConfig('htconfig'), true); - $config->loadConfigArray($this->loadCoreConfig('local'), true); + $config->load($this->loadCoreConfig('local'), true); } /** diff --git a/src/Core/Config/Cache/IConfigCache.php b/src/Core/Config/Cache/IConfigCache.php new file mode 100644 index 0000000000..9d948527d4 --- /dev/null +++ b/src/Core/Config/Cache/IConfigCache.php @@ -0,0 +1,65 @@ +!' if not set + */ + function get($cat, $key = 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 + * + * @return bool True, if the value is set + */ + function set($cat, $key, $value); + + /** + * Deletes a value from the config cache. + * + * @param string $cat Config category + * @param string $key Config key + * + * @return bool true, if deleted + */ + function delete($cat, $key); + + /** + * Checks if a value is set in the config cache. + * + * @param string $cat Config category + * @param string $key Config key + * @return bool + */ + function has($cat, $key = null); + + /** + * Returns the whole configuration cache + * + * @return array + */ + function getAll(); +} diff --git a/src/Core/Config/Cache/IPConfigCache.php b/src/Core/Config/Cache/IPConfigCache.php new file mode 100644 index 0000000000..4ac21481a1 --- /dev/null +++ b/src/Core/Config/Cache/IPConfigCache.php @@ -0,0 +1,70 @@ +!' if not set + */ + function getP($uid, $cat, $key = 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 + */ + function setP($uid, $cat, $key, $value); + + /** + * 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 + */ + function deleteP($uid, $cat, $key); + + + /** + * Checks if a value is set in the user config cache. + * + * @param int $uid User Id + * @param string $cat Config category + * @param string $key Config key + * @return bool + */ + function hasP($uid, $cat, $key = null); + + /** + * Returns the whole configuration cache + * + * @return array + */ + function getAll(); +} diff --git a/src/Core/Config/Configuration.php b/src/Core/Config/Configuration.php new file mode 100644 index 0000000000..ccb9abda8a --- /dev/null +++ b/src/Core/Config/Configuration.php @@ -0,0 +1,154 @@ +configCache = $configCache; + $this->configAdapter = $configAdapter; + + $this->load(); + } + + /** + * Returns the Config Cache + * + * @return Cache\IConfigCache + */ + public function getCache() + { + return $this->configCache; + } + + /** + * @brief Loads all configuration values of family into a cached storage. + * + * All configuration values of the system are stored in the cache ( @see IConfigCache ) + * + * @param string $cat The category of the configuration value + * + * @return void + */ + public function load($cat = 'config') + { + // If not connected, do nothing + if (!$this->configAdapter->isConnected()) { + return; + } + + // load the whole category out of the DB into the cache + $this->configCache->load($this->configAdapter->load($cat), true); + } + + /** + * @brief Get a particular user's config variable given the category name + * ($cat) and a $key. + * + * Get a particular config value from the given category ($cat) + * and the $key from a cached storage either from the $this->configAdapter + * (@see IConfigAdapter ) or from the $this->configCache (@see IConfigCache ). + * + * @param string $cat The category of the configuration value + * @param string $key The configuration key to query + * @param mixed $default_value optional, The value to return if key is not set (default: null) + * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false) + * + * @return mixed Stored value or null if it does not exist + */ + public function get($cat, $key, $default_value = null, $refresh = false) + { + // Return the value of the cache if found and no refresh is forced + if (!$refresh && $this->configCache->has($cat, $key)) { + return $this->configCache->get($cat, $key); + } + + // if we don't find the value in the cache and the adapter isn't ready, return the default value + if (!$this->configAdapter->isConnected()) { + return $default_value; + } + + // load DB value to cache + $dbvalue = $this->configAdapter->get($cat, $key); + + if ($dbvalue !== '!!') { + $this->configCache->set($cat, $key, $dbvalue); + return $dbvalue; + } else { + return $default_value; + } + } + + /** + * @brief Sets a configuration value for system config + * + * 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 + */ + public function set($cat, $key, $value) + { + // set the cache first + $cached = $this->configCache->set($cat, $key, $value); + + // If there is no connected adapter, we're finished + if (!$this->configAdapter->isConnected()) { + return $cached; + } + + $stored = $this->configAdapter->set($cat, $key, $value); + + return $cached && $stored; + } + + /** + * @brief Deletes the given key from the system configuration. + * + * Removes the configured value from the stored cache in $this->configCache + * (@see ConfigCache ) and removes it from the database (@see IConfigAdapter ). + * + * @param string $cat The category of the configuration value + * @param string $key The configuration key to delete + * + * @return bool + */ + public function delete($cat, $key) + { + $cacheRemoved = $this->configCache->delete($cat, $key); + + if (!$this->configAdapter->isConnected()) { + return $cacheRemoved; + } + + $storeRemoved = $this->configAdapter->delete($cat, $key); + + return $cacheRemoved || $storeRemoved; + } +} diff --git a/src/Core/Config/IConfigCache.php b/src/Core/Config/IConfigCache.php deleted file mode 100644 index 898e3c0f86..0000000000 --- a/src/Core/Config/IConfigCache.php +++ /dev/null @@ -1,39 +0,0 @@ - - */ -class JITConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter -{ - private $cache; - private $in_db; - - /** - * @var IConfigCache The config cache of this driver - */ - private $configCache; - - /** - * @param IConfigCache $configCache The config cache of this driver - */ - public function __construct(IConfigCache $configCache) - { - $this->configCache = $configCache; - $this->connected = DBA::connected(); - } - - /** - * {@inheritdoc} - */ - public function load($cat = "config") - { - if (!$this->isConnected()) { - return; - } - - // We don't preload "system" anymore. - // This reduces the number of database reads a lot. - if ($cat === 'system') { - return; - } - - $configs = DBA::select('config', ['v', 'k'], ['cat' => $cat]); - while ($config = DBA::fetch($configs)) { - $k = $config['k']; - - $this->configCache->set($cat, $k, $config['v']); - - if ($cat !== 'config') { - $this->cache[$cat][$k] = $config['v']; - $this->in_db[$cat][$k] = true; - } - } - DBA::close($configs); - } - - /** - * {@inheritdoc} - */ - public function get($cat, $k, $default_value = null, $refresh = false) - { - if (!$this->isConnected()) { - return $default_value; - } - - if (!$refresh) { - // Do we have the cached value? Then return it - if (isset($this->cache[$cat][$k])) { - if ($this->cache[$cat][$k] === '!!') { - return $default_value; - } else { - return $this->cache[$cat][$k]; - } - } - } - - $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $k]); - if (DBA::isResult($config)) { - // manage array value - $value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']); - - // Assign the value from the database to the cache - $this->cache[$cat][$k] = $value; - $this->in_db[$cat][$k] = true; - return $value; - } elseif ($this->configCache->get($cat, $k) !== null) { - // Assign the value (mostly) from config/local.config.php file to the cache - $this->cache[$cat][$k] = $this->configCache->get($cat, $k); - $this->in_db[$cat][$k] = false; - - return $this->configCache->get($cat, $k); - } elseif ($this->configCache->get('config', $k) !== null) { - // Assign the value (mostly) from config/local.config.php file to the cache - $this->cache[$k] = $this->configCache->get('config', $k); - $this->in_db[$k] = false; - - return $this->configCache->get('config', $k); - } - - $this->cache[$cat][$k] = '!!'; - $this->in_db[$cat][$k] = false; - - return $default_value; - } - - /** - * {@inheritdoc} - */ - public function set($cat, $k, $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. - $dbvalue = (!is_array($value) ? (string)$value : $value); - - $stored = $this->get($cat, $k, null, true); - - if (!isset($this->in_db[$cat])) { - $this->in_db[$cat] = []; - } - if (!isset($this->in_db[$cat][$k])) { - $this->in_db[$cat] = false; - } - - if (($stored === $dbvalue) && $this->in_db[$cat][$k]) { - return true; - } - - $this->configCache->set($cat, $k, $value); - - // Assign the just added value to the cache - $this->cache[$cat][$k] = $dbvalue; - - // manage array value - $dbvalue = (is_array($value) ? serialize($value) : $dbvalue); - - $result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $k], true); - - if ($result) { - $this->in_db[$cat][$k] = true; - } - - return $result; - } - - /** - * {@inheritdoc} - */ - public function delete($cat, $k) - { - if (!$this->isConnected()) { - return false; - } - - if (isset($this->cache[$cat][$k])) { - unset($this->cache[$cat][$k]); - unset($this->in_db[$cat][$k]); - } - - $result = DBA::delete('config', ['cat' => $cat, 'k' => $k]); - - return $result; - } -} diff --git a/src/Core/Config/JITPConfigAdapter.php b/src/Core/Config/JITPConfigAdapter.php deleted file mode 100644 index b1a15601cc..0000000000 --- a/src/Core/Config/JITPConfigAdapter.php +++ /dev/null @@ -1,136 +0,0 @@ - - */ -class JITPConfigAdapter implements IPConfigAdapter -{ - private $in_db; - - /** - * The config cache of this adapter - * @var IPConfigCache - */ - private $configCache; - - /** - * @param IPConfigCache $configCache The config cache of this adapter - */ - public function __construct(IPConfigCache $configCache) - { - $this->configCache = $configCache; - } - - /** - * {@inheritdoc} - */ - public function load($uid, $cat) - { - $pconfigs = DBA::select('pconfig', ['v', 'k'], ['cat' => $cat, 'uid' => $uid]); - if (DBA::isResult($pconfigs)) { - while ($pconfig = DBA::fetch($pconfigs)) { - $k = $pconfig['k']; - - $this->configCache->setP($uid, $cat, $k, $pconfig['v']); - - $this->in_db[$uid][$cat][$k] = true; - } - } else if ($cat != 'config') { - // Negative caching - $this->configCache->setP($uid, $cat, null, "!!"); - } - DBA::close($pconfigs); - } - - /** - * {@inheritdoc} - */ - public function get($uid, $cat, $k, $default_value = null, $refresh = false) - { - if (!$refresh) { - // Looking if the whole family isn't set - if ($this->configCache->getP($uid, $cat) !== null) { - if ($this->configCache->getP($uid, $cat) === '!!') { - return $default_value; - } - } - - if ($this->configCache->getP($uid, $cat, $k) !== null) { - if ($this->configCache->getP($uid, $cat, $k) === '!!') { - return $default_value; - } - return $this->configCache->getP($uid, $cat, $k); - } - } - - $pconfig = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $k]); - if (DBA::isResult($pconfig)) { - $val = (preg_match("|^a:[0-9]+:{.*}$|s", $pconfig['v']) ? unserialize($pconfig['v']) : $pconfig['v']); - - $this->configCache->setP($uid, $cat, $k, $val); - - $this->in_db[$uid][$cat][$k] = true; - - return $val; - } else { - $this->configCache->setP($uid, $cat, $k, '!!'); - - $this->in_db[$uid][$cat][$k] = false; - - return $default_value; - } - } - - /** - * {@inheritdoc} - */ - public function set($uid, $cat, $k, $value) - { - // 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. - $dbvalue = (!is_array($value) ? (string)$value : $value); - - $stored = $this->get($uid, $cat, $k, null, true); - - if (($stored === $dbvalue) && $this->in_db[$uid][$cat][$k]) { - return true; - } - - $this->configCache->setP($uid, $cat, $k, $value); - - // manage array value - $dbvalue = (is_array($value) ? serialize($value) : $dbvalue); - - $result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $k], true); - - if ($result) { - $this->in_db[$uid][$cat][$k] = true; - } - - return $result; - } - - /** - * {@inheritdoc} - */ - public function delete($uid, $cat, $k) - { - $this->configCache->deleteP($uid, $cat, $k); - - if (!empty($this->in_db[$uid][$cat][$k])) { - unset($this->in_db[$uid][$cat][$k]); - } - - $result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $k]); - - return $result; - } -} diff --git a/src/Core/Config/PConfiguration.php b/src/Core/Config/PConfiguration.php new file mode 100644 index 0000000000..d3c848c9db --- /dev/null +++ b/src/Core/Config/PConfiguration.php @@ -0,0 +1,150 @@ +configCache = $configCache; + $this->configAdapter = $configAdapter; + } + + /** + * @brief Loads all configuration values of a user's config family into a cached storage. + * + * All configuration values of the given user are stored with the $uid in + * the cache ( @see IPConfigCache ) + * + * @param string $uid The user_id + * @param string $cat The category of the configuration value + * + * @return void + */ + public function load($uid, $cat = 'config') + { + // If not connected, do nothing + if (!$this->configAdapter->isConnected()) { + return; + } + + // load the whole category out of the DB into the cache + $this->configCache->loadP($uid, $this->configAdapter->load($uid, $cat)); + } + + /** + * @brief Get a particular user's config variable given the category name + * ($cat) and a key. + * + * Get a particular user's config value from the given category ($cat) + * and the $key with the $uid from a cached storage either from the $this->configAdapter + * (@see IConfigAdapter ) or from the $this->configCache (@see IConfigCache ). + * + * @param string $uid The user_id + * @param string $cat The category of the configuration value + * @param string $key The configuration key to query + * @param mixed $default_value optional, The value to return if key is not set (default: null) + * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false) + * + * @return mixed Stored value or null if it does not exist + */ + public function get($uid, $cat, $key, $default_value = null, $refresh = false) + { + // Return the value of the cache if found and no refresh is forced + if (!$refresh && $this->configCache->hasP($uid, $cat, $key)) { + return $this->configCache->getP($uid, $cat, $key); + } + + // if we don't find the value in the cache and the adapter isn't ready, return the default value + if (!$this->configAdapter->isConnected()) { + return $default_value; + } + + // load DB value to cache + $dbvalue = $this->configAdapter->get($uid, $cat, $key); + + if ($dbvalue !== '!!') { + $this->configCache->setP($uid, $cat, $key, $dbvalue); + return $dbvalue; + } else { + return $default_value; + } + } + + /** + * @brief Sets a configuration value for a user + * + * Stores a config value ($value) in the category ($family) under the key ($key) + * for the user_id $uid. + * + * @note Please do not store booleans - convert to 0/1 integer values! + * + * @param string $uid The user_id + * @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 + */ + public function set($uid, $cat, $key, $value) + { + // set the cache first + $cached = $this->configCache->setP($uid, $cat, $key, $value); + + // If there is no connected adapter, we're finished + if (!$this->configAdapter->isConnected()) { + return $cached; + } + + $stored = $this->configAdapter->set($uid, $cat, $key, $value); + + return $cached && $stored; + } + + /** + * @brief Deletes the given key from the users's configuration. + * + * Removes the configured value from the stored cache in $this->configCache + * (@see ConfigCache ) and removes it from the database (@see IConfigAdapter ) + * with the given $uid. + * + * @param string $uid The user_id + * @param string $cat The category of the configuration value + * @param string $key The configuration key to delete + * + * @return bool + */ + public function delete($uid, $cat, $key) + { + $cacheRemoved = $this->configCache->deleteP($uid, $cat, $key); + + if (!$this->configAdapter->isConnected()) { + return $cacheRemoved; + } + + $storeRemoved = $this->configAdapter->delete($uid, $cat, $key); + + return $cacheRemoved || $storeRemoved; + } +} diff --git a/src/Core/Config/PreloadConfigAdapter.php b/src/Core/Config/PreloadConfigAdapter.php deleted file mode 100644 index 96331e7a2c..0000000000 --- a/src/Core/Config/PreloadConfigAdapter.php +++ /dev/null @@ -1,123 +0,0 @@ - - */ -class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter -{ - private $config_loaded = false; - - /** - * @var IConfigCache The config cache of this driver - */ - private $configCache; - - /** - * @param IConfigCache $configCache The config cache of this driver - */ - public function __construct(IConfigCache $configCache) - { - $this->configCache = $configCache; - $this->connected = DBA::connected(); - $this->load(); - } - - /** - * {@inheritdoc} - */ - public function load($family = 'config') - { - if (!$this->isConnected()) { - return; - } - - if ($this->config_loaded) { - return; - } - - $configs = DBA::select('config', ['cat', 'v', 'k']); - while ($config = DBA::fetch($configs)) { - $this->configCache->set($config['cat'], $config['k'], $config['v']); - } - DBA::close($configs); - - $this->config_loaded = true; - } - - /** - * {@inheritdoc} - */ - public function get($cat, $k, $default_value = null, $refresh = false) - { - if (!$this->isConnected()) { - return $default_value; - } - - if ($refresh) { - $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $k]); - if (DBA::isResult($config)) { - $this->configCache->set($cat, $k, $config['v']); - } - } - - $return = $this->configCache->get($cat, $k, $default_value); - - return $return; - } - - /** - * {@inheritdoc} - */ - public function set($cat, $k, $value) - { - if (!$this->isConnected()) { - return false; - } - - // We store our setting values as strings. - // 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; - - if ($this->configCache->get($cat, $k) === $compare_value) { - return true; - } - - $this->configCache->set($cat, $k, $value); - - // manage array value - $dbvalue = is_array($value) ? serialize($value) : $value; - - $result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $k], true); - if (!$result) { - throw new Exception('Unable to store config value in [' . $cat . '][' . $k . ']'); - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function delete($cat, $k) - { - if (!$this->isConnected()) { - return false; - } - - $this->configCache->delete($cat, $k); - - $result = DBA::delete('config', ['cat' => $cat, 'k' => $k]); - - return $result; - } -} diff --git a/src/Core/Config/PreloadPConfigAdapter.php b/src/Core/Config/PreloadPConfigAdapter.php deleted file mode 100644 index af97815ade..0000000000 --- a/src/Core/Config/PreloadPConfigAdapter.php +++ /dev/null @@ -1,125 +0,0 @@ - - */ -class PreloadPConfigAdapter implements IPConfigAdapter -{ - private $config_loaded = false; - - /** - * The config cache of this adapter - * @var IPConfigCache - */ - private $configCache; - - /** - * @param IPConfigCache $configCache The config cache of this adapter - * @param int $uid The UID of the current user - */ - public function __construct(IPConfigCache $configCache, $uid = null) - { - $this->configCache = $configCache; - if (isset($uid)) { - $this->load($uid, 'config'); - } - } - - /** - * {@inheritdoc} - */ - public function load($uid, $family) - { - if ($this->config_loaded) { - return; - } - - if (empty($uid)) { - return; - } - - $pconfigs = DBA::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]); - while ($pconfig = DBA::fetch($pconfigs)) { - $this->configCache->setP($uid, $pconfig['cat'], $pconfig['k'], $pconfig['v']); - } - DBA::close($pconfigs); - - $this->config_loaded = true; - } - - /** - * {@inheritdoc} - */ - public function get($uid, $cat, $k, $default_value = null, $refresh = false) - { - if (!$this->config_loaded) { - $this->load($uid, $cat); - } - - if ($refresh) { - $config = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $k]); - if (DBA::isResult($config)) { - $this->configCache->setP($uid, $cat, $k, $config['v']); - } else { - $this->configCache->deleteP($uid, $cat, $k); - } - } - - return $this->configCache->getP($uid, $cat, $k, $default_value);; - } - - /** - * {@inheritdoc} - */ - public function set($uid, $cat, $k, $value) - { - if (!$this->config_loaded) { - $this->load($uid, $cat); - } - // We store our setting values as strings. - // 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; - - if ($this->configCache->getP($uid, $cat, $k) === $compare_value) { - return true; - } - - $this->configCache->setP($uid, $cat, $k, $value); - - // manage array value - $dbvalue = is_array($value) ? serialize($value) : $value; - - $result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $k], true); - if (!$result) { - throw new Exception('Unable to store config value in [' . $uid . '][' . $cat . '][' . $k . ']'); - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function delete($uid, $cat, $k) - { - if (!$this->config_loaded) { - $this->load($uid, $cat); - } - - $this->configCache->deleteP($uid, $cat, $k); - - $result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $k]); - - return $result; - } -} diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php index d5c63dd990..682d109712 100644 --- a/src/Core/Console/AutomaticInstallation.php +++ b/src/Core/Console/AutomaticInstallation.php @@ -100,10 +100,10 @@ HELP; } } - $db_host = $a->getConfig()->get('database', 'hostname'); - $db_user = $a->getConfig()->get('database', 'username'); - $db_pass = $a->getConfig()->get('database', 'password'); - $db_data = $a->getConfig()->get('database', 'database'); + $db_host = $a->getConfigCache()->get('database', 'hostname'); + $db_user = $a->getConfigCache()->get('database', 'username'); + $db_pass = $a->getConfigCache()->get('database', 'password'); + $db_data = $a->getConfigCache()->get('database', 'database'); } else { // Creating config file $this->out("Creating config file...\n"); @@ -146,7 +146,7 @@ HELP; $installer->resetChecks(); - if (!$installer->checkDB($a->getConfig(), $a->getProfiler(), $db_host, $db_user, $db_pass, $db_data)) { + if (!$installer->checkDB($a->getConfigCache(), $a->getProfiler(), $db_host, $db_user, $db_pass, $db_data)) { $errorMessage = $this->extractErrors($installer->getChecks()); throw new RuntimeException($errorMessage); } diff --git a/src/Core/Console/Config.php b/src/Core/Console/Config.php index b1c3df54e0..cf5c09fc0a 100644 --- a/src/Core/Console/Config.php +++ b/src/Core/Console/Config.php @@ -124,9 +124,9 @@ HELP; $cat = $this->getArgument(0); Core\Config::load($cat); - if ($a->getConfig()->get($cat) !== null) { + if ($a->getConfigCache()->get($cat) !== null) { $this->out("[{$cat}]"); - $catVal = $a->getConfig()->get($cat); + $catVal = $a->getConfigCache()->get($cat); foreach ($catVal as $key => $value) { if (is_array($value)) { foreach ($value as $k => $v) { @@ -148,7 +148,7 @@ HELP; $this->out('Warning: The JIT (Just In Time) Config adapter doesn\'t support loading the entire configuration, showing file config only'); } - $config = $a->getConfig()->getAll(); + $config = $a->getConfigCache()->getAll(); foreach ($config as $cat => $section) { if (is_array($section)) { foreach ($section as $key => $value) { diff --git a/src/Core/Console/Typo.php b/src/Core/Console/Typo.php index 32ba6ded35..8d07051e83 100644 --- a/src/Core/Console/Typo.php +++ b/src/Core/Console/Typo.php @@ -43,7 +43,7 @@ HELP; throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); } - $php_path = BaseObject::getApp()->getConfig()->get('config', 'php_path', 'php'); + $php_path = BaseObject::getApp()->getConfigCache()->get('config', 'php_path', 'php'); if ($this->getOption('v')) { $this->out('Directory: src'); diff --git a/src/Core/Installer.php b/src/Core/Installer.php index dd9e3d22e9..73f85785e7 100644 --- a/src/Core/Installer.php +++ b/src/Core/Installer.php @@ -6,7 +6,7 @@ namespace Friendica\Core; use DOMDocument; use Exception; -use Friendica\Core\Config\ConfigCache; +use Friendica\Core\Config\Cache\IConfigCache; use Friendica\Database\DBA; use Friendica\Database\DBStructure; use Friendica\Object\Image; @@ -583,7 +583,7 @@ class Installer /** * Checking the Database connection and if it is available for the current installation * - * @param ConfigCache $configCache The configuration cache + * @param IConfigCache $configCache The configuration cache * @param Profiler $profiler The profiler of this app * @param string $dbhost Hostname/IP of the Friendica Database * @param string $dbuser Username of the Database connection credentials @@ -593,7 +593,7 @@ class Installer * @return bool true if the check was successful, otherwise false * @throws Exception */ - public function checkDB(ConfigCache $configCache, Profiler $profiler, $dbhost, $dbuser, $dbpass, $dbdata) + public function checkDB(IConfigCache $configCache, Profiler $profiler, $dbhost, $dbuser, $dbpass, $dbdata) { if (!DBA::connect($configCache, $profiler, $dbhost, $dbuser, $dbpass, $dbdata)) { $this->addCheck(L10n::t('Could not connect to database.'), false, true, ''); diff --git a/src/Core/PConfig.php b/src/Core/PConfig.php index df024f0f34..f62b59f476 100644 --- a/src/Core/PConfig.php +++ b/src/Core/PConfig.php @@ -18,123 +18,78 @@ namespace Friendica\Core; class PConfig { /** - * @var Config\IPConfigAdapter + * @var Config\PConfiguration */ - private static $adapter; - - /** - * @var Config\IPConfigCache - */ - private static $cache; + private static $config; /** * Initialize the config with only the cache * - * @param Config\IPConfigCache $cache The configuration cache + * @param Config\PConfiguration $config The configuration cache */ - public static function init(Config\IPConfigCache $cache) + public static function init(Config\PConfiguration $config) { - self::$cache = $cache; - } - - /** - * Add the adapter for DB-backend - * - * @param Config\IPConfigAdapter $adapter - */ - public static function setAdapter(Config\IPConfigAdapter $adapter) - { - self::$adapter = $adapter; + self::$config = $config; } /** * @brief Loads all configuration values of a user's config family into a cached storage. * - * All configuration values of the given user are stored with the $uid in - * the cache ( @see IPConfigCache ) - * - * @param string $uid The user_id - * @param string $family The category of the configuration value + * @param string $uid The user_id + * @param string $cat The category of the configuration value * * @return void */ - public static function load($uid, $family) + public static function load($uid, $cat) { - if (!isset(self::$adapter)) { - return; - } - - self::$adapter->load($uid, $family); + self::$config->load($uid, $cat); } /** * @brief Get a particular user's config variable given the category name - * ($family) and a key. - * - * Get a particular user's config value from the given category ($family) - * and the $key with the $uid from a cached storage either from the self::$adapter - * (@see IConfigAdapter ) or from the static::$cache (@see IConfigCache ). + * ($cat) and a key. * * @param string $uid The user_id - * @param string $family The category of the configuration value + * @param string $cat The category of the configuration value * @param string $key The configuration key to query * @param mixed $default_value optional, The value to return if key is not set (default: null) * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false) * * @return mixed Stored value or null if it does not exist */ - public static function get($uid, $family, $key, $default_value = null, $refresh = false) + public static function get($uid, $cat, $key, $default_value = null, $refresh = false) { - if (!isset(self::$adapter)) { - return self::$cache->getP($uid, $family, $key, $default_value); - } - - return self::$adapter->get($uid, $family, $key, $default_value, $refresh); + return self::$config->get($uid, $cat, $key, $default_value, $refresh); } /** * @brief Sets a configuration value for a user * - * Stores a config value ($value) in the category ($family) under the key ($key) - * for the user_id $uid. - * * @note Please do not store booleans - convert to 0/1 integer values! * * @param string $uid The user_id - * @param string $family The category of the configuration value + * @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 */ - public static function set($uid, $family, $key, $value) + public static function set($uid, $cat, $key, $value) { - if (!isset(self::$adapter)) { - return self::$cache->setP($uid, $family, $key, $value); - } - - return self::$adapter->set($uid, $family, $key, $value); + return self::$config->set($uid, $cat, $key, $value); } /** * @brief Deletes the given key from the users's configuration. * - * Removes the configured value from the stored cache in self::$config - * (@see ConfigCache ) and removes it from the database (@see IConfigAdapter ) - * with the given $uid. + * @param string $uid The user_id + * @param string $cat The category of the configuration value + * @param string $key The configuration key to delete * - * @param string $uid The user_id - * @param string $family The category of the configuration value - * @param string $key The configuration key to delete - * - * @return mixed + * @return bool */ - public static function delete($uid, $family, $key) + public static function delete($uid, $cat, $key) { - if (!isset(self::$adapter)) { - return self::$cache->deleteP($uid, $family, $key); - } - - return self::$adapter->delete($uid, $family, $key); + return self::$config->delete($uid, $cat, $key); } } diff --git a/src/Database/DBA.php b/src/Database/DBA.php index edef309015..1c17d9aca5 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -2,7 +2,7 @@ namespace Friendica\Database; -use Friendica\Core\Config\IConfigCache; +use Friendica\Core\Config\Cache\IConfigCache; use Friendica\Core\Logger; use Friendica\Core\System; use Friendica\Util\DateTimeFormat; diff --git a/src/Factory/ConfigFactory.php b/src/Factory/ConfigFactory.php index 269daea8b8..6a30cf0e05 100644 --- a/src/Factory/ConfigFactory.php +++ b/src/Factory/ConfigFactory.php @@ -2,51 +2,66 @@ namespace Friendica\Factory; +use Friendica\Core; use Friendica\Core\Config; +use Friendica\Core\Config\Adapter; +use Friendica\Core\Config\Cache; class ConfigFactory { /** - * @param Config\ConfigCacheLoader $loader The Config Cache loader (INI/config/.htconfig) + * @param Cache\ConfigCacheLoader $loader The Config Cache loader (INI/config/.htconfig) * - * @return Config\ConfigCache + * @return Cache\ConfigCache */ - public static function createCache(Config\ConfigCacheLoader $loader) + public static function createCache(Cache\ConfigCacheLoader $loader) { - $configCache = new Config\ConfigCache(); + $configCache = new Cache\ConfigCache(); $loader->loadConfigFiles($configCache); return $configCache; } /** - * @param string $type The adapter type - * @param Config\IConfigCache $config The config cache of this adapter + * @param Cache\ConfigCache $configCache The config cache of this adapter * - * @return Config\IConfigAdapter + * @return Config\Configuration */ - public static function createConfig($type, Config\IConfigCache $config) + public static function createConfig(Cache\ConfigCache $configCache) { - if ($type == 'preload') { - return new Config\PreloadConfigAdapter($config); + if ($configCache->get('system', 'config_adapter') === 'preload') { + $configAdapter = new Adapter\PreloadConfigAdapter(); } else { - return new Config\JITConfigAdapter($config); + $configAdapter = new Adapter\JITConfigAdapter(); } + + $configuration = new Config\Configuration($configCache, $configAdapter); + + // Set the config in the static container for legacy usage + Core\Config::init($configuration); + + return $configuration; } /** - * @param string $type The adapter type - * @param Config\IPConfigCache $config The config cache of this adapter - * @param int $uid The UID of the current user + * @param Cache\ConfigCache $configCache The config cache of this adapter + * @param int $uid The UID of the current user * - * @return Config\IPConfigAdapter + * @return Config\PConfiguration */ - public static function createPConfig($type, Config\IPConfigCache $config, $uid = null) + public static function createPConfig(Cache\ConfigCache $configCache, $uid = null) { - if ($type == 'preload') { - return new Config\PreloadPConfigAdapter($config, $uid); + if ($configCache->get('system', 'config_adapter') === 'preload') { + $configAdapter = new Adapter\PreloadPConfigAdapter($uid); } else { - return new Config\JITPConfigAdapter($config); + $configAdapter = new Adapter\JITPConfigAdapter(); } + + $configuration = new Config\PConfiguration($configCache, $configAdapter); + + // Set the config in the static container for legacy usage + Core\PConfig::init($configuration); + + return $configuration; } } diff --git a/src/Factory/DBFactory.php b/src/Factory/DBFactory.php new file mode 100644 index 0000000000..5970541c10 --- /dev/null +++ b/src/Factory/DBFactory.php @@ -0,0 +1,48 @@ +get('database', 'hostname'); + $db_user = $configCache->get('database', 'username'); + $db_pass = $configCache->get('database', 'password'); + $db_data = $configCache->get('database', 'database'); + $charset = $configCache->get('database', 'charset'); + + // Use environment variables for mysql if they are set beforehand + if (!empty($server['MYSQL_HOST']) + && !empty($server['MYSQL_USERNAME'] || !empty($server['MYSQL_USER'])) + && $server['MYSQL_PASSWORD'] !== false + && !empty($server['MYSQL_DATABASE'])) + { + $db_host = $server['MYSQL_HOST']; + if (!empty($server['MYSQL_PORT'])) { + $db_host .= ':' . $server['MYSQL_PORT']; + } + if (!empty($server['MYSQL_USERNAME'])) { + $db_user = $server['MYSQL_USERNAME']; + } else { + $db_user = $server['MYSQL_USER']; + } + $db_pass = (string) $server['MYSQL_PASSWORD']; + $db_data = $server['MYSQL_DATABASE']; + } + + if (Database\DBA::connect($configCache, $db_host, $db_user, $db_pass, $db_data, $charset)) { + // Loads DB_UPDATE_VERSION constant + Database\DBStructure::definition($configCache->get('system', 'basepath'), false); + } + + unset($db_host, $db_user, $db_pass, $db_data, $charset); + } +} diff --git a/src/Factory/LoggerFactory.php b/src/Factory/LoggerFactory.php index f6e2d60395..e9bacb38e8 100644 --- a/src/Factory/LoggerFactory.php +++ b/src/Factory/LoggerFactory.php @@ -2,7 +2,7 @@ namespace Friendica\Factory; -use Friendica\Core\Config\ConfigCache; +use Friendica\Core\Config\Configuration; use Friendica\Core\Logger; use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Util\Logger\FriendicaDevelopHandler; @@ -22,12 +22,12 @@ class LoggerFactory /** * Creates a new PSR-3 compliant logger instances * - * @param string $channel The channel of the logger instance - * @param ConfigCache $config The config + * @param string $channel The channel of the logger instance + * @param Configuration $config The config * * @return LoggerInterface The PSR-3 compliant logger instance */ - public static function create($channel, ConfigCache $config = null) + public static function create($channel, Configuration $config) { $logger = new Monolog\Logger($channel); $logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor()); diff --git a/src/Module/Install.php b/src/Module/Install.php index 4fb4a932cd..3414e887fa 100644 --- a/src/Module/Install.php +++ b/src/Module/Install.php @@ -75,7 +75,7 @@ class Install extends BaseModule $dbdata = Strings::escapeTags(trim(defaults($_POST, 'dbdata', ''))); // If we cannot connect to the database, return to the previous step - if (!self::$installer->checkDB($a->getConfig(), $a->getProfiler(), $dbhost, $dbuser, $dbpass, $dbdata)) { + if (!self::$installer->checkDB($a->getConfigCache(), $a->getProfiler(), $dbhost, $dbuser, $dbpass, $dbdata)) { self::$currentWizardStep = self::DATABASE_CONFIG; } @@ -92,7 +92,7 @@ class Install extends BaseModule $adminmail = Strings::escapeTags(trim(defaults($_POST, 'adminmail', ''))); // If we cannot connect to the database, return to the Database config wizard - if (!self::$installer->checkDB($a->getConfig(), $a->getProfiler(), $dbhost, $dbuser, $dbpass, $dbdata)) { + if (!self::$installer->checkDB($a->getConfigCache(), $a->getProfiler(), $dbhost, $dbuser, $dbpass, $dbdata)) { self::$currentWizardStep = self::DATABASE_CONFIG; return; } diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php index 5c66711dcf..dde61e856b 100644 --- a/tests/DatabaseTest.php +++ b/tests/DatabaseTest.php @@ -5,7 +5,7 @@ namespace Friendica\Test; -use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Database\DBA; use Friendica\Factory; use Friendica\Util\BasePath; @@ -41,7 +41,7 @@ abstract class DatabaseTest extends MockedTest } $basedir = BasePath::create(dirname(__DIR__)); - $configLoader = new Config\ConfigCacheLoader($basedir); + $configLoader = new Cache\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $profiler = \Mockery::mock(Profiler::class); diff --git a/tests/Util/AppMockTrait.php b/tests/Util/AppMockTrait.php index 18188239f1..66b95b04e8 100644 --- a/tests/Util/AppMockTrait.php +++ b/tests/Util/AppMockTrait.php @@ -5,7 +5,6 @@ namespace Friendica\Test\Util; use Friendica\App; use Friendica\BaseObject; use Friendica\Core\Config; -use Friendica\Core\Config\ConfigCache; use Friendica\Render\FriendicaSmartyEngine; use Mockery\MockInterface; use org\bovigo\vfs\vfsStreamDirectory; @@ -21,7 +20,7 @@ trait AppMockTrait protected $app; /** - * @var MockInterface|ConfigCache The mocked Config Cache + * @var MockInterface|Config\Configuration The mocked Config Cache */ protected $configCache; @@ -29,9 +28,9 @@ trait AppMockTrait * Mock the App * * @param vfsStreamDirectory $root The root directory - * @param MockInterface|ConfigCache $config The config cache + * @param MockInterface|Config\Configuration $config The config cache */ - public function mockApp($root, $config) + public function mockApp($root, Config\Configuration $config) { $this->configCache = $config; // Mocking App and most used functions @@ -62,11 +61,14 @@ trait AppMockTrait ->andReturn('localhost'); $config ->shouldReceive('get') - ->with('system', 'theme', NULL) + ->with('system', 'theme', NULL, false) ->andReturn('system_theme'); + $config + ->shouldReceive('getConfig') + ->andReturn($config); $this->app - ->shouldReceive('getConfig') + ->shouldReceive('getConfigCache') ->andReturn($config); $this->app @@ -84,11 +86,6 @@ trait AppMockTrait // Initialize empty Config Config::init($config); - $configAdapter = \Mockery::mock('Friendica\Core\Config\IConfigAdapter'); - $configAdapter - ->shouldReceive('isConnected') - ->andReturn(false); - Config::setAdapter($configAdapter); BaseObject::setApp($this->app); } diff --git a/tests/include/ApiTest.php b/tests/include/ApiTest.php index 41f5c0fdf1..7f2299d519 100644 --- a/tests/include/ApiTest.php +++ b/tests/include/ApiTest.php @@ -7,6 +7,7 @@ namespace Friendica\Test; use Friendica\App; use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Core\PConfig; use Friendica\Core\Protocol; use Friendica\Core\System; @@ -36,8 +37,11 @@ class ApiTest extends DatabaseTest public function setUp() { $basedir = BasePath::create(dirname(__DIR__) . '/../'); - $configLoader = new Config\ConfigCacheLoader($basedir); - $config = Factory\ConfigFactory::createCache($configLoader); + $configLoader = new Cache\ConfigCacheLoader($basedir); + $configCache = Factory\ConfigFactory::createCache($configLoader); + Factory\DBFactory::init($configCache, $_SERVER); + $config = Factory\ConfigFactory::createConfig($configCache); + $pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('test', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); $this->app = new App($config, $logger, $profiler, false); diff --git a/tests/src/App/ModeTest.php b/tests/src/App/ModeTest.php index 19dad07cd6..5a5c4c87e6 100644 --- a/tests/src/App/ModeTest.php +++ b/tests/src/App/ModeTest.php @@ -90,19 +90,14 @@ class ModeTest extends MockedTest $this->mockConnected(true, 1); $this->mockFetchFirst('SHOW TABLES LIKE \'config\'', true, 1); - $config = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $config = \Mockery::mock('Friendica\Core\Config\Configuration'); $config ->shouldReceive('get') - ->with('system', 'maintenance', null) + ->with('system', 'maintenance', null, false) ->andReturn(true) ->once(); // Initialize empty Config Config::init($config); - $configAdapter = \Mockery::mock('Friendica\Core\Config\IConfigAdapter'); - $configAdapter - ->shouldReceive('isConnected') - ->andReturn(false); - Config::setAdapter($configAdapter); $mode = new Mode($this->root->url()); $mode->determine(); @@ -123,19 +118,14 @@ class ModeTest extends MockedTest $this->mockConnected(true, 1); $this->mockFetchFirst('SHOW TABLES LIKE \'config\'', true, 1); - $config = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $config = \Mockery::mock('Friendica\Core\Config\Configuration'); $config ->shouldReceive('get') - ->with('system', 'maintenance', null) + ->with('system', 'maintenance', null, false) ->andReturn(false) ->once(); // Initialize empty Config Config::init($config); - $configAdapter = \Mockery::mock('Friendica\Core\Config\IConfigAdapter'); - $configAdapter - ->shouldReceive('isConnected') - ->andReturn(false); - Config::setAdapter($configAdapter); $mode = new Mode($this->root->url()); $mode->determine(); diff --git a/tests/src/BaseObjectTest.php b/tests/src/BaseObjectTest.php index 784944c3a0..39741eb9e1 100644 --- a/tests/src/BaseObjectTest.php +++ b/tests/src/BaseObjectTest.php @@ -31,7 +31,7 @@ class BaseObjectTest extends TestCase { $baseObject = new BaseObject(); $this->setUpVfsDir(); - $configMock = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $configMock = \Mockery::mock('Friendica\Core\Config\Configuration'); $this->mockApp($this->root, $configMock); $this->assertNull($baseObject->setApp($this->app)); diff --git a/tests/src/Core/Cache/CacheTest.php b/tests/src/Core/Cache/CacheTest.php index e8bd65cbfe..961ac9e1b4 100644 --- a/tests/src/Core/Cache/CacheTest.php +++ b/tests/src/Core/Cache/CacheTest.php @@ -67,7 +67,7 @@ abstract class CacheTest extends MockedTest protected function setUp() { $this->setUpVfsDir(); - $configMock = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $configMock = \Mockery::mock('Friendica\Core\Config\Configuration'); $this->mockApp($this->root, $configMock); $this->app ->shouldReceive('getHostname') diff --git a/tests/src/Core/Cache/MemcacheCacheDriverTest.php b/tests/src/Core/Cache/MemcacheCacheDriverTest.php index 7832344a89..5017b6967e 100644 --- a/tests/src/Core/Cache/MemcacheCacheDriverTest.php +++ b/tests/src/Core/Cache/MemcacheCacheDriverTest.php @@ -14,12 +14,12 @@ class MemcacheCacheDriverTest extends MemoryCacheTest { $this->configCache ->shouldReceive('get') - ->with('system', 'memcache_host', NULL) + ->with('system', 'memcache_host', NULL, false) ->andReturn('localhost'); $this->configCache ->shouldReceive('get') - ->with('system', 'memcache_port', NULL) + ->with('system', 'memcache_port', NULL, false) ->andReturn(11211); $this->cache = CacheDriverFactory::create('memcache'); diff --git a/tests/src/Core/Cache/MemcachedCacheDriverTest.php b/tests/src/Core/Cache/MemcachedCacheDriverTest.php index fe401f97dd..7c68353593 100644 --- a/tests/src/Core/Cache/MemcachedCacheDriverTest.php +++ b/tests/src/Core/Cache/MemcachedCacheDriverTest.php @@ -14,7 +14,7 @@ class MemcachedCacheDriverTest extends MemoryCacheTest { $this->configCache ->shouldReceive('get') - ->with('system', 'memcached_hosts', NULL) + ->with('system', 'memcached_hosts', NULL, false) ->andReturn([0 => 'localhost, 11211']); $this->cache = CacheDriverFactory::create('memcached'); diff --git a/tests/src/Core/Cache/RedisCacheDriverTest.php b/tests/src/Core/Cache/RedisCacheDriverTest.php index 0a3dba439d..d36e6b826e 100644 --- a/tests/src/Core/Cache/RedisCacheDriverTest.php +++ b/tests/src/Core/Cache/RedisCacheDriverTest.php @@ -14,12 +14,12 @@ class RedisCacheDriverTest extends MemoryCacheTest { $this->configCache ->shouldReceive('get') - ->with('system', 'redis_host', NULL) + ->with('system', 'redis_host', NULL, false) ->andReturn('localhost'); $this->configCache ->shouldReceive('get') - ->with('system', 'redis_port', NULL) + ->with('system', 'redis_port', NULL, false) ->andReturn(null); $this->cache = CacheDriverFactory::create('redis'); diff --git a/tests/src/Core/Config/ConfigCacheLoaderTest.php b/tests/src/Core/Config/Cache/ConfigCacheLoaderTest.php similarity index 95% rename from tests/src/Core/Config/ConfigCacheLoaderTest.php rename to tests/src/Core/Config/Cache/ConfigCacheLoaderTest.php index 6be89bc40f..f91f267c71 100644 --- a/tests/src/Core/Config/ConfigCacheLoaderTest.php +++ b/tests/src/Core/Config/Cache/ConfigCacheLoaderTest.php @@ -1,9 +1,9 @@ delConfigFile('local.config.php'); $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . @@ -91,6 +92,7 @@ class ConfigCacheLoaderTest extends MockedTest $this->delConfigFile('local.config.php'); $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . @@ -122,6 +124,7 @@ class ConfigCacheLoaderTest extends MockedTest $this->delConfigFile('local.config.php'); $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . @@ -160,6 +163,7 @@ class ConfigCacheLoaderTest extends MockedTest vfsStream::create($structure, $this->root); $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . diff --git a/tests/src/Core/Config/ConfigCacheTest.php b/tests/src/Core/Config/Cache/ConfigCacheTest.php similarity index 62% rename from tests/src/Core/Config/ConfigCacheTest.php rename to tests/src/Core/Config/Cache/ConfigCacheTest.php index 25ea6030f7..7b56ca6469 100644 --- a/tests/src/Core/Config/ConfigCacheTest.php +++ b/tests/src/Core/Config/Cache/ConfigCacheTest.php @@ -1,8 +1,8 @@ loadConfigArray($data); + $configCache->load($data); $this->assertConfigValues($data, $configCache); } @@ -67,18 +67,38 @@ class ConfigCacheTest extends MockedTest ]; $configCache = new ConfigCache(); - $configCache->loadConfigArray($data); - $configCache->loadConfigArray($override); + $configCache->load($data); + $configCache->load($override); $this->assertConfigValues($data, $configCache); // override the value - $configCache->loadConfigArray($override, true); + $configCache->load($override, true); $this->assertEquals($override['system']['test'], $configCache->get('system', 'test')); $this->assertEquals($override['system']['boolTrue'], $configCache->get('system', 'boolTrue')); } + /** + * Test the loadConfigArray() method with wrong/empty datasets + */ + public function testLoadConfigArrayWrong() + { + $configCache = new ConfigCache(); + + // empty dataset + $configCache->load([]); + $this->assertEmpty($configCache->getAll()); + + // wrong dataset + $configCache->load(['system' => 'not_array']); + $this->assertEmpty($configCache->getAll()); + + // incomplete dataset (key is integer ID of the array) + $configCache->load(['system' => ['value']]); + $this->assertEquals('value', $configCache->get('system', 0)); + } + /** * Test the getAll() method * @dataProvider dataTests @@ -86,14 +106,12 @@ class ConfigCacheTest extends MockedTest public function testGetAll($data) { $configCache = new ConfigCache(); - $configCache->loadConfigArray($data); + $configCache->load($data); $all = $configCache->getAll(); $this->assertContains($data['system'], $all); - - // config values are stored directly in the array base - $this->assertEquals($data['config']['a'], $all['a']); + $this->assertContains($data['config'], $all); } /** @@ -113,6 +131,33 @@ class ConfigCacheTest extends MockedTest $this->assertConfigValues($data, $configCache); } + /** + * Test the get() method without a value + */ + public function testGetEmpty() + { + $configCache = new ConfigCache(); + + $this->assertEquals('!!', $configCache->get('something', 'value')); + } + + /** + * Test the has() method + */ + public function testHas() + { + $configCache = new ConfigCache(); + + $this->assertFalse($configCache->has('system', 'test')); + + $configCache->set('system', 'test', 'it'); + $this->assertTrue($configCache->has('system', 'test')); + + $this->assertFalse($configCache->has('system', null)); + $configCache->set('system', null, 'it'); + $this->assertTrue($configCache->has('system', null)); + } + /** * Test the delete() method * @dataProvider dataTests @@ -172,4 +217,22 @@ class ConfigCacheTest extends MockedTest $this->assertEmpty($configCache->getAll()); } + + /** + * Test the hasP() method + */ + public function testHasP() + { + $configCache = new ConfigCache(); + $uid = 345; + + $this->assertFalse($configCache->hasP($uid, 'system', 'test')); + + $configCache->setP($uid, 'system', 'test', 'it'); + $this->assertTrue($configCache->hasP($uid, 'system', 'test')); + + $this->assertFalse($configCache->hasP($uid, 'system', null)); + $configCache->setP($uid, 'system', null, 'it'); + $this->assertTrue($configCache->hasP($uid, 'system', null)); + } } diff --git a/tests/src/Core/Config/ConfigurationTest.php b/tests/src/Core/Config/ConfigurationTest.php new file mode 100644 index 0000000000..6ce81a41b0 --- /dev/null +++ b/tests/src/Core/Config/ConfigurationTest.php @@ -0,0 +1,215 @@ +shouldReceive('isConnected')->andReturn(false)->once(); + + $configuration = new Configuration($configCache, $configAdapter); + + $this->assertInstanceOf(IConfigCache::class, $configuration->getCache()); + } + + /** + * Test if the configuration load() method + */ + public function testCacheLoad() + { + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->twice(); + // constructor loading + $configAdapter->shouldReceive('load')->andReturn([])->once(); + // expected loading + $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once(); + + $configuration = new Configuration($configCache, $configAdapter); + $configuration->load('testing'); + + $this->assertEquals('it', $configuration->get('testing', 'test')); + $this->assertEquals('it', $configuration->getCache()->get('testing', 'test')); + } + + /** + * Test if the configuration load() method with overwrite + */ + public function testCacheLoadDouble() + { + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); + // constructor loading + $configAdapter->shouldReceive('load')->andReturn([])->once(); + // expected loading + $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once(); + // expected next loading + $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'again']])->once(); + + $configuration = new Configuration($configCache, $configAdapter); + $configuration->load('testing'); + + $this->assertEquals('it', $configuration->get('testing', 'test')); + $this->assertEquals('it', $configuration->getCache()->get('testing', 'test')); + + $configuration->load('testing'); + + $this->assertEquals('again', $configuration->get('testing', 'test')); + $this->assertEquals('again', $configuration->getCache()->get('testing', 'test')); + } + + /** + * Test if the configuration get() and set() methods without adapter + */ + public function testSetGetWithoutDB() + { + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->twice(); + + $configuration = new Configuration($configCache, $configAdapter); + + $this->assertTrue($configuration->set('test', 'it', 'now')); + + $this->assertEquals('now', $configuration->get('test', 'it')); + $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); + } + + /** + * Test if the configuration get() and set() methods with adapter + */ + public function testSetGetWithDB() + { + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->twice(); + // constructor loading + $configAdapter->shouldReceive('load')->andReturn([])->once(); + $configAdapter->shouldReceive('set')->with('test', 'it', 'now')->andReturn(true)->once(); + + $configuration = new Configuration($configCache, $configAdapter); + + $this->assertTrue($configuration->set('test', 'it', 'now')); + + $this->assertEquals('now', $configuration->get('test', 'it')); + $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); + } + + /** + * Test the configuration get() method with wrong value and no db + */ + public function testGetWrongWithoutDB() + { + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(4); + + $configuration = new Configuration($configCache, $configAdapter); + + // without refresh + $this->assertNull($configuration->get('test', 'it')); + + /// beware that the cache returns '!!' and not null for a non existing value + $this->assertEquals('!!', $configuration->getCache()->get('test', 'it')); + + // with default value + $this->assertEquals('default', $configuration->get('test', 'it', 'default')); + + // with default value and refresh + $this->assertEquals('default', $configuration->get('test', 'it', 'default', true)); + } + + /** + * Test the configuration get() method with refresh + */ + public function testGetWithRefresh() + { + $configCache = new ConfigCache(['test' => ['it' => 'now']]); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); + // constructor loading + $configAdapter->shouldReceive('load')->andReturn([])->once(); + $configAdapter->shouldReceive('get')->with('test', 'it')->andReturn('again')->once(); + $configAdapter->shouldReceive('get')->with('test', 'not')->andReturn('!!')->once(); + + $configuration = new Configuration($configCache, $configAdapter); + + // without refresh + $this->assertEquals('now', $configuration->get('test', 'it')); + $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); + + // with refresh + $this->assertEquals('again', $configuration->get('test', 'it', null, true)); + $this->assertEquals('again', $configuration->getCache()->get('test', 'it')); + + // without refresh and wrong value and default + $this->assertEquals('default', $configuration->get('test', 'not', 'default')); + $this->assertEquals('!!', $configuration->getCache()->get('test', 'not')); + } + + /** + * Test the configuration delete() method without adapter + */ + public function testDeleteWithoutDB() + { + $configCache = new ConfigCache(['test' => ['it' => 'now']]); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(3); + + $configuration = new Configuration($configCache, $configAdapter); + + $this->assertEquals('now', $configuration->get('test', 'it')); + $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); + + $this->assertTrue($configuration->delete('test', 'it')); + $this->assertNull($configuration->get('test', 'it')); + $this->assertEquals('!!', $configuration->getCache()->get('test', 'it')); + + $this->assertEmpty($configuration->getCache()->getAll()); + } + + /** + * Test the configuration delete() method with adapter + */ + public function testDeleteWithDB() + { + $configCache = new ConfigCache(['test' => ['it' => 'now', 'quarter' => 'true']]); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(5); + // constructor loading + $configAdapter->shouldReceive('load')->andReturn([])->once(); + $configAdapter->shouldReceive('delete')->with('test', 'it')->andReturn(false)->once(); + + $configAdapter->shouldReceive('delete')->with('test', 'second')->andReturn(true)->once(); + $configAdapter->shouldReceive('delete')->with('test', 'third')->andReturn(false)->once(); + $configAdapter->shouldReceive('delete')->with('test', 'quarter')->andReturn(true)->once(); + + $configuration = new Configuration($configCache, $configAdapter); + + $this->assertEquals('now', $configuration->get('test', 'it')); + $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); + + // delete from cache only + $this->assertTrue($configuration->delete('test', 'it')); + // delete from db only + $this->assertTrue($configuration->delete('test', 'second')); + // no delete + $this->assertFalse($configuration->delete('test', 'third')); + // delete both + $this->assertTrue($configuration->delete('test', 'quarter')); + + $this->assertEmpty($configuration->getCache()->getAll()); + } +} diff --git a/tests/src/Core/Config/PConfigurationTest.php b/tests/src/Core/Config/PConfigurationTest.php new file mode 100644 index 0000000000..3d8fb586ce --- /dev/null +++ b/tests/src/Core/Config/PConfigurationTest.php @@ -0,0 +1,186 @@ +shouldReceive('isConnected')->andReturn(true)->once(); + // expected loading + $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once(); + + $configuration = new PConfiguration($configCache, $configAdapter); + $configuration->load($uid, 'testing'); + + $this->assertEquals('it', $configuration->get($uid, 'testing', 'test')); + } + + /** + * Test if the configuration load() method with overwrite + */ + public function testCacheLoadDouble() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->twice(); + // expected loading + $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once(); + // expected next loading + $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'again']])->once(); + + $configuration = new PConfiguration($configCache, $configAdapter); + $configuration->load($uid, 'testing'); + + $this->assertEquals('it', $configuration->get($uid, 'testing', 'test')); + + $configuration->load($uid, 'testing'); + + $this->assertEquals('again', $configuration->get($uid, 'testing', 'test')); + } + + /** + * Test if the configuration get() and set() methods without adapter + */ + public function testSetGetWithoutDB() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->once(); + + $configuration = new PConfiguration($configCache, $configAdapter); + + $this->assertTrue($configuration->set($uid, 'test', 'it', 'now')); + + $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + } + + /** + * Test if the configuration get() and set() methods with adapter + */ + public function testSetGetWithDB() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->once(); + $configAdapter->shouldReceive('set')->with($uid, 'test', 'it', 'now')->andReturn(true)->once(); + + $configuration = new PConfiguration($configCache, $configAdapter); + + $this->assertTrue($configuration->set($uid, 'test', 'it', 'now')); + + $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + } + + /** + * Test the configuration get() method with wrong value and no db + */ + public function testGetWrongWithoutDB() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(3); + + $configuration = new PConfiguration($configCache, $configAdapter); + + // without refresh + $this->assertNull($configuration->get($uid, 'test', 'it')); + + // with default value + $this->assertEquals('default', $configuration->get($uid, 'test', 'it', 'default')); + + // with default value and refresh + $this->assertEquals('default', $configuration->get($uid, 'test', 'it', 'default', true)); + } + + /** + * Test the configuration get() method with refresh + */ + public function testGetWithRefresh() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); + $configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn('now')->once(); + $configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn('again')->once(); + $configAdapter->shouldReceive('get')->with($uid, 'test', 'not')->andReturn('!!')->once(); + + $configuration = new PConfiguration($configCache, $configAdapter); + + // without refresh + $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + // use the cache again + $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + + // with refresh (and load the second value out of the db) + $this->assertEquals('again', $configuration->get($uid, 'test', 'it', null, true)); + + // without refresh and wrong value and default + $this->assertEquals('default', $configuration->get($uid, 'test', 'not', 'default')); + } + + /** + * Test the configuration delete() method without adapter + */ + public function testDeleteWithoutDB() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(3); + + $configuration = new PConfiguration($configCache, $configAdapter); + + $this->assertTrue($configuration->set($uid, 'test', 'it', 'now')); + $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + + $this->assertTrue($configuration->delete($uid, 'test', 'it')); + $this->assertNull($configuration->get($uid, 'test', 'it')); + } + + /** + * Test the configuration delete() method with adapter + */ + public function testDeleteWithDB() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(5); + $configAdapter->shouldReceive('set')->with($uid, 'test', 'it', 'now')->andReturn(false)->once(); + $configAdapter->shouldReceive('delete')->with($uid, 'test', 'it')->andReturn(false)->once(); + + $configAdapter->shouldReceive('delete')->with($uid, 'test', 'second')->andReturn(true)->once(); + $configAdapter->shouldReceive('delete')->with($uid, 'test', 'third')->andReturn(false)->once(); + $configAdapter->shouldReceive('delete')->with($uid, 'test', 'quarter')->andReturn(true)->once(); + + $configuration = new PConfiguration($configCache, $configAdapter); + + $this->assertFalse($configuration->set($uid, 'test', 'it', 'now')); + $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + + // delete from set + $this->assertTrue($configuration->delete($uid, 'test', 'it')); + // delete from db only + $this->assertTrue($configuration->delete($uid, 'test', 'second')); + // no delete + $this->assertFalse($configuration->delete($uid, 'test', 'third')); + // delete both + $this->assertTrue($configuration->delete($uid, 'test', 'quarter')); + } +} diff --git a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php index 41ccce0b28..ce3dac02cc 100644 --- a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php +++ b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php @@ -54,7 +54,7 @@ class AutomaticInstallationConsoleTest extends ConsoleTest $this->configCache ->shouldReceive('get') - ->with('config', 'php_path', NULL) + ->with('config', 'php_path', NULL, false) ->andReturn(false); $this->mockL10nT(); diff --git a/tests/src/Core/Console/ConfigConsoleTest.php b/tests/src/Core/Console/ConfigConsoleTest.php index 505c4f794d..5b7d14906c 100644 --- a/tests/src/Core/Console/ConfigConsoleTest.php +++ b/tests/src/Core/Console/ConfigConsoleTest.php @@ -39,7 +39,7 @@ class ConfigConsoleTest extends ConsoleTest ->once(); $this->configCache ->shouldReceive('get') - ->with('config', 'test', NULL) + ->with('config', 'test', NULL, false) ->andReturn('now') ->twice(); @@ -52,7 +52,7 @@ class ConfigConsoleTest extends ConsoleTest $this->configCache ->shouldReceive('get') - ->with('config', 'test', null) + ->with('config', 'test', null, false) ->andReturn('now') ->once(); @@ -64,7 +64,7 @@ class ConfigConsoleTest extends ConsoleTest $this->configCache ->shouldReceive('get') - ->with('config', 'test', null) + ->with('config', 'test', null, false) ->andReturn(null) ->once(); @@ -79,7 +79,7 @@ class ConfigConsoleTest extends ConsoleTest $testArray = [1, 2, 3]; $this->configCache ->shouldReceive('get') - ->with('config', 'test', null) + ->with('config', 'test', null, false) ->andReturn($testArray) ->once(); @@ -107,7 +107,7 @@ class ConfigConsoleTest extends ConsoleTest function testVerbose() { $this->configCache ->shouldReceive('get') - ->with('test', 'it', null) + ->with('test', 'it', null, false) ->andReturn('now') ->once(); $console = new Config($this->consoleArgv); @@ -140,7 +140,7 @@ CONF; ->once(); $this->configCache ->shouldReceive('get') - ->with('test', 'it', NULL) + ->with('test', 'it', NULL, false) ->andReturn(NULL) ->once(); $console = new Config(); diff --git a/tests/src/Core/Console/ConsoleTest.php b/tests/src/Core/Console/ConsoleTest.php index 715e68ab26..f733175d34 100644 --- a/tests/src/Core/Console/ConsoleTest.php +++ b/tests/src/Core/Console/ConsoleTest.php @@ -3,7 +3,7 @@ namespace Friendica\Test\src\Core\Console; use Asika\SimpleConsole\Console; -use Friendica\Core\Config\ConfigCache; +use Friendica\Core\Config\Configuration; use Friendica\Test\MockedTest; use Friendica\Test\Util\AppMockTrait; use Friendica\Test\Util\Intercept; @@ -31,7 +31,7 @@ abstract class ConsoleTest extends MockedTest Intercept::setUp(); $this->setUpVfsDir(); - $configMock = \Mockery::mock(ConfigCache::class); + $configMock = \Mockery::mock(Configuration::class); $this->mockApp($this->root, $configMock); $profileMock = \Mockery::mock(Profiler::class); $this->app->shouldReceive('getProfiler')->andReturn($profileMock); diff --git a/tests/src/Core/Lock/LockTest.php b/tests/src/Core/Lock/LockTest.php index ab8e1b2f2e..c1378aa164 100644 --- a/tests/src/Core/Lock/LockTest.php +++ b/tests/src/Core/Lock/LockTest.php @@ -27,7 +27,7 @@ abstract class LockTest extends MockedTest { // Reusable App object $this->setUpVfsDir(); - $configMock = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $configMock = \Mockery::mock('Friendica\Core\Config\Configuration'); $this->mockApp($this->root, $configMock); $this->app ->shouldReceive('getHostname') diff --git a/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php b/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php index 46f29f52e2..0e118c5dd7 100644 --- a/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php +++ b/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php @@ -15,12 +15,12 @@ class MemcacheCacheLockDriverTest extends LockTest { $this->configCache ->shouldReceive('get') - ->with('system', 'memcache_host', NULL) + ->with('system', 'memcache_host', NULL, false) ->andReturn('localhost'); $this->configCache ->shouldReceive('get') - ->with('system', 'memcache_port', NULL) + ->with('system', 'memcache_port', NULL, false) ->andReturn(11211); return new CacheLockDriver(CacheDriverFactory::create('memcache')); diff --git a/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php b/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php index 72271c98b9..fe490a38cf 100644 --- a/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php +++ b/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php @@ -15,7 +15,7 @@ class MemcachedCacheLockDriverTest extends LockTest { $this->configCache ->shouldReceive('get') - ->with('system', 'memcached_hosts', NULL) + ->with('system', 'memcached_hosts', NULL, false) ->andReturn([0 => 'localhost, 11211']); return new CacheLockDriver(CacheDriverFactory::create('memcached')); diff --git a/tests/src/Core/Lock/RedisCacheLockDriverTest.php b/tests/src/Core/Lock/RedisCacheLockDriverTest.php index 0c9deea16e..f5d0a648fb 100644 --- a/tests/src/Core/Lock/RedisCacheLockDriverTest.php +++ b/tests/src/Core/Lock/RedisCacheLockDriverTest.php @@ -15,12 +15,12 @@ class RedisCacheLockDriverTest extends LockTest { $this->configCache ->shouldReceive('get') - ->with('system', 'redis_host', NULL) + ->with('system', 'redis_host', NULL, false) ->andReturn('localhost'); $this->configCache ->shouldReceive('get') - ->with('system', 'redis_port', NULL) + ->with('system', 'redis_port', NULL, false) ->andReturn(null); return new CacheLockDriver(CacheDriverFactory::create('redis')); diff --git a/tests/src/Core/Lock/SemaphoreLockDriverTest.php b/tests/src/Core/Lock/SemaphoreLockDriverTest.php index c2b9414572..bf422f2f88 100644 --- a/tests/src/Core/Lock/SemaphoreLockDriverTest.php +++ b/tests/src/Core/Lock/SemaphoreLockDriverTest.php @@ -14,7 +14,7 @@ class SemaphoreLockDriverTest extends LockTest $this->configCache ->shouldReceive('get') - ->with('system', 'temppath', NULL) + ->with('system', 'temppath', NULL, false) ->andReturn('/tmp/'); } diff --git a/tests/src/Database/DBATest.php b/tests/src/Database/DBATest.php index c6981a91d9..a4a715575c 100644 --- a/tests/src/Database/DBATest.php +++ b/tests/src/Database/DBATest.php @@ -3,6 +3,7 @@ namespace Friendica\Test\Database; use Friendica\App; use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Database\DBA; use Friendica\Factory; use Friendica\Test\DatabaseTest; @@ -13,8 +14,11 @@ class DBATest extends DatabaseTest public function setUp() { $basedir = BasePath::create(dirname(__DIR__) . '/../../'); - $configLoader = new Config\ConfigCacheLoader($basedir); - $config = Factory\ConfigFactory::createCache($configLoader); + $configLoader = new Cache\ConfigCacheLoader($basedir); + $configCache = Factory\ConfigFactory::createCache($configLoader); + Factory\DBFactory::init($configCache, $_SERVER); + $config = Factory\ConfigFactory::createConfig($configCache); + $pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('test', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); $this->app = new App($config, $logger, $profiler, false); diff --git a/tests/src/Database/DBStructureTest.php b/tests/src/Database/DBStructureTest.php index 250df06936..6a5e25e76b 100644 --- a/tests/src/Database/DBStructureTest.php +++ b/tests/src/Database/DBStructureTest.php @@ -3,7 +3,7 @@ namespace Friendica\Test\Database; use Friendica\App; -use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Database\DBStructure; use Friendica\Factory; use Friendica\Test\DatabaseTest; @@ -14,8 +14,11 @@ class DBStructureTest extends DatabaseTest public function setUp() { $basedir = BasePath::create(dirname(__DIR__) . '/../../'); - $configLoader = new Config\ConfigCacheLoader($basedir); - $config = Factory\ConfigFactory::createCache($configLoader); + $configLoader = new Cache\ConfigCacheLoader($basedir); + $configCache = Factory\ConfigFactory::createCache($configLoader); + Factory\DBFactory::init($configCache, $_SERVER); + $config = Factory\ConfigFactory::createConfig($configCache); + $pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('test', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); $this->app = new App($config, $logger, $profiler, false);