--- /dev/null
+<?php\r
+\r
+namespace Friendica\Core\Config;\r
+\r
+/**\r
+ *\r
+ * @author Hypolite Petovan <mrpetovan@gmail.com>\r
+ */\r
+interface IConfigAdapter\r
+{\r
+ /**\r
+ * @brief Loads all configuration values into a cached storage.\r
+ *\r
+ * All configuration values of the system are stored in global cache\r
+ * which is available under the global variable $a->config\r
+ *\r
+ * @param string $cat The category of the configuration values to load\r
+ *\r
+ * @return void\r
+ */\r
+ public function load($cat = "config");\r
+\r
+ /**\r
+ * @brief Get a particular user's config variable given the category name\r
+ * ($family) and a key.\r
+ *\r
+ * Get a particular config value from the given category ($family)\r
+ * and the $key from a cached storage in $a->config[$uid].\r
+ * $instore is only used by the set_config function\r
+ * to determine if the key already exists in the DB\r
+ * If a key is found in the DB but doesn't exist in\r
+ * local config cache, pull it into the cache so we don't have\r
+ * to hit the DB again for this item.\r
+ *\r
+ * @param string $cat The category of the configuration value\r
+ * @param string $k The configuration key to query\r
+ * @param mixed $default_value optional, The value to return if key is not set (default: null)\r
+ * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false)\r
+ *\r
+ * @return mixed Stored value or null if it does not exist\r
+ */\r
+ public function get($cat, $k, $default_value = null, $refresh = false);\r
+\r
+ /**\r
+ * @brief Sets a configuration value for system config\r
+ *\r
+ * Stores a config value ($value) in the category ($family) under the key ($key)\r
+ * for the user_id $uid.\r
+ *\r
+ * Note: Please do not store booleans - convert to 0/1 integer values!\r
+ *\r
+ * @param string $family The category of the configuration value\r
+ * @param string $key The configuration key to set\r
+ * @param mixed $value The value to store\r
+ *\r
+ * @return mixed Stored $value or false if the database update failed\r
+ */\r
+ public function set($cat, $k, $value);\r
+\r
+ /**\r
+ * @brief Deletes the given key from the system configuration.\r
+ *\r
+ * Removes the configured value from the stored cache in $a->config\r
+ * and removes it from the database.\r
+ *\r
+ * @param string $cat The category of the configuration value\r
+ * @param string $k The configuration key to delete\r
+ *\r
+ * @return mixed\r
+ */\r
+ public function delete($cat, $k);\r
+}\r
--- /dev/null
+<?php\r
+\r
+/*\r
+ * To change this license header, choose License Headers in Project Properties.\r
+ * To change this template file, choose Tools | Templates\r
+ * and open the template in the editor.\r
+ */\r
+\r
+namespace Friendica\Core\Config;\r
+\r
+/**\r
+ *\r
+ * @author benlo\r
+ */\r
+interface IPConfigAdapter\r
+{\r
+ /**\r
+ * @brief Loads all configuration values of a user's config family into a cached storage.\r
+ *\r
+ * All configuration values of the given user are stored in global cache\r
+ * which is available under the global variable $a->config[$uid].\r
+ *\r
+ * @param string $uid The user_id\r
+ * @param string $cat The category of the configuration value\r
+ *\r
+ * @return void\r
+ */\r
+ public function load($uid, $cat);\r
+\r
+ /**\r
+ * @brief Get a particular user's config variable given the category name\r
+ * ($family) and a key.\r
+ *\r
+ * Get a particular user's config value from the given category ($family)\r
+ * and the $key from a cached storage in $a->config[$uid].\r
+ *\r
+ * @param string $uid The user_id\r
+ * @param string $cat The category of the configuration value\r
+ * @param string $k The configuration key to query\r
+ * @param mixed $default_value optional, The value to return if key is not set (default: null)\r
+ * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false)\r
+ *\r
+ * @return mixed Stored value or null if it does not exist\r
+ */\r
+ public function get($uid, $cat, $k, $default_value = null, $refresh = false);\r
+\r
+ /**\r
+ * @brief Sets a configuration value for a user\r
+ *\r
+ * Stores a config value ($value) in the category ($family) under the key ($key)\r
+ * for the user_id $uid.\r
+ *\r
+ * @note Please do not store booleans - convert to 0/1 integer values!\r
+ *\r
+ * @param string $uid The user_id\r
+ * @param string $cat The category of the configuration value\r
+ * @param string $k The configuration key to set\r
+ * @param string $value The value to store\r
+ *\r
+ * @return mixed Stored $value or false\r
+ */\r
+ public function set($uid, $cat, $k, $value);\r
+\r
+ /**\r
+ * @brief Deletes the given key from the users's configuration.\r
+ *\r
+ * Removes the configured value from the stored cache in $a->config[$uid]\r
+ * and removes it from the database.\r
+ *\r
+ * @param string $uid The user_id\r
+ * @param string $cat The category of the configuration value\r
+ * @param string $k The configuration key to delete\r
+ *\r
+ * @return mixed\r
+ */\r
+ public function delete($uid, $cat, $k);\r
+}\r
--- /dev/null
+<?php
+namespace Friendica\Core\Config;
+
+use dba;
+use Friendica\BaseObject;
+use Friendica\Database\DBM;
+
+require_once 'include/dba.php';
+
+/**
+ * JustInTime ConfigAdapter
+ *
+ * Default Config Adapter. Provides the best performance for pages loading few configuration variables.
+ *
+ * @author Hypolite Petovan <mrpetovan@gmail.com>
+ */
+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] === '!<unset>!') {
+ 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] = '!<unset>!';
+ $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;
+ }
+}
--- /dev/null
+<?php
+namespace Friendica\Core\Config;
+
+use dba;
+use Friendica\BaseObject;
+use Friendica\Database\DBM;
+
+require_once 'include/dba.php';
+
+/**
+ * JustInTime PConfigAdapter
+ *
+ * Default PConfig Adapter. Provides the best performance for pages loading few configuration variables.
+ *
+ * @author Hypolite Petovan <mrpetovan@gmail.com>
+ */
+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] = "!<unset>!";
+ }
+ 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] === '!<unset>!') {
+ return $default_value;
+ }
+ }
+
+ if (isset($a->config[$uid][$cat][$k])) {
+ if ($a->config[$uid][$cat][$k] === '!<unset>!') {
+ 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] = '!<unset>!';
+ $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;
+ }
+}
--- /dev/null
+<?php\r
+\r
+namespace Friendica\Core\Config;\r
+\r
+use dba;\r
+use Exception;\r
+use Friendica\BaseObject;\r
+\r
+require_once 'include/dba.php';\r
+\r
+/**\r
+ * Preload ConfigAdapter\r
+ *\r
+ * Minimize the number of database queries to retrieve configuration values at the cost of memory.\r
+ *\r
+ * @author Hypolite Petovan <mrpetovan@gmail.com>\r
+ */\r
+class PreloadConfigAdapter extends BaseObject implements IConfigAdapter\r
+{\r
+ private $config_loaded = false;\r
+\r
+ public function __construct()\r
+ {\r
+ $this->load();\r
+ }\r
+\r
+ public function load($family = 'config')\r
+ {\r
+ if ($this->config_loaded) {\r
+ return;\r
+ }\r
+\r
+ $a = self::getApp();\r
+\r
+ $configs = dba::select('config', ['cat', 'v', 'k']);\r
+ while ($config = dba::fetch($configs)) {\r
+ $cat = $config['cat'];\r
+ $k = $config['k'];\r
+ $value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']);\r
+\r
+ if ($cat === 'config') {\r
+ $a->config[$k] = $value;\r
+ } else {\r
+ $a->config[$cat][$k] = $value;\r
+ }\r
+ }\r
+ dba::close($configs);\r
+\r
+ $this->config_loaded = true;\r
+ }\r
+\r
+ public function get($cat, $k, $default_value = null, $refresh = false)\r
+ {\r
+ $a = self::getApp();\r
+\r
+ $return = $default_value;\r
+\r
+ if ($cat === 'config') {\r
+ if (isset($a->config[$k])) {\r
+ $return = $a->config[$k];\r
+ }\r
+ } else {\r
+ if (isset($a->config[$cat][$k])) {\r
+ $return = $a->config[$cat][$k];\r
+ }\r
+ }\r
+\r
+ return $return;\r
+ }\r
+\r
+ public function set($cat, $k, $value)\r
+ {\r
+ $a = self::getApp();\r
+\r
+ // We store our setting values as strings.\r
+ // So we have to do the conversion here so that the compare below works.\r
+ // The exception are array values.\r
+ $compare_value = !is_array($value) ? (string)$value : $value;\r
+\r
+ if ($this->get($cat, $k) === $compare_value) {\r
+ return true;\r
+ }\r
+\r
+ if ($cat === 'config') {\r
+ $a->config[$k] = $value;\r
+ } else {\r
+ $a->config[$cat][$k] = $value;\r
+ }\r
+\r
+ // manage array value\r
+ $dbvalue = is_array($value) ? serialize($value) : $value;\r
+\r
+ $result = dba::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $k], true);\r
+ if (!$result) {\r
+ throw new Exception('Unable to store config value in [' . $cat . '][' . $k . ']');\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
+ public function delete($cat, $k)\r
+ {\r
+ $a = self::getApp();\r
+\r
+ if ($cat === 'config') {\r
+ if (isset($a->config[$k])) {\r
+ unset($a->config[$k]);\r
+ }\r
+ } else {\r
+ if (isset($a->config[$cat][$k])) {\r
+ unset($a->config[$cat][$k]);\r
+ }\r
+ }\r
+\r
+ $result = dba::delete('config', ['cat' => $cat, 'k' => $k]);\r
+\r
+ return $result;\r
+ }\r
+}\r
--- /dev/null
+<?php\r
+\r
+namespace Friendica\Core\Config;\r
+\r
+use dba;\r
+use Exception;\r
+use Friendica\BaseObject;\r
+\r
+require_once 'include/dba.php';\r
+\r
+/**\r
+ * Preload PConfigAdapter\r
+ *\r
+ * Minimize the number of database queries to retrieve configuration values at the cost of memory.\r
+ *\r
+ * @author Hypolite Petovan <mrpetovan@gmail.com>\r
+ */\r
+class PreloadPConfigAdapter extends BaseObject implements IPConfigAdapter\r
+{\r
+ private $config_loaded = false;\r
+\r
+ public function __construct($uid)\r
+ {\r
+ $this->load($uid, 'config');\r
+ }\r
+\r
+ public function load($uid, $family)\r
+ {\r
+ if ($this->config_loaded) {\r
+ return;\r
+ }\r
+\r
+ $a = self::getApp();\r
+\r
+ $pconfigs = dba::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]);\r
+ while ($pconfig = dba::fetch($pconfigs)) {\r
+ $cat = $pconfig['cat'];\r
+ $k = $pconfig['k'];\r
+ $value = (preg_match("|^a:[0-9]+:{.*}$|s", $pconfig['v']) ? unserialize($pconfig['v']) : $pconfig['v']);\r
+\r
+ $a->config[$uid][$cat][$k] = $value;\r
+ }\r
+ dba::close($pconfigs);\r
+\r
+ $this->config_loaded = true;\r
+ }\r
+\r
+ public function get($uid, $cat, $k, $default_value = null, $refresh = false)\r
+ {\r
+ $a = self::getApp();\r
+\r
+ $return = $default_value;\r
+\r
+ if (isset($a->config[$uid][$cat][$k])) {\r
+ $return = $a->config[$uid][$cat][$k];\r
+ }\r
+\r
+ return $return;\r
+ }\r
+\r
+ public function set($uid, $cat, $k, $value)\r
+ {\r
+ $a = self::getApp();\r
+\r
+ // We store our setting values as strings.\r
+ // So we have to do the conversion here so that the compare below works.\r
+ // The exception are array values.\r
+ $compare_value = !is_array($value) ? (string)$value : $value;\r
+\r
+ if ($this->get($uid, $cat, $k) === $compare_value) {\r
+ return true;\r
+ }\r
+\r
+ $a->config[$uid][$cat][$k] = $value;\r
+\r
+ // manage array value\r
+ $dbvalue = is_array($value) ? serialize($value) : $value;\r
+\r
+ $result = dba::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $k], true);\r
+\r
+ if (!$result) {\r
+ throw new Exception('Unable to store config value in [' . $uid . '][' . $cat . '][' . $k . ']');\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
+ public function delete($uid, $cat, $k)\r
+ {\r
+ $a = self::getApp();\r
+\r
+ if (!isset($a->config[$uid][$cat][$k])) {\r
+ return true;\r
+ }\r
+\r
+ unset($a->config[$uid][$cat][$k]);\r
+\r
+ $result = dba::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $k]);\r
+\r
+ return $result;\r
+ }\r
+}\r