]> git.mxchange.org Git - friendica.git/commitdiff
Add Config adapter interfaces/classes
authorHypolite Petovan <mrpetovan@gmail.com>
Sat, 3 Mar 2018 17:09:12 +0000 (12:09 -0500)
committerHypolite Petovan <mrpetovan@gmail.com>
Wed, 7 Mar 2018 00:52:36 +0000 (19:52 -0500)
src/Core/Config/IConfigAdapter.php [new file with mode: 0644]
src/Core/Config/IPConfigAdapter.php [new file with mode: 0644]
src/Core/Config/JITConfigAdapter.php [new file with mode: 0644]
src/Core/Config/JITPConfigAdapter.php [new file with mode: 0644]
src/Core/Config/PreloadConfigAdapter.php [new file with mode: 0644]
src/Core/Config/PreloadPConfigAdapter.php [new file with mode: 0644]

diff --git a/src/Core/Config/IConfigAdapter.php b/src/Core/Config/IConfigAdapter.php
new file mode 100644 (file)
index 0000000..ee5ca3c
--- /dev/null
@@ -0,0 +1,72 @@
+<?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
diff --git a/src/Core/Config/IPConfigAdapter.php b/src/Core/Config/IPConfigAdapter.php
new file mode 100644 (file)
index 0000000..f78654d
--- /dev/null
@@ -0,0 +1,77 @@
+<?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
diff --git a/src/Core/Config/JITConfigAdapter.php b/src/Core/Config/JITConfigAdapter.php
new file mode 100644 (file)
index 0000000..1bc3bf5
--- /dev/null
@@ -0,0 +1,132 @@
+<?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;
+       }
+}
diff --git a/src/Core/Config/JITPConfigAdapter.php b/src/Core/Config/JITPConfigAdapter.php
new file mode 100644 (file)
index 0000000..27f2ed8
--- /dev/null
@@ -0,0 +1,117 @@
+<?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;
+       }
+}
diff --git a/src/Core/Config/PreloadConfigAdapter.php b/src/Core/Config/PreloadConfigAdapter.php
new file mode 100644 (file)
index 0000000..c10f2ee
--- /dev/null
@@ -0,0 +1,119 @@
+<?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
diff --git a/src/Core/Config/PreloadPConfigAdapter.php b/src/Core/Config/PreloadPConfigAdapter.php
new file mode 100644 (file)
index 0000000..002094a
--- /dev/null
@@ -0,0 +1,102 @@
+<?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