From d760d339895d40e9de86ab98471d233179502a8a Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sat, 3 Mar 2018 12:09:12 -0500 Subject: [PATCH] Add Config adapter interfaces/classes --- src/Core/Config/IConfigAdapter.php | 72 ++++++++++++ src/Core/Config/IPConfigAdapter.php | 77 +++++++++++++ src/Core/Config/JITConfigAdapter.php | 132 ++++++++++++++++++++++ src/Core/Config/JITPConfigAdapter.php | 117 +++++++++++++++++++ src/Core/Config/PreloadConfigAdapter.php | 119 +++++++++++++++++++ src/Core/Config/PreloadPConfigAdapter.php | 102 +++++++++++++++++ 6 files changed, 619 insertions(+) create mode 100644 src/Core/Config/IConfigAdapter.php create mode 100644 src/Core/Config/IPConfigAdapter.php create mode 100644 src/Core/Config/JITConfigAdapter.php create mode 100644 src/Core/Config/JITPConfigAdapter.php create mode 100644 src/Core/Config/PreloadConfigAdapter.php create mode 100644 src/Core/Config/PreloadPConfigAdapter.php diff --git a/src/Core/Config/IConfigAdapter.php b/src/Core/Config/IConfigAdapter.php new file mode 100644 index 0000000000..ee5ca3ca54 --- /dev/null +++ b/src/Core/Config/IConfigAdapter.php @@ -0,0 +1,72 @@ + + */ +interface IConfigAdapter +{ + /** + * @brief Loads all configuration values into a cached storage. + * + * All configuration values of the system are stored in global cache + * which is available under the global variable $a->config + * + * @param string $cat The category of the configuration values to load + * + * @return void + */ + public function load($cat = "config"); + + /** + * @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 in $a->config[$uid]. + * $instore is only used by the set_config function + * to determine if the key already exists in the DB + * If a key is found in the DB but doesn't exist in + * local config cache, pull it into the cache so we don't have + * to hit the DB again for this item. + * + * @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) + * + * @return mixed Stored value or null if it does not exist + */ + public function get($cat, $k, $default_value = null, $refresh = false); + + /** + * @brief Sets a configuration value for system config + * + * 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 $family The category of the configuration value + * @param string $key The configuration key to set + * @param mixed $value The value to store + * + * @return mixed Stored $value or false if the database update failed + */ + public function set($cat, $k, $value); + + /** + * @brief Deletes the given key from the system configuration. + * + * Removes the configured value from the stored cache in $a->config + * and removes it from the database. + * + * @param string $cat The category of the configuration value + * @param string $k The configuration key to delete + * + * @return mixed + */ + public function delete($cat, $k); +} diff --git a/src/Core/Config/IPConfigAdapter.php b/src/Core/Config/IPConfigAdapter.php new file mode 100644 index 0000000000..f78654d39c --- /dev/null +++ b/src/Core/Config/IPConfigAdapter.php @@ -0,0 +1,77 @@ +config[$uid]. + * + * @param string $uid The user_id + * @param string $cat The category of the configuration value + * + * @return void + */ + public function 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 from a cached storage in $a->config[$uid]. + * + * @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) + * + * @return mixed Stored value or null if it does not exist + */ + public function get($uid, $cat, $k, $default_value = null, $refresh = false); + + /** + * @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 $k The configuration key to set + * @param string $value The value to store + * + * @return mixed Stored $value or false + */ + public function set($uid, $cat, $k, $value); + + /** + * @brief Deletes the given key from the users's configuration. + * + * Removes the configured value from the stored cache in $a->config[$uid] + * and removes it from the database. + * + * @param string $uid The user_id + * @param string $cat The category of the configuration value + * @param string $k The configuration key to delete + * + * @return mixed + */ + public function delete($uid, $cat, $k); +} diff --git a/src/Core/Config/JITConfigAdapter.php b/src/Core/Config/JITConfigAdapter.php new file mode 100644 index 0000000000..1bc3bf5a8f --- /dev/null +++ b/src/Core/Config/JITConfigAdapter.php @@ -0,0 +1,132 @@ + + */ +class JITConfigAdapter extends BaseObject implements IConfigAdapter +{ + private $cache; + private $in_db; + + public function load($cat = "config") + { + // We don't preload "system" anymore. + // This reduces the number of database reads a lot. + if ($cat === 'system') { + return; + } + + $a = self::getApp(); + + $configs = dba::select('config', ['v', 'k'], ['cat' => $cat]); + while ($config = dba::fetch($configs)) { + $k = $config['k']; + if ($cat === 'config') { + $a->config[$k] = $config['v']; + } else { + $a->config[$cat][$k] = $config['v']; + self::$cache[$cat][$k] = $config['v']; + self::$in_db[$cat][$k] = true; + } + } + dba::close($configs); + } + + public function get($cat, $k, $default_value = null, $refresh = false) + { + $a = self::getApp(); + + 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 (DBM::is_result($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 (isset($a->config[$cat][$k])) { + // Assign the value (mostly) from the .htconfig.php to the cache + $this->cache[$cat][$k] = $a->config[$cat][$k]; + $this->in_db[$cat][$k] = false; + + return $a->config[$cat][$k]; + } + + $this->cache[$cat][$k] = '!!'; + $this->in_db[$cat][$k] = false; + + return $default_value; + } + + public function set($cat, $k, $value) + { + $a = self::getApp(); + + // 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 (($stored === $dbvalue) && $this->in_db[$cat][$k]) { + return true; + } + + if ($cat === 'config') { + $a->config[$k] = $dbvalue; + } elseif ($cat != 'system') { + $a->config[$cat][$k] = $dbvalue; + } + + // 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 $value; + } + + return $result; + } + + public function delete($cat, $k) + { + 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 new file mode 100644 index 0000000000..27f2ed8622 --- /dev/null +++ b/src/Core/Config/JITPConfigAdapter.php @@ -0,0 +1,117 @@ + + */ +class JITPConfigAdapter extends BaseObject implements IPConfigAdapter +{ + private $in_db; + + public function load($uid, $cat) + { + $a = self::getApp(); + + $pconfigs = dba::select('pconfig', ['v', 'k'], ['cat' => $cat, 'uid' => $uid]); + if (DBM::is_result($pconfigs)) { + while ($pconfig = dba::fetch($pconfigs)) { + $k = $pconfig['k']; + $a->config[$uid][$cat][$k] = $pconfig['v']; + $this->in_db[$uid][$cat][$k] = true; + } + } else if ($cat != 'config') { + // Negative caching + $a->config[$uid][$cat] = "!!"; + } + dba::close($pconfigs); + } + + public function get($uid, $cat, $k, $default_value = null, $refresh = false) + { + $a = self::getApp(); + + if (!$refresh) { + // Looking if the whole family isn't set + if (isset($a->config[$uid][$cat])) { + if ($a->config[$uid][$cat] === '!!') { + return $default_value; + } + } + + if (isset($a->config[$uid][$cat][$k])) { + if ($a->config[$uid][$cat][$k] === '!!') { + return $default_value; + } + return $a->config[$uid][$cat][$k]; + } + } + + $pconfig = dba::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $k]); + if (DBM::is_result($pconfig)) { + $val = (preg_match("|^a:[0-9]+:{.*}$|s", $pconfig['v']) ? unserialize($pconfig['v']) : $pconfig['v']); + $a->config[$uid][$cat][$k] = $val; + $this->in_db[$uid][$cat][$k] = true; + + return $val; + } else { + $a->config[$uid][$cat][$k] = '!!'; + $this->in_db[$uid][$cat][$k] = false; + + return $default_value; + } + } + + public function set($uid, $cat, $k, $value) + { + $a = self::getApp(); + + // 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; + } + + $a->config[$uid][$cat][$k] = $dbvalue; + + // 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 $value; + } + + return $result; + } + + public function delete($uid, $cat, $k) + { + $a = self::getApp(); + + if (!empty($a->config[$uid][$cat][$k])) { + unset($a->config[$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/PreloadConfigAdapter.php b/src/Core/Config/PreloadConfigAdapter.php new file mode 100644 index 0000000000..c10f2ee648 --- /dev/null +++ b/src/Core/Config/PreloadConfigAdapter.php @@ -0,0 +1,119 @@ + + */ +class PreloadConfigAdapter extends BaseObject implements IConfigAdapter +{ + private $config_loaded = false; + + public function __construct() + { + $this->load(); + } + + public function load($family = 'config') + { + if ($this->config_loaded) { + return; + } + + $a = self::getApp(); + + $configs = dba::select('config', ['cat', 'v', 'k']); + while ($config = dba::fetch($configs)) { + $cat = $config['cat']; + $k = $config['k']; + $value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']); + + if ($cat === 'config') { + $a->config[$k] = $value; + } else { + $a->config[$cat][$k] = $value; + } + } + dba::close($configs); + + $this->config_loaded = true; + } + + public function get($cat, $k, $default_value = null, $refresh = false) + { + $a = self::getApp(); + + $return = $default_value; + + if ($cat === 'config') { + if (isset($a->config[$k])) { + $return = $a->config[$k]; + } + } else { + if (isset($a->config[$cat][$k])) { + $return = $a->config[$cat][$k]; + } + } + + return $return; + } + + public function set($cat, $k, $value) + { + $a = self::getApp(); + + // 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, $k) === $compare_value) { + return true; + } + + if ($cat === 'config') { + $a->config[$k] = $value; + } else { + $a->config[$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; + } + + public function delete($cat, $k) + { + $a = self::getApp(); + + if ($cat === 'config') { + if (isset($a->config[$k])) { + unset($a->config[$k]); + } + } else { + if (isset($a->config[$cat][$k])) { + unset($a->config[$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 new file mode 100644 index 0000000000..002094a516 --- /dev/null +++ b/src/Core/Config/PreloadPConfigAdapter.php @@ -0,0 +1,102 @@ + + */ +class PreloadPConfigAdapter extends BaseObject implements IPConfigAdapter +{ + private $config_loaded = false; + + public function __construct($uid) + { + $this->load($uid, 'config'); + } + + public function load($uid, $family) + { + if ($this->config_loaded) { + return; + } + + $a = self::getApp(); + + $pconfigs = dba::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]); + while ($pconfig = dba::fetch($pconfigs)) { + $cat = $pconfig['cat']; + $k = $pconfig['k']; + $value = (preg_match("|^a:[0-9]+:{.*}$|s", $pconfig['v']) ? unserialize($pconfig['v']) : $pconfig['v']); + + $a->config[$uid][$cat][$k] = $value; + } + dba::close($pconfigs); + + $this->config_loaded = true; + } + + public function get($uid, $cat, $k, $default_value = null, $refresh = false) + { + $a = self::getApp(); + + $return = $default_value; + + if (isset($a->config[$uid][$cat][$k])) { + $return = $a->config[$uid][$cat][$k]; + } + + return $return; + } + + public function set($uid, $cat, $k, $value) + { + $a = self::getApp(); + + // 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, $k) === $compare_value) { + return true; + } + + $a->config[$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; + } + + public function delete($uid, $cat, $k) + { + $a = self::getApp(); + + if (!isset($a->config[$uid][$cat][$k])) { + return true; + } + + unset($a->config[$uid][$cat][$k]); + + $result = dba::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $k]); + + return $result; + } +}