]> git.mxchange.org Git - friendica.git/commitdiff
Merge pull request #7372 from nupplaphil/task/simplify_config
authorHypolite Petovan <hypolite@mrpetovan.com>
Sun, 14 Jul 2019 23:05:09 +0000 (19:05 -0400)
committerGitHub <noreply@github.com>
Sun, 14 Jul 2019 23:05:09 +0000 (19:05 -0400)
Refactor Configuration (Simplify Config Part 3)

25 files changed:
include/api.php
src/Core/Config/Adapter/IConfigAdapter.php [deleted file]
src/Core/Config/Adapter/JITConfigAdapter.php [deleted file]
src/Core/Config/Adapter/PreloadConfigAdapter.php [deleted file]
src/Core/Config/Cache/ConfigCache.php
src/Core/Config/Cache/PConfigCache.php
src/Core/Config/Configuration.php
src/Core/Config/JitConfiguration.php [new file with mode: 0644]
src/Core/Config/PConfiguration.php
src/Core/Config/PreloadConfiguration.php [new file with mode: 0644]
src/Database/Database.php
src/Factory/ConfigFactory.php
src/Factory/DependencyFactory.php
src/Model/Config/Config.php [new file with mode: 0644]
src/Model/Config/DbaConfig.php [new file with mode: 0644]
tests/DatabaseTest.php
tests/Util/AppMockTrait.php
tests/include/ApiTest.php
tests/src/Core/Config/Cache/ConfigCacheTest.php
tests/src/Core/Config/Cache/PConfigCacheTest.php
tests/src/Core/Config/ConfigurationTest.php
tests/src/Core/Config/JitConfigurationTest.php [new file with mode: 0644]
tests/src/Core/Config/PreloadConfigurationTest.php [new file with mode: 0644]
tests/src/Database/DBATest.php
tests/src/Database/DBStructureTest.php

index 6c6e6f7dcdcc5460c5be2591faffa16f5694df6a..59a95659fbd921e19ce1f2de9360e8b18e8dc5e3 100644 (file)
@@ -4207,7 +4207,7 @@ function api_fr_photos_list($type)
        $r = q(
                "SELECT `resource-id`, MAX(scale) AS `scale`, `album`, `filename`, `type`, MAX(`created`) AS `created`,
                MAX(`edited`) AS `edited`, MAX(`desc`) AS `desc` FROM `photo`
-               WHERE `uid` = %d AND `album` != 'Contact Photos' GROUP BY `resource-id`",
+               WHERE `uid` = %d AND `album` != 'Contact Photos' GROUP BY `resource-id`, `album`, `filename`, `type`",
                intval(local_user())
        );
        $typetoext = [
@@ -4888,7 +4888,9 @@ function prepare_photo_data($type, $scale, $photo_id)
                "SELECT %s `resource-id`, `created`, `edited`, `title`, `desc`, `album`, `filename`,
                                        `type`, `height`, `width`, `datasize`, `profile`, `allow_cid`, `deny_cid`, `allow_gid`, `deny_gid`,
                                        MIN(`scale`) AS `minscale`, MAX(`scale`) AS `maxscale`
-                       FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' %s GROUP BY `resource-id`",
+                       FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' %s GROUP BY 
+                              `resource-id`, `created`, `edited`, `title`, `desc`, `album`, `filename`,
+                              `type`, `height`, `width`, `datasize`, `profile`, `allow_cid`, `deny_cid`, `allow_gid`, `deny_gid`",
                $data_sql,
                intval(local_user()),
                DBA::escape($photo_id),
diff --git a/src/Core/Config/Adapter/IConfigAdapter.php b/src/Core/Config/Adapter/IConfigAdapter.php
deleted file mode 100644 (file)
index 892c476..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-
-namespace Friendica\Core\Config\Adapter;
-
-/**
- *
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-interface IConfigAdapter
-{
-       /**
-        * Loads all configuration values and returns the loaded category as an array.
-        *
-        * @param string  $cat The category of the configuration values to load
-        *
-        * @return array
-        */
-       public function load($cat = "config");
-
-       /**
-        * Get a particular system-wide config variable given the category name
-        * ($family) and a key.
-        *
-        * Note: Boolean variables are defined as 0/1 in the database
-        *
-        * @param string  $cat The category of the configuration value
-        * @param string  $key The configuration key to query
-        *
-        * @return null|mixed Stored value or null if it does not exist
-        */
-       public function get($cat, $key);
-
-       /**
-        * Stores a config value ($value) in the category ($family) 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);
-
-       /**
-        * 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 $key The configuration key to delete
-        *
-        * @return bool Operation success
-        */
-       public function delete($cat, $key);
-
-       /**
-        * Checks, if the current adapter is connected to the backend
-        *
-        * @return bool
-        */
-       public function isConnected();
-
-       /**
-        * Checks, if a config key ($key) in the category ($cat) is already loaded.
-        *
-        * @param string $cat The configuration category
-        * @param string $key The configuration key
-        *
-        * @return bool
-        */
-       public function isLoaded($cat, $key);
-}
diff --git a/src/Core/Config/Adapter/JITConfigAdapter.php b/src/Core/Config/Adapter/JITConfigAdapter.php
deleted file mode 100644 (file)
index d125f7d..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-<?php
-namespace Friendica\Core\Config\Adapter;
-
-use Friendica\Database\DBA;
-
-/**
- * JustInTime Configuration Adapter
- *
- * Default Config Adapter. Provides the best performance for pages loading few configuration variables.
- *
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-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'];
-                       $value = $this->toConfigValue($config['v']);
-
-                       // The value was in the db, so don't check it again (unless you have to)
-                       $this->in_db[$cat][$key] = true;
-
-                       // just save it in case it is set
-                       if (isset($value)) {
-                               $return[$key] = $value;
-                       }
-               }
-               DBA::close($configs);
-
-               return [$cat => $return];
-       }
-
-       /**
-        * {@inheritdoc}
-        *
-        * @param bool $mark if true, mark the selection of the current cat/key pair
-        */
-       public function get($cat, $key, $mark = true)
-       {
-               if (!$this->isConnected()) {
-                       return null;
-               }
-
-               // The value got checked, so mark it to avoid checking it over and over again
-               if ($mark) {
-                       $this->in_db[$cat][$key] = true;
-               }
-
-               $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]);
-               if (DBA::isResult($config)) {
-                       $value = $this->toConfigValue($config['v']);
-
-                       // just return it in case it is set
-                       if (isset($value)) {
-                               return $value;
-                       }
-               }
-
-               return null;
-       }
-
-       /**
-        * {@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.
-               $compare_value = (!is_array($value) ? (string)$value : $value);
-               $stored_value = $this->get($cat, $key, false);
-
-               if (!isset($this->in_db[$cat])) {
-                       $this->in_db[$cat] = [];
-               }
-               if (!isset($this->in_db[$cat][$key])) {
-                       $this->in_db[$cat][$key] = false;
-               }
-
-               if (isset($stored_value) && ($stored_value === $compare_value) && $this->in_db[$cat][$key]) {
-                       return true;
-               }
-
-               $dbvalue = $this->toDbValue($value);
-
-               $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;
-       }
-
-       /**
-        * {@inheritdoc}
-        */
-       public function isLoaded($cat, $key)
-       {
-               if (!$this->isConnected()) {
-                       return false;
-               }
-
-               return (isset($this->in_db[$cat][$key])) && $this->in_db[$cat][$key];
-       }
-}
diff --git a/src/Core/Config/Adapter/PreloadConfigAdapter.php b/src/Core/Config/Adapter/PreloadConfigAdapter.php
deleted file mode 100644 (file)
index c691c88..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php
-
-namespace Friendica\Core\Config\Adapter;
-
-use Friendica\Database\DBA;
-
-/**
- * Preload Configuration Adapter
- *
- * Minimizes the number of database queries to retrieve configuration values at the cost of memory.
- *
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-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)) {
-                       $value = $this->toConfigValue($config['v']);
-                       if (isset($value)) {
-                               $return[$config['cat']][$config['k']] = $value;
-                       }
-               }
-               DBA::close($configs);
-
-               $this->config_loaded = true;
-
-               return $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)) {
-                       $value = $this->toConfigValue($config['v']);
-
-                       if (isset($value)) {
-                               return $value;
-                       }
-               }
-
-               return null;
-       }
-
-       /**
-        * {@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;
-               $stored_value = $this->get($cat, $key);
-
-               if (isset($stored_value) && $stored_value === $compare_value) {
-                       return true;
-               }
-
-               $dbvalue = $this->toDbValue($value);
-
-               return DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true);
-       }
-
-       /**
-        * {@inheritdoc}
-        */
-       public function delete($cat, $key)
-       {
-               if (!$this->isConnected()) {
-                       return false;
-               }
-
-               return DBA::delete('config', ['cat' => $cat, 'k' => $key]);
-       }
-
-       /**
-        * {@inheritdoc}
-        */
-       public function isLoaded($cat, $key)
-       {
-               if (!$this->isConnected()) {
-                       return false;
-               }
-
-               return $this->config_loaded;
-       }
-}
index b8175452bf4b8181c44d9db3c9d6ccd9f1ac7ef9..3119b5db123c4d1665c587b907cb6363fd8d0d56 100644 (file)
@@ -25,7 +25,7 @@ class ConfigCache
         * @param array $config             A initial config array
         * @param bool  $hidePasswordOutput True, if cache variables should take extra care of password values
         */
-       public function __construct(array $config = [], $hidePasswordOutput = true)
+       public function __construct(array $config = [], bool $hidePasswordOutput = true)
        {
                $this->hidePasswordOutput = $hidePasswordOutput;
                $this->load($config);
@@ -38,7 +38,7 @@ class ConfigCache
         * @param array $config
         * @param bool  $overwrite Force value overwrite if the config key already exists
         */
-       public function load(array $config, $overwrite = false)
+       public function load(array $config, bool $overwrite = false)
        {
                $categories = array_keys($config);
 
@@ -68,7 +68,7 @@ class ConfigCache
         *
         * @return null|mixed Returns the value of the Config entry or null if not set
         */
-       public function get($cat, $key = null)
+       public function get(string $cat, string $key = null)
        {
                if (isset($this->config[$cat][$key])) {
                        return $this->config[$cat][$key];
@@ -82,14 +82,14 @@ class ConfigCache
        /**
         * Sets a default value in the config cache. Ignores already existing keys.
         *
-        * @param string $cat Config category
-        * @param string $k   Config key
-        * @param mixed  $v   Default value to set
+        * @param string $cat   Config category
+        * @param string $key   Config key
+        * @param mixed  $value Default value to set
         */
-       private function setDefault($cat, $k, $v)
+       private function setDefault(string $cat, string $key, $value)
        {
-               if (!isset($this->config[$cat][$k])) {
-                       $this->set($cat, $k, $v);
+               if (!isset($this->config[$cat][$key])) {
+                       $this->set($cat, $key, $value);
                }
        }
 
@@ -102,7 +102,7 @@ class ConfigCache
         *
         * @return bool True, if the value is set
         */
-       public function set($cat, $key, $value)
+       public function set(string $cat, string $key, $value)
        {
                if (!isset($this->config[$cat])) {
                        $this->config[$cat] = [];
@@ -111,7 +111,7 @@ class ConfigCache
                if ($this->hidePasswordOutput &&
                    $key == 'password' &&
                    is_string($value)) {
-                       $this->config[$cat][$key] = new HiddenString((string) $value);
+                       $this->config[$cat][$key] = new HiddenString((string)$value);
                } else {
                        $this->config[$cat][$key] = $value;
                }
@@ -126,7 +126,7 @@ class ConfigCache
         *
         * @return bool true, if deleted
         */
-       public function delete($cat, $key)
+       public function delete(string $cat, string $key)
        {
                if (isset($this->config[$cat][$key])) {
                        unset($this->config[$cat][$key]);
index 98adfa2ce1ce5171e2fb1f0e0fbfb2824e0b67ca..b03d86f41ee63faf14c997058a46b8b7b8393fd4 100644 (file)
@@ -20,9 +20,9 @@ class PConfigCache
        private $hidePasswordOutput;
 
        /**
-        * @param bool  $hidePasswordOutput True, if cache variables should take extra care of password values
+        * @param bool $hidePasswordOutput True, if cache variables should take extra care of password values
         */
-       public function __construct($hidePasswordOutput = true)
+       public function __construct(bool $hidePasswordOutput = true)
        {
                $this->hidePasswordOutput = $hidePasswordOutput;
        }
@@ -34,7 +34,7 @@ class PConfigCache
         * @param int   $uid
         * @param array $config
         */
-       public function load($uid, array $config)
+       public function load(int $uid, array $config)
        {
                $categories = array_keys($config);
 
@@ -56,13 +56,13 @@ class PConfigCache
        /**
         * Retrieves a value from the user config cache
         *
-        * @param int    $uid     User Id
-        * @param string $cat     Config category
-        * @param string $key     Config key
+        * @param int    $uid User Id
+        * @param string $cat Config category
+        * @param string $key Config key
         *
         * @return null|string The value of the config entry or null if not set
         */
-       public function get($uid, $cat, $key = null)
+       public function get(int $uid, string $cat, string $key = null)
        {
                if (isset($this->config[$uid][$cat][$key])) {
                        return $this->config[$uid][$cat][$key];
@@ -85,7 +85,7 @@ class PConfigCache
         *
         * @return bool Set successful
         */
-       public function set($uid, $cat, $key, $value)
+       public function set(int $uid, string $cat, string $key, $value)
        {
                if (!isset($this->config[$uid]) || !is_array($this->config[$uid])) {
                        $this->config[$uid] = [];
@@ -98,7 +98,7 @@ class PConfigCache
                if ($this->hidePasswordOutput &&
                    $key == 'password' &&
                    !empty($value) && is_string($value)) {
-                       $this->config[$uid][$cat][$key] = new HiddenString((string) $value);
+                       $this->config[$uid][$cat][$key] = new HiddenString((string)$value);
                } else {
                        $this->config[$uid][$cat][$key] = $value;
                }
@@ -116,7 +116,7 @@ class PConfigCache
         *
         * @return bool true, if deleted
         */
-       public function delete($uid, $cat, $key)
+       public function delete(int $uid, string $cat, string $key)
        {
                if (isset($this->config[$uid][$cat][$key])) {
                        unset($this->config[$uid][$cat][$key]);
index 1489d91de04823104178c0f954f6d04e5249e212..37b947d11bf7463fd8a131656e07572b323e7390 100644 (file)
@@ -2,34 +2,34 @@
 
 namespace Friendica\Core\Config;
 
+use Friendica\Model;
+
 /**
  * This class is responsible for all system-wide configuration values in Friendica
  * There are two types of storage
- * - The Config-Files    (loaded into the FileCache @see Cache\IConfigCache )
- * - The Config-DB-Table (per Config-DB-adapter @see Adapter\IConfigAdapter )
+ * - The Config-Files    (loaded into the FileCache @see Cache\ConfigCache )
+ * - The Config-DB-Table (per Config-DB-model @see Model\Config\Config )
  */
-class Configuration
+abstract class Configuration
 {
        /**
         * @var Cache\ConfigCache
         */
-       private $configCache;
+       protected $configCache;
 
        /**
-        * @var Adapter\IConfigAdapter
+        * @var Model\Config\Config
         */
-       private $configAdapter;
+       protected $configModel;
 
        /**
-        * @param Cache\ConfigCache     $configCache   The configuration cache (based on the config-files)
-        * @param Adapter\IConfigAdapter $configAdapter The configuration DB-backend
+        * @param Cache\ConfigCache  $configCache The configuration cache (based on the config-files)
+        * @param Model\Config\Config $configModel The configuration model
         */
-       public function __construct(Cache\ConfigCache $configCache, Adapter\IConfigAdapter $configAdapter)
+       public function __construct(Cache\ConfigCache $configCache, Model\Config\Config $configModel)
        {
                $this->configCache = $configCache;
-               $this->configAdapter = $configAdapter;
-
-               $this->load();
+               $this->configModel = $configModel;
        }
 
        /**
@@ -51,16 +51,7 @@ class Configuration
         *
         * @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);
-       }
+       abstract public function load(string $cat = 'config');
 
        /**
         * @brief Get a particular user's config variable given the category name
@@ -77,26 +68,7 @@ class Configuration
         *
         * @return mixed Stored value or null if it does not exist
         */
-       public function get($cat, $key, $default_value = null, $refresh = false)
-       {
-               // if the value isn't loaded or refresh is needed, load it to the cache
-               if ($this->configAdapter->isConnected() &&
-                       (!$this->configAdapter->isLoaded($cat, $key) ||
-                       $refresh)) {
-
-                       $dbvalue = $this->configAdapter->get($cat, $key);
-
-                       if (isset($dbvalue)) {
-                               $this->configCache->set($cat, $key, $dbvalue);
-                               unset($dbvalue);
-                       }
-               }
-
-               // use the config cache for return
-               $result = $this->configCache->get($cat, $key);
-
-               return (isset($result)) ? $result : $default_value;
-       }
+       abstract public function get(string $cat, string $key, $default_value = null, bool $refresh = false);
 
        /**
         * @brief Sets a configuration value for system config
@@ -111,20 +83,7 @@ class Configuration
         *
         * @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;
-       }
+       abstract public function set(string $cat, string $key, $value);
 
        /**
         * @brief Deletes the given key from the system configuration.
@@ -137,16 +96,5 @@ class Configuration
         *
         * @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;
-       }
+       abstract public function delete(string $cat, string $key);
 }
diff --git a/src/Core/Config/JitConfiguration.php b/src/Core/Config/JitConfiguration.php
new file mode 100644 (file)
index 0000000..40aa5d6
--- /dev/null
@@ -0,0 +1,128 @@
+<?php
+
+namespace Friendica\Core\Config;
+
+use Friendica\Model;
+
+/**
+ * This class implements the Just-In-Time configuration, which will cache
+ * config values in a cache, once they are retrieved.
+ *
+ * Default Configuration type.
+ * Provides the best performance for pages loading few configuration variables.
+ */
+class JitConfiguration extends Configuration
+{
+       /** @var array */
+       private $in_db;
+
+       /**
+        * @param Cache\ConfigCache   $configCache The configuration cache (based on the config-files)
+        * @param Model\Config\Config $configModel The configuration model
+        */
+       public function __construct(Cache\ConfigCache $configCache, Model\Config\Config $configModel)
+       {
+               parent::__construct($configCache, $configModel);
+               $this->in_db = [];
+
+               // take the values of the given cache instead of loading them from the model again
+               $preSet = $configCache->getAll();
+               if (!empty($preSet)) {
+                       foreach ($preSet as $cat => $data) {
+                               foreach ($data as $key => $value) {
+                                       $this->in_db[$cat][$key] = true;
+                               }
+                       }
+               }
+
+               $this->load();
+       }
+
+       /**
+        * {@inheritDoc}
+        *
+        */
+       public function load(string $cat = 'config')
+       {
+               // If not connected, do nothing
+               if (!$this->configModel->isConnected()) {
+                       return;
+               }
+
+               $config = $this->configModel->load($cat);
+
+               if (!empty($config[$cat])) {
+                       foreach ($config[$cat] as $key => $value) {
+                               $this->in_db[$cat][$key] = true;
+                       }
+               }
+
+               // load the whole category out of the DB into the cache
+               $this->configCache->load($config, true);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public function get(string $cat, string $key, $default_value = null, bool $refresh = false)
+       {
+               // if the value isn't loaded or refresh is needed, load it to the cache
+               if ($this->configModel->isConnected() &&
+                   (empty($this->in_db[$cat][$key]) ||
+                    $refresh)) {
+
+                       $dbvalue = $this->configModel->get($cat, $key);
+
+                       if (isset($dbvalue)) {
+                               $this->configCache->set($cat, $key, $dbvalue);
+                               unset($dbvalue);
+                               $this->in_db[$cat][$key] = true;
+                       }
+               }
+
+               // use the config cache for return
+               $result = $this->configCache->get($cat, $key);
+
+               return (isset($result)) ? $result : $default_value;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public function set(string $cat, string $key, $value)
+       {
+               // set the cache first
+               $cached = $this->configCache->set($cat, $key, $value);
+
+               // If there is no connected adapter, we're finished
+               if (!$this->configModel->isConnected()) {
+                       return $cached;
+               }
+
+               $stored = $this->configModel->set($cat, $key, $value);
+
+               $this->in_db[$cat][$key] = $stored;
+
+               return $cached && $stored;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public function delete(string $cat, string $key)
+       {
+               $cacheRemoved = $this->configCache->delete($cat, $key);
+
+               if (isset($this->in_db[$cat][$key])) {
+                       unset($this->in_db[$cat][$key]);
+               }
+
+               if (!$this->configModel->isConnected()) {
+                       return $cacheRemoved;
+               }
+
+               $storeRemoved = $this->configModel->delete($cat, $key);
+
+               return $cacheRemoved || $storeRemoved;
+       }
+}
index 79ed1a61e6d0fe6eaeb429b3ed08e42939d02bb0..e69981c08c182543079b96d93de0b30cc2a84dd5 100644 (file)
@@ -6,7 +6,7 @@ namespace Friendica\Core\Config;
  * This class is responsible for the user-specific configuration values in Friendica
  * The values are set through the Config-DB-Table (per Config-DB-adapter @see Adapter\IPConfigAdapter )
  *
- * The configuration cache (@see Cache\IPConfigCache ) is used for temporary caching of database calls. This will
+ * The configuration cache (@see Cache\PConfigCache ) is used for temporary caching of database calls. This will
  * increase the performance.
  */
 class PConfiguration
@@ -35,7 +35,7 @@ class PConfiguration
         * @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 )
+        * the cache ( @see PConfigCache )
         *
         * @param string $uid The user_id
         * @param string $cat The category of the configuration value
@@ -59,7 +59,7 @@ class PConfiguration
         *
         * 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 ).
+        * (@see IConfigAdapter ) or from the $this->configCache (@see PConfigCache ).
         *
         * @param string  $uid           The user_id
         * @param string  $cat           The category of the configuration value
diff --git a/src/Core/Config/PreloadConfiguration.php b/src/Core/Config/PreloadConfiguration.php
new file mode 100644 (file)
index 0000000..b5823c6
--- /dev/null
@@ -0,0 +1,116 @@
+<?php
+
+namespace Friendica\Core\Config;
+
+use Friendica\Model;
+
+/**
+ * This class implements the preload Time configuration, which will cache
+ * all config values per call in a cache.
+ *
+ * Minimizes the number of database queries to retrieve configuration values at the cost of memory.
+ */
+class PreloadConfiguration extends Configuration
+{
+       /** @var bool */
+       private $config_loaded;
+
+       /**
+        * @param Cache\ConfigCache   $configCache The configuration cache (based on the config-files)
+        * @param Model\Config\Config $configModel The configuration model
+        */
+       public function __construct(Cache\ConfigCache $configCache, Model\Config\Config $configModel)
+       {
+               parent::__construct($configCache, $configModel);
+               $this->config_loaded = false;
+
+               $this->load();
+       }
+
+       /**
+        * {@inheritDoc}
+        *
+        * This loads all config values everytime load is called
+        *
+        */
+       public function load(string $cat = 'config')
+       {
+               // Don't load the whole configuration twice
+               if ($this->config_loaded) {
+                       return;
+               }
+
+               // If not connected, do nothing
+               if (!$this->configModel->isConnected()) {
+                       return;
+               }
+
+               $config              = $this->configModel->load();
+               $this->config_loaded = true;
+
+               // load the whole category out of the DB into the cache
+               $this->configCache->load($config, true);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public function get(string $cat, string $key, $default_value = null, bool $refresh = false)
+       {
+               if ($refresh) {
+                       if ($this->configModel->isConnected()) {
+                               $config = $this->configModel->get($cat, $key);
+                               if (isset($config)) {
+                                       $this->configCache->set($cat, $key, $config);
+                               }
+                       }
+               }
+
+               // use the config cache for return
+               $result = $this->configCache->get($cat, $key);
+
+               return (isset($result)) ? $result : $default_value;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public function set(string $cat, string $key, $value)
+       {
+               if (!$this->config_loaded) {
+                       $this->load();
+               }
+
+               // set the cache first
+               $cached = $this->configCache->set($cat, $key, $value);
+
+               // If there is no connected adapter, we're finished
+               if (!$this->configModel->isConnected()) {
+                       return $cached;
+               }
+
+               $stored = $this->configModel->set($cat, $key, $value);
+
+               return $cached && $stored;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public function delete(string $cat, string $key)
+       {
+               if ($this->config_loaded) {
+                       $this->load();
+               }
+
+               $cacheRemoved = $this->configCache->delete($cat, $key);
+
+               if (!$this->configModel->isConnected()) {
+                       return $cacheRemoved;
+               }
+
+               $storeRemoved = $this->configModel->delete($cat, $key);
+
+               return $cacheRemoved || $storeRemoved;
+       }
+}
index 14381ae922d791d8a1079a42cfde9cfa9317575a..0d1540f7cd94fca392d76c194e65ead662c84723 100644 (file)
@@ -161,6 +161,15 @@ class Database
                $this->logger = $logger;
        }
 
+       /**
+        * Sets the profiler for DBA
+        *
+        * @param Profiler $profiler
+        */
+       public function setProfiler(Profiler $profiler)
+       {
+               $this->profiler = $profiler;
+       }
        /**
         * Disconnects the current database connection
         */
@@ -323,6 +332,11 @@ class Database
                }
        }
 
+       public function isConnected()
+       {
+               return $this->connected;
+       }
+
        public function connected()
        {
                $connected = false;
index 7764d89900417c3d2499b3d171b15222b30197ac..5a24f86283b4817d4b08e45457ee59220205a92f 100644 (file)
@@ -6,6 +6,7 @@ use Friendica\Core;
 use Friendica\Core\Config;
 use Friendica\Core\Config\Adapter;
 use Friendica\Core\Config\Cache;
+use Friendica\Model\Config\Config as ConfigModel;
 use Friendica\Util\Config\ConfigFileLoader;
 
 class ConfigFactory
@@ -24,19 +25,19 @@ class ConfigFactory
        }
 
        /**
-        * @param Cache\ConfigCache $configCache The config cache
+        * @param Cache\ConfigCache $configCache The config cache of this adapter
+        * @param ConfigModel $configModel The configuration model
         *
         * @return Config\Configuration
         */
-       public static function createConfig(Cache\ConfigCache $configCache)
+       public static function createConfig(Cache\ConfigCache $configCache, ConfigModel $configModel)
        {
                if ($configCache->get('system', 'config_adapter') === 'preload') {
-                       $configAdapter = new Adapter\PreloadConfigAdapter();
+                       $configuration = new Config\PreloadConfiguration($configCache, $configModel);
                } else {
-                       $configAdapter = new Adapter\JITConfigAdapter();
+                       $configuration = new Config\JitConfiguration($configCache, $configModel);
                }
 
-               $configuration = new Config\Configuration($configCache, $configAdapter);
 
                // Set the config in the static container for legacy usage
                Core\Config::init($configuration);
index 656a255b2ba2e4b782fb32b87cf79938cbfc4f53..36ab20a0134b2e9cb02ebcaae081ddde282bf6bb 100644 (file)
@@ -31,7 +31,8 @@ class DependencyFactory
                $configCache = Factory\ConfigFactory::createCache($configLoader);
                $profiler = Factory\ProfilerFactory::create($configCache);
                $database = Factory\DBFactory::init($configCache, $profiler, $_SERVER);
-               $config = Factory\ConfigFactory::createConfig($configCache);
+               $configModel = new \Friendica\Model\Config\Config($database);
+               $config = Factory\ConfigFactory::createConfig($configCache, $configModel);
                // needed to call PConfig::init()
                Factory\ConfigFactory::createPConfig($configCache, new PConfigCache());
                $logger = Factory\LoggerFactory::create($channel, $database, $config, $profiler);
diff --git a/src/Model/Config/Config.php b/src/Model/Config/Config.php
new file mode 100644 (file)
index 0000000..aa81f1c
--- /dev/null
@@ -0,0 +1,131 @@
+<?php
+
+namespace Friendica\Model\Config;
+
+
+/**
+ * The Config model backend, which is using the general DB-model backend for configs
+ */
+class Config extends DbaConfig
+{
+       /**
+        * Loads all configuration values and returns the loaded category as an array.
+        *
+        * @param string|null $cat The category of the configuration values to load
+        *
+        * @return array The config array
+        *
+        * @throws \Exception In case DB calls are invalid
+        */
+       public function load(string $cat = null)
+       {
+               $return = [];
+
+               if (empty($cat)) {
+                       $configs = $this->dba->select('config', ['cat', 'v', 'k']);
+               } else {
+                       $configs = $this->dba->select('config', ['cat', 'v', 'k'], ['cat' => $cat]);
+               }
+
+               while ($config = $this->dba->fetch($configs)) {
+
+                       $key   = $config['k'];
+                       $value = $this->toConfigValue($config['v']);
+
+                       // just save it in case it is set
+                       if (isset($value)) {
+                               $return[$config['cat']][$key] = $value;
+                       }
+               }
+               $this->dba->close($configs);
+
+               return $return;
+       }
+
+       /**
+        * Get a particular, system-wide config variable out of the DB with the
+        * given category name ($cat) and a key ($key).
+        *
+        * Note: Boolean variables are defined as 0/1 in the database
+        *
+        * @param string $cat The category of the configuration value
+        * @param string $key The configuration key to query
+        *
+        * @return array|string|null Stored value or null if it does not exist
+        *
+        * @throws \Exception In case DB calls are invalid
+        */
+       public function get(string $cat, string $key)
+       {
+               if (!$this->isConnected()) {
+                       return null;
+               }
+
+               $config = $this->dba->selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]);
+               if ($this->dba->isResult($config)) {
+                       $value = $this->toConfigValue($config['v']);
+
+                       // just return it in case it is set
+                       if (isset($value)) {
+                               return $value;
+                       }
+               }
+
+               return null;
+       }
+
+       /**
+        * Stores a config value ($value) in the category ($cat) under the key ($key).
+        *
+        * Note: Please do not store booleans - convert to 0/1 integer values!
+        *
+        * @param string $cat   The category of the configuration value
+        * @param string $key   The configuration key to set
+        * @param mixed  $value The value to store
+        *
+        * @return bool Operation success
+        *
+        * @throws \Exception In case DB calls are invalid
+        */
+       public function set(string $cat, string $key, $value)
+       {
+               if (!$this->isConnected()) {
+                       return false;
+               }
+
+               // We store our setting values in a string variable.
+               // So we have to do the conversion here so that the compare below works.
+               // The exception are array values.
+               $compare_value = (!is_array($value) ? (string)$value : $value);
+               $stored_value  = $this->get($cat, $key);
+
+               if (isset($stored_value) && ($stored_value === $compare_value)) {
+                       return true;
+               }
+
+               $dbvalue = $this->toDbValue($value);
+
+               $result = $this->dba->update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true);
+
+               return $result;
+       }
+
+       /**
+        * Removes the configured value from the database.
+        *
+        * @param string $cat The category of the configuration value
+        * @param string $key The configuration key to delete
+        *
+        * @return bool Operation success
+        *
+        * @throws \Exception In case DB calls are invalid
+        */
+       public function delete(string $cat, string $key)
+       {
+               if (!$this->isConnected()) {
+                       return false;
+               }
+
+               return $this->dba->delete('config', ['cat' => $cat, 'k' => $key]);
+       }
+}
diff --git a/src/Model/Config/DbaConfig.php b/src/Model/Config/DbaConfig.php
new file mode 100644 (file)
index 0000000..cd6b6da
--- /dev/null
@@ -0,0 +1,86 @@
+<?php
+
+namespace Friendica\Model\Config;
+
+use Friendica\Database\Database;
+
+/**
+ * The DB-based model of (P-)Config values
+ * Encapsulates db-calls in case of config queries
+ */
+abstract class DbaConfig
+{
+       /** @var Database */
+       protected $dba;
+
+       /**
+        * @param Database $dba The database connection of this model
+        */
+       public function __construct(Database $dba)
+       {
+               $this->dba = $dba;
+       }
+
+       /**
+        * Checks if the model is currently connected
+        *
+        * @return bool
+        */
+       public function isConnected()
+       {
+               return $this->dba->isConnected();
+       }
+
+       /**
+        * Formats a DB value to a config value
+        * - null   = The db-value isn't set
+        * - bool   = The db-value is either '0' or '1'
+        * - array  = The db-value is a serialized array
+        * - string = The db-value is a string
+        *
+        * Keep in mind that there aren't any numeric/integer config values in the database
+        *
+        * @param null|string $value
+        *
+        * @return null|array|string
+        */
+       protected function toConfigValue($value)
+       {
+               if (!isset($value)) {
+                       return null;
+               }
+
+               switch (true) {
+                       // manage array value
+                       case preg_match("|^a:[0-9]+:{.*}$|s", $value):
+                               return unserialize($value);
+
+                       default:
+                               return $value;
+               }
+       }
+
+       /**
+        * Formats a config value to a DB value (string)
+        *
+        * @param mixed $value
+        *
+        * @return string
+        */
+       protected function toDbValue($value)
+       {
+               // if not set, save an empty string
+               if (!isset($value)) {
+                       return '';
+               }
+
+               switch (true) {
+                       // manage arrays
+                       case is_array($value):
+                               return serialize($value);
+
+                       default:
+                               return (string)$value;
+               }
+       }
+}
index b3418c20f4024878c9999ebf9f6d908d6374335b..999da871dbb047ef8386bee002bcfe611344827e 100644 (file)
@@ -5,12 +5,15 @@
 
 namespace Friendica\Test;
 
-use Friendica\App;
-use Friendica\Database\DBA;
-use Friendica\Factory;
+use Friendica\App\Mode;
+use Friendica\App\Router;
+use Friendica\Core\Config\Cache\ConfigCache;
+use Friendica\Database\Database;
+use Friendica\Factory\ConfigFactory;
+use Friendica\Factory\DBFactory;
+use Friendica\Factory\ProfilerFactory;
 use Friendica\Util\BasePath;
 use Friendica\Util\Config\ConfigFileLoader;
-use Friendica\Util\Logger\VoidLogger;
 use Friendica\Util\Profiler;
 use PHPUnit\DbUnit\DataSet\YamlDataSet;
 use PHPUnit\DbUnit\TestCaseTrait;
@@ -25,6 +28,33 @@ abstract class DatabaseTest extends MockedTest
 {
        use TestCaseTrait;
 
+       /** @var Database */
+       protected static $dba;
+
+       /** @var BasePath */
+       protected static $basePath;
+
+       /** @var Mode */
+       protected static $mode;
+
+       /** @var ConfigCache */
+       protected static $configCache;
+
+       /** @var Profiler */
+       protected static $profiler;
+
+       public static function setUpBeforeClass()
+       {
+               parent::setUpBeforeClass();
+
+               self::$basePath = BasePath::create(dirname(__DIR__));
+               self::$mode = new Mode(self::$basePath);
+               $configLoader = new ConfigFileLoader(self::$basePath, self::$mode);
+               self::$configCache = ConfigFactory::createCache($configLoader);
+               self::$profiler = ProfilerFactory::create(self::$configCache);
+               self::$dba = DBFactory::init(self::$configCache, self::$profiler, $_SERVER);
+       }
+
        /**
         * Get database connection.
         *
@@ -42,27 +72,13 @@ abstract class DatabaseTest extends MockedTest
                        $this->markTestSkipped('Please set the MYSQL_* environment variables to your test database credentials.');
                }
 
-               $basePath = BasePath::create(dirname(__DIR__));
-               $mode = new App\Mode($basePath);
-               $configLoader = new ConfigFileLoader($basePath, $mode);
-               $config = Factory\ConfigFactory::createCache($configLoader);
-
-               $profiler = \Mockery::mock(Profiler::class);
-
-               DBA::connect(
-                       $config,
-                       $profiler,
-                       new VoidLogger(),
-                       getenv('MYSQL_HOST'),
-                       getenv('MYSQL_USERNAME'),
-                       getenv('MYSQL_PASSWORD'),
-                       getenv('MYSQL_DATABASE'));
-
-               if (!DBA::connected()) {
-                       $this->markTestSkipped('Could not connect to the database.');
+               if (!self::$dba->isConnected()) {
+                       if (!self::$dba->connect()) {
+                               $this->markTestSkipped('Could not connect to the database.');
+                       }
                }
 
-               return $this->createDefaultDBConnection(DBA::getConnection(), getenv('MYSQL_DATABASE'));
+               return $this->createDefaultDBConnection(self::$dba->getConnection(), getenv('MYSQL_DATABASE'));
        }
 
        /**
index 0ca625ee0e5b8ee98ab5737491e478c0dc666064..52941d0d513474a699c8dd0cbce49ab9cbb6dd8c 100644 (file)
@@ -44,12 +44,13 @@ trait AppMockTrait
        public function mockApp(vfsStreamDirectory $root, $raw = false)
        {
                $this->configMock = \Mockery::mock(Config\Cache\ConfigCache::class);
+               $this->configMock->shouldReceive('getAll')->andReturn([])->once();
                $this->mode = \Mockery::mock(App\Mode::class);
-               $configAdapterMock = \Mockery::mock(Config\Adapter\IConfigAdapter::class);
+               $configModel= \Mockery::mock(\Friendica\Model\Config\Config::class);
                // Disable the adapter
-               $configAdapterMock->shouldReceive('isConnected')->andReturn(false);
+               $configModel->shouldReceive('isConnected')->andReturn(false);
 
-               $config = new Config\Configuration($this->configMock, $configAdapterMock);
+               $config = new Config\JitConfiguration($this->configMock, $configModel);
                // Initialize empty Config
                Config::init($config);
 
index 94557ac69c234b46b78a1bb48f8608d9c94632f1..5ae4bdff5074eecd7e6c4e7bec09f62c7c17451a 100644 (file)
@@ -12,9 +12,7 @@ use Friendica\Core\Protocol;
 use Friendica\Core\System;
 use Friendica\Factory;
 use Friendica\Network\HTTPException;
-use Friendica\Util\BasePath;
 use Friendica\Util\BaseURL;
-use Friendica\Util\Config\ConfigFileLoader;
 use Monolog\Handler\TestHandler;
 
 require_once __DIR__ . '/../../include/api.php';
@@ -49,18 +47,13 @@ class ApiTest extends DatabaseTest
         */
        public function setUp()
        {
-               $basePath = BasePath::create(dirname(__DIR__) . '/../');
-               $mode = new App\Mode($basePath);
-               $router = new App\Router();
-               $configLoader = new ConfigFileLoader($basePath, $mode);
-               $configCache = Factory\ConfigFactory::createCache($configLoader);
-               $profiler = Factory\ProfilerFactory::create($configCache);
-               $database = Factory\DBFactory::init($configCache, $profiler, $_SERVER);
-               $config = Factory\ConfigFactory::createConfig($configCache);
-               Factory\ConfigFactory::createPConfig($configCache, new Config\Cache\PConfigCache());
-               $logger = Factory\LoggerFactory::create('test', $database, $config, $profiler);
+               $configModel = new \Friendica\Model\Config\Config(self::$dba);
+               $config = Factory\ConfigFactory::createConfig(self::$configCache, $configModel);
+               Factory\ConfigFactory::createPConfig(self::$configCache, new Config\Cache\PConfigCache());
+               $logger = Factory\LoggerFactory::create('test', self::$dba, $config, self::$profiler);
                $baseUrl = new BaseURL($config, $_SERVER);
-               $this->app = new App($database, $config, $mode, $router, $baseUrl, $logger, $profiler, false);
+               $router = new App\Router();
+               $this->app = new App(self::$dba, $config, self::$mode, $router, $baseUrl, $logger, self::$profiler, false);
 
                parent::setUp();
 
index db92cc74365430da33a2e70f7a49ac2f5967f918..d8ac3eaea4d8cbe2aa63c5d22ae3eb57d5d635a7 100644 (file)
@@ -157,6 +157,12 @@ class ConfigCacheTest extends MockedTest
                        'key1' => 'value1',
                        'key2' => 'value2',
                ], $configCache->get('system'));
+
+               // explicit null as key
+               $this->assertEquals([
+                       'key1' => 'value1',
+                       'key2' => 'value2',
+               ], $configCache->get('system', null));
        }
 
        /**
index b8feec4b19e49b8a4748a39b2408eb5a61ae572e..22beccf6019a295850549dec9ab902b6a98680cc 100644 (file)
@@ -79,6 +79,12 @@ class PConfigCacheTest extends MockedTest
                        'key1' => 'value1',
                        'key2' => 'value2',
                ], $configCache->get($uid, 'system'));
+
+               // test explicit cat with null as key
+               $this->assertEquals([
+                       'key1' => 'value1',
+                       'key2' => 'value2',
+               ], $configCache->get($uid, 'system', null));
        }
 
        /**
@@ -113,7 +119,7 @@ class PConfigCacheTest extends MockedTest
         */
        public function testKeyDiffWithResult($data)
        {
-               $configCache = new PConfigCache($data);
+               $configCache = new PConfigCache();
 
                $diffConfig = [
                        'fakeCat' => [
index fda69896fdcc0f6c505fb24ee9915d32dc5c0742..2191d86f1cbe9b0ca663286f5ac87a78d2df7288 100644 (file)
@@ -2,13 +2,55 @@
 
 namespace Friendica\Test\src\Core\Config;
 
-use Friendica\Core\Config\Adapter\IConfigAdapter;
 use Friendica\Core\Config\Cache\ConfigCache;
 use Friendica\Core\Config\Configuration;
+use Friendica\Core\Config\JitConfiguration;
+use Friendica\Model\Config\Config as ConfigModel;
 use Friendica\Test\MockedTest;
+use Mockery\MockInterface;
+use Mockery;
 
-class ConfigurationTest extends MockedTest
+abstract class ConfigurationTest extends MockedTest
 {
+       /** @var ConfigModel|MockInterface */
+       protected $configModel;
+
+       /** @var ConfigCache */
+       protected $configCache;
+
+       /** @var Configuration */
+       protected $testedConfig;
+
+       /**
+        * Assert a config tree
+        *
+        * @param string $cat  The category to assert
+        * @param array  $data The result data array
+        */
+       protected function assertConfig(string $cat, array $data)
+       {
+               $result = $this->testedConfig->getCache()->getAll();
+
+               $this->assertNotEmpty($result);
+               $this->assertArrayHasKey($cat, $result);
+               $this->assertArraySubset($data, $result[$cat]);
+       }
+
+
+       protected function setUp()
+       {
+               parent::setUp();
+
+               // Create the config model
+               $this->configModel = Mockery::mock(ConfigModel::class);
+               $this->configCache = new ConfigCache();
+       }
+
+       /**
+        * @return Configuration
+        */
+       public abstract function getInstance();
+
        public function dataTests()
        {
                return [
@@ -23,107 +65,243 @@ class ConfigurationTest extends MockedTest
                ];
        }
 
+       public function dataConfigLoad()
+       {
+               $data = [
+                       'system' => [
+                               'key1' => 'value1',
+                               'key2' => 'value2',
+                               'key3' => 'value3',
+                       ],
+                       'config' => [
+                               'key1' => 'value1a',
+                               'key4' => 'value4',
+                       ],
+                       'other'  => [
+                               'key5' => 'value5',
+                               'key6' => 'value6',
+                       ],
+               ];
+
+               return [
+                       'system' => [
+                               'data'         => $data,
+                               'possibleCats' => [
+                                       'system',
+                                       'config',
+                                       'other'
+                               ],
+                               'load'         => [
+                                       'system',
+                               ],
+                       ],
+                       'other'  => [
+                               'data'         => $data,
+                               'possibleCats' => [
+                                       'system',
+                                       'config',
+                                       'other'
+                               ],
+                               'load'         => [
+                                       'other',
+                               ],
+                       ],
+                       'config' => [
+                               'data'         => $data,
+                               'possibleCats' => [
+                                       'system',
+                                       'config',
+                                       'other'
+                               ],
+                               'load'         => [
+                                       'config',
+                               ],
+                       ],
+                       'all'    => [
+                               'data'         => $data,
+                               'possibleCats' => [
+                                       'system',
+                                       'config',
+                                       'other'
+                               ],
+                               'load'         => [
+                                       'system',
+                                       'config',
+                                       'other'
+                               ],
+                       ],
+               ];
+       }
+
        /**
         * Test the configuration initialization
         */
-       public function testSetUp()
+       public function testSetUp(array $data)
        {
-               $configCache = new ConfigCache();
-               $configAdapter = \Mockery::mock(IConfigAdapter::class);
-               $configAdapter->shouldReceive('isConnected')->andReturn(false)->once();
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(true)
+                                 ->once();
 
-               $configuration = new Configuration($configCache, $configAdapter);
+               $this->testedConfig = $this->getInstance();
+               $this->assertInstanceOf(ConfigCache::class, $this->testedConfig->getCache());
 
-               $this->assertInstanceOf(ConfigCache::class, $configuration->getCache());
+               // assert config is loaded everytime
+               $this->assertConfig('config', $data['config']);
        }
 
        /**
         * Test the configuration load() method
         */
-       public function testCacheLoad()
+       public function testLoad(array $data, array $possibleCats, array $load)
        {
-               $configCache = new ConfigCache();
-               $configAdapter = \Mockery::mock(IConfigAdapter::class);
-               $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3);
-               // constructor loading
-               $configAdapter->shouldReceive('load')->andReturn([])->once();
-               // expected loading
-               $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once();
-               $configAdapter->shouldReceive('isLoaded')->with('testing', 'test')->andReturn(true)->once();
-
-               $configuration = new Configuration($configCache, $configAdapter);
-               $configuration->load('testing');
-
-               $this->assertEquals('it', $configuration->get('testing', 'test'));
-               $this->assertEquals('it', $configuration->getCache()->get('testing', 'test'));
+               $this->testedConfig = $this->getInstance();
+               $this->assertInstanceOf(ConfigCache::class, $this->testedConfig->getCache());
+
+               foreach ($load as $loadedCats) {
+                       $this->testedConfig->load($loadedCats);
+               }
+
+               // Assert at least loaded cats are loaded
+               foreach ($load as $loadedCats) {
+                       $this->assertConfig($loadedCats, $data[$loadedCats]);
+               }
+       }
+
+       public function dataDoubleLoad()
+       {
+               return [
+                       'config' => [
+                               'data1'  => [
+                                       'config' => [
+                                               'key1' => 'value1',
+                                               'key2' => 'value2',
+                                       ],
+                               ],
+                               'data2'  => [
+                                       'config' => [
+                                               'key1' => 'overwritten!',
+                                               'key3' => 'value3',
+                                       ],
+                               ],
+                               'expect' => [
+                                       'config' => [
+                                               // load should overwrite values everytime!
+                                               'key1' => 'overwritten!',
+                                               'key2' => 'value2',
+                                               'key3' => 'value3',
+                                       ],
+                               ],
+                       ],
+                       'other'  => [
+                               'data1'  => [
+                                       'config' => [
+                                               'key12' => 'data4',
+                                               'key45' => 7,
+                                       ],
+                                       'other'  => [
+                                               'key1' => 'value1',
+                                               'key2' => 'value2',
+                                       ],
+                               ],
+                               'data2'  => [
+                                       'other'  => [
+                                               'key1' => 'overwritten!',
+                                               'key3' => 'value3',
+                                       ],
+                                       'config' => [
+                                               'key45' => 45,
+                                               'key52' => true,
+                                       ]
+                               ],
+                               'expect' => [
+                                       'other'  => [
+                                               // load should overwrite values everytime!
+                                               'key1' => 'overwritten!',
+                                               'key2' => 'value2',
+                                               'key3' => 'value3',
+                                       ],
+                                       'config' => [
+                                               'key12' => 'data4',
+                                               'key45' => 45,
+                                               'key52' => true,
+                                       ],
+                               ],
+                       ],
+               ];
        }
 
        /**
         * Test the configuration load() method with overwrite
         */
-       public function testCacheLoadDouble()
+       public function testCacheLoadDouble(array $data1, array $data2, array $expect)
        {
-               $configCache = new ConfigCache();
-               $configAdapter = \Mockery::mock(IConfigAdapter::class);
-               $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(5);
-               // constructor loading
-               $configAdapter->shouldReceive('load')->andReturn([])->once();
-               // expected loading
-               $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once();
-               $configAdapter->shouldReceive('isLoaded')->with('testing', 'test')->andReturn(true)->twice();
-               // 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'));
+               $this->testedConfig = $this->getInstance();
+               $this->assertInstanceOf(ConfigCache::class, $this->testedConfig->getCache());
+
+               foreach ($data1 as $cat => $data) {
+                       $this->testedConfig->load($cat);
+               }
+
+               // Assert at least loaded cats are loaded
+               foreach ($data1 as $cat => $data) {
+                       $this->assertConfig($cat, $data);
+               }
+
+               foreach ($data2 as $cat => $data) {
+                       $this->testedConfig->load($cat);
+               }
+       }
+
+       /**
+        * Test the configuration load without result
+        */
+       public function testLoadWrong()
+       {
+               $this->configModel->shouldReceive('isConnected')->andReturn(true)->once();
+               $this->configModel->shouldReceive('load')->withAnyArgs()->andReturn([])->once();
+
+               $this->testedConfig = $this->getInstance();
+               $this->assertInstanceOf(ConfigCache::class, $this->testedConfig->getCache());
+
+               $this->assertEmpty($this->testedConfig->getCache()->getAll());
        }
 
        /**
         * Test the configuration get() and set() methods without adapter
+        *
         * @dataProvider dataTests
         */
        public function testSetGetWithoutDB($data)
        {
-               $configCache = new ConfigCache();
-               $configAdapter = \Mockery::mock(IConfigAdapter::class);
-               $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(3);
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(false)
+                                 ->times(3);
 
-               $configuration = new Configuration($configCache, $configAdapter);
+               $this->testedConfig = $this->getInstance();
+               $this->assertInstanceOf(ConfigCache::class, $this->testedConfig->getCache());
 
-               $this->assertTrue($configuration->set('test', 'it', $data));
+               $this->assertTrue($this->testedConfig->set('test', 'it', $data));
 
-               $this->assertEquals($data, $configuration->get('test', 'it'));
-               $this->assertEquals($data, $configuration->getCache()->get('test', 'it'));
+               $this->assertEquals($data, $this->testedConfig->get('test', 'it'));
+               $this->assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
        }
 
        /**
-        * Test the configuration get() and set() methods with adapter
+        * Test the configuration get() and set() methods with a model/db
+        *
         * @dataProvider dataTests
         */
        public function testSetGetWithDB($data)
        {
-               $configCache = new ConfigCache();
-               $configAdapter = \Mockery::mock(IConfigAdapter::class);
-               $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3);
-               // constructor loading
-               $configAdapter->shouldReceive('load')->andReturn([])->once();
-               $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(true)->once();
-               $configAdapter->shouldReceive('set')->with('test', 'it', $data)->andReturn(true)->once();
+               $this->configModel->shouldReceive('set')->with('test', 'it', $data)->andReturn(true)->once();
 
-               $configuration = new Configuration($configCache, $configAdapter);
+               $this->testedConfig = $this->getInstance();
+               $this->assertInstanceOf(ConfigCache::class, $this->testedConfig->getCache());
 
-               $this->assertTrue($configuration->set('test', 'it', $data));
+               $this->assertTrue($this->testedConfig->set('test', 'it', $data));
 
-               $this->assertEquals($data, $configuration->get('test', 'it'));
-               $this->assertEquals($data, $configuration->getCache()->get('test', 'it'));
+               $this->assertEquals($data, $this->testedConfig->get('test', 'it'));
+               $this->assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
        }
 
        /**
@@ -131,145 +309,111 @@ class ConfigurationTest extends MockedTest
         */
        public function testGetWrongWithoutDB()
        {
-               $configCache = new ConfigCache();
-               $configAdapter = \Mockery::mock(IConfigAdapter::class);
-               $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(4);
-
-               $configuration = new Configuration($configCache, $configAdapter);
+               $this->testedConfig = $this->getInstance();
+               $this->assertInstanceOf(ConfigCache::class, $this->testedConfig->getCache());
 
                // without refresh
-               $this->assertNull($configuration->get('test', 'it'));
+               $this->assertNull($this->testedConfig->get('test', 'it'));
 
                /// beware that the cache returns '!<unset>!' and not null for a non existing value
-               $this->assertNull($configuration->getCache()->get('test', 'it'));
+               $this->assertNull($this->testedConfig->getCache()->get('test', 'it'));
 
                // with default value
-               $this->assertEquals('default', $configuration->get('test', 'it', 'default'));
+               $this->assertEquals('default', $this->testedConfig->get('test', 'it', 'default'));
 
                // with default value and refresh
-               $this->assertEquals('default', $configuration->get('test', 'it', 'default', true));
+               $this->assertEquals('default', $this->testedConfig->get('test', 'it', 'default', true));
        }
 
        /**
         * Test the configuration get() method with refresh
+        *
         * @dataProvider dataTests
         */
        public function testGetWithRefresh($data)
        {
-               $configCache = new ConfigCache(['test' => ['it' => 'now']]);
-               $configAdapter = \Mockery::mock(IConfigAdapter::class);
-               $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(4);
-               // constructor loading
-               $configAdapter->shouldReceive('load')->andReturn([])->once();
-               $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(true)->twice();
-               $configAdapter->shouldReceive('get')->with('test', 'it')->andReturn($data)->once();
-               $configAdapter->shouldReceive('isLoaded')->with('test', 'not')->andReturn(false)->once();
-               $configAdapter->shouldReceive('get')->with('test', 'not')->andReturn(null)->once();
-
-               $configuration = new Configuration($configCache, $configAdapter);
+               $this->configCache->load(['test' => ['it' => 'now']]);
+
+               $this->testedConfig = $this->getInstance();
+               $this->assertInstanceOf(ConfigCache::class, $this->testedConfig->getCache());
 
                // without refresh
-               $this->assertEquals('now', $configuration->get('test', 'it'));
-               $this->assertEquals('now', $configuration->getCache()->get('test', 'it'));
+               $this->assertEquals('now', $this->testedConfig->get('test', 'it'));
+               $this->assertEquals('now', $this->testedConfig->getCache()->get('test', 'it'));
 
                // with refresh
-               $this->assertEquals($data, $configuration->get('test', 'it', null, true));
-               $this->assertEquals($data, $configuration->getCache()->get('test', 'it'));
+               $this->assertEquals($data, $this->testedConfig->get('test', 'it', null, true));
+               $this->assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
 
                // without refresh and wrong value and default
-               $this->assertEquals('default', $configuration->get('test', 'not', 'default'));
-               $this->assertNull($configuration->getCache()->get('test', 'not'));
-       }
-
-       /**
-        * Test the configuration get() method with different isLoaded settings
-        * @dataProvider dataTests
-        */
-       public function testGetWithoutLoaded($data)
-       {
-               $configCache = new ConfigCache(['test' => ['it' => 'now']]);
-               $configAdapter = \Mockery::mock(IConfigAdapter::class);
-               $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(4);
-               // constructor loading
-               $configAdapter->shouldReceive('load')->andReturn([])->once();
-
-               $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(false)->once();
-               $configAdapter->shouldReceive('get')->with('test', 'it')->andReturn(null)->once();
-
-               $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(false)->once();
-               $configAdapter->shouldReceive('get')->with('test', 'it')->andReturn($data)->once();
-
-               $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(true)->once();
-
-               $configuration = new Configuration($configCache, $configAdapter);
-
-               // first run is not loaded and no data is found in the DB
-               $this->assertEquals('now', $configuration->get('test', 'it'));
-               $this->assertEquals('now', $configuration->getCache()->get('test', 'it'));
-
-               // second run is not loaded, but now data is found in the db (overwrote cache)
-               $this->assertEquals($data, $configuration->get('test', 'it'));
-               $this->assertEquals($data, $configuration->getCache()->get('test', 'it'));
-
-               // third run is loaded and therefore cache is used
-               $this->assertEquals($data, $configuration->get('test', 'it'));
-               $this->assertEquals($data, $configuration->getCache()->get('test', 'it'));
+               $this->assertEquals('default', $this->testedConfig->get('test', 'not', 'default'));
+               $this->assertNull($this->testedConfig->getCache()->get('test', 'not'));
        }
 
        /**
-        * Test the configuration delete() method without adapter
+        * Test the configuration delete() method without a model/db
+        *
         * @dataProvider dataTests
         */
        public function testDeleteWithoutDB($data)
        {
-               $configCache = new ConfigCache(['test' => ['it' => $data]]);
-               $configAdapter = \Mockery::mock(IConfigAdapter::class);
-               $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(4);
+               $this->configCache->load(['test' => ['it' => $data]]);
 
-               $configuration = new Configuration($configCache, $configAdapter);
+               $this->testedConfig = $this->getInstance();
+               $this->assertInstanceOf(ConfigCache::class, $this->testedConfig->getCache());
 
-               $this->assertEquals($data, $configuration->get('test', 'it'));
-               $this->assertEquals($data, $configuration->getCache()->get('test', 'it'));
+               $this->assertEquals($data, $this->testedConfig->get('test', 'it'));
+               $this->assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
 
-               $this->assertTrue($configuration->delete('test', 'it'));
-               $this->assertNull($configuration->get('test', 'it'));
-               $this->assertNull($configuration->getCache()->get('test', 'it'));
+               $this->assertTrue($this->testedConfig->delete('test', 'it'));
+               $this->assertNull($this->testedConfig->get('test', 'it'));
+               $this->assertNull($this->testedConfig->getCache()->get('test', 'it'));
 
-               $this->assertEmpty($configuration->getCache()->getAll());
+               $this->assertEmpty($this->testedConfig->getCache()->getAll());
        }
 
        /**
-        * Test the configuration delete() method with adapter
+        * Test the configuration delete() method with a model/db
         */
        public function testDeleteWithDB()
        {
-               $configCache = new ConfigCache(['test' => ['it' => 'now', 'quarter' => 'true']]);
-               $configAdapter = \Mockery::mock(IConfigAdapter::class);
-               $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(6);
-               // constructor loading
-               $configAdapter->shouldReceive('load')->andReturn([])->once();
-               $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(true)->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'));
+               $this->configCache->load(['test' => ['it' => 'now', 'quarter' => 'true']]);
+
+               $this->configModel->shouldReceive('delete')
+                                 ->with('test', 'it')
+                                 ->andReturn(false)
+                                 ->once();
+               $this->configModel->shouldReceive('delete')
+                                 ->with('test', 'second')
+                                 ->andReturn(true)
+                                 ->once();
+               $this->configModel->shouldReceive('delete')
+                                 ->with('test', 'third')
+                                 ->andReturn(false)
+                                 ->once();
+               $this->configModel->shouldReceive('delete')
+                                 ->with('test', 'quarter')
+                                 ->andReturn(true)
+                                 ->once();
+
+               $this->testedConfig = $this->getInstance();
+               $this->assertInstanceOf(ConfigCache::class, $this->testedConfig->getCache());
+
+               // directly set the value to the cache
+               $this->testedConfig->getCache()->set('test', 'it', 'now');
+
+               $this->assertEquals('now', $this->testedConfig->get('test', 'it'));
+               $this->assertEquals('now', $this->testedConfig->getCache()->get('test', 'it'));
 
                // delete from cache only
-               $this->assertTrue($configuration->delete('test', 'it'));
+               $this->assertTrue($this->testedConfig->delete('test', 'it'));
                // delete from db only
-               $this->assertTrue($configuration->delete('test', 'second'));
+               $this->assertTrue($this->testedConfig->delete('test', 'second'));
                // no delete
-               $this->assertFalse($configuration->delete('test', 'third'));
+               $this->assertFalse($this->testedConfig->delete('test', 'third'));
                // delete both
-               $this->assertTrue($configuration->delete('test', 'quarter'));
+               $this->assertTrue($this->testedConfig->delete('test', 'quarter'));
 
-               $this->assertEmpty($configuration->getCache()->getAll());
+               $this->assertEmpty($this->testedConfig->getCache()->getAll());
        }
 }
diff --git a/tests/src/Core/Config/JitConfigurationTest.php b/tests/src/Core/Config/JitConfigurationTest.php
new file mode 100644 (file)
index 0000000..79aada4
--- /dev/null
@@ -0,0 +1,167 @@
+<?php
+
+namespace Friendica\Test\src\Core\Config;
+
+use Friendica\Core\Config\JitConfiguration;
+
+class JitConfigurationTest extends ConfigurationTest
+{
+       public function getInstance()
+       {
+               return new JitConfiguration($this->configCache, $this->configModel);
+       }
+
+       /**
+        * @dataProvider dataConfigLoad
+        */
+       public function testSetUp(array $data)
+       {
+               $this->configModel->shouldReceive('load')
+                                 ->with('config')
+                                 ->andReturn(['config' => $data['config']])
+                                 ->once();
+
+               parent::testSetUp($data);
+       }
+
+       /**
+        * @dataProvider dataConfigLoad
+        */
+       public function testLoad(array $data, array $possibleCats, array $load)
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(true)
+                                 ->times(count($load) + 1);
+
+               $this->configModel->shouldReceive('load')
+                                 ->with('config')
+                                 ->andReturn(['config' => $data['config']])
+                                 ->once();
+
+               foreach ($load as $loadCat) {
+                       $this->configModel->shouldReceive('load')
+                                         ->with($loadCat)
+                                         ->andReturn([$loadCat => $data[$loadCat]])
+                                         ->once();
+               }
+
+               parent::testLoad($data, $possibleCats, $load);
+       }
+
+       /**
+        * @dataProvider dataDoubleLoad
+        */
+       public function testCacheLoadDouble(array $data1, array $data2, array $expect)
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(true)
+                                 ->times(count($data1) + count($data2) + 1);
+
+               $this->configModel->shouldReceive('load')
+                                 ->with('config')
+                                 ->andReturn(['config' => $data1['config']])
+                                 ->once();
+
+               foreach ($data1 as $cat => $data) {
+                       $this->configModel->shouldReceive('load')
+                                         ->with($cat)
+                                         ->andReturn([$cat => $data])
+                                         ->once();
+               }
+
+
+               foreach ($data2 as $cat => $data) {
+                       $this->configModel->shouldReceive('load')
+                                         ->with($cat)
+                                         ->andReturn([$cat => $data])
+                                         ->once();
+               }
+
+               parent::testCacheLoadDouble($data1, $data2, $expect);
+
+               // Assert the expected categories
+               foreach ($data2 as $cat => $data) {
+                       $this->assertConfig($cat, $expect[$cat]);
+               }
+       }
+
+       /**
+        * @dataProvider dataTests
+        */
+       public function testSetGetWithDB($data)
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(true)
+                                 ->times(3);
+
+               $this->configModel->shouldReceive('load')->with('config')->andReturn(['config' => []])->once();
+
+               parent::testSetGetWithDB($data);
+       }
+
+       /**
+        * @dataProvider dataTests
+        */
+       public function testGetWithRefresh($data)
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(true)
+                                 ->times(4);
+
+               // constructor loading
+               $this->configModel->shouldReceive('load')
+                                 ->with('config')
+                                 ->andReturn(['config' => []])
+                                 ->once();
+
+               // mocking one get
+               $this->configModel->shouldReceive('get')
+                                 ->with('test', 'it')
+                                 ->andReturn($data)
+                                 ->once();
+
+               // mocking second get
+               $this->configModel->shouldReceive('get')
+                                 ->with('test', 'not')
+                                 ->andReturn(null)
+                                 ->once();
+
+               parent::testGetWithRefresh($data);
+       }
+
+       public function testGetWrongWithoutDB()
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(false)
+                                 ->times(4);
+
+               parent::testGetWrongWithoutDB();
+       }
+
+       /**
+        * @dataProvider dataTests
+        */
+       public function testDeleteWithoutDB($data)
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(false)
+                                 ->times(4);
+
+               parent::testDeleteWithoutDB($data);
+       }
+
+       public function testDeleteWithDB()
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(true)
+                                 ->times(6);
+
+               // constructor loading
+               $this->configModel->shouldReceive('load')
+                                 ->with('config')
+                                 ->andReturn(['config' => []])
+                                 ->once();
+
+               parent::testDeleteWithDB();
+       }
+}
diff --git a/tests/src/Core/Config/PreloadConfigurationTest.php b/tests/src/Core/Config/PreloadConfigurationTest.php
new file mode 100644 (file)
index 0000000..8804439
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+
+namespace Friendica\Test\src\Core\Config;
+
+use Friendica\Core\Config\PreloadConfiguration;
+
+class PreloadConfigurationTest extends ConfigurationTest
+{
+       public function getInstance()
+       {
+               return new PreloadConfiguration($this->configCache, $this->configModel);
+       }
+
+       /**
+        * @dataProvider dataConfigLoad
+        */
+       public function testSetUp(array $data)
+       {
+               $this->configModel->shouldReceive('load')
+                                 ->andReturn($data)
+                                 ->once();
+
+               parent::testSetUp($data);
+       }
+
+       /**
+        * @dataProvider dataConfigLoad
+        */
+       public function testLoad(array $data, array $possibleCats, array $load)
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(true)
+                                 ->once();
+
+               $this->configModel->shouldReceive('load')
+                                 ->andReturn($data)
+                                 ->once();
+
+               parent::testLoad($data, $possibleCats, $load);
+
+               // Assert that every category is loaded everytime
+               foreach ($data as $cat => $values) {
+                       $this->assertConfig($cat, $values);
+               }
+       }
+
+       /**
+        * @dataProvider dataDoubleLoad
+        */
+       public function testCacheLoadDouble(array $data1, array $data2, array $expect)
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(true)
+                                 ->once();
+
+               $this->configModel->shouldReceive('load')
+                                 ->andReturn($data1)
+                                 ->once();
+
+               parent::testCacheLoadDouble($data1, $data2, $expect);
+
+               // Assert that every category is loaded everytime and is NOT overwritten
+               foreach ($data1 as $cat => $values) {
+                       $this->assertConfig($cat, $values);
+               }
+       }
+
+       /**
+        * @dataProvider dataTests
+        */
+       public function testSetGetWithDB($data)
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(true)
+                                 ->times(2);
+
+               $this->configModel->shouldReceive('load')->andReturn(['config' => []])->once();
+
+               parent::testSetGetWithDB($data);
+       }
+
+       /**
+        * @dataProvider dataTests
+        */
+       public function testGetWithRefresh($data)
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(true)
+                                 ->times(2);
+
+               // constructor loading
+               $this->configModel->shouldReceive('load')
+                                 ->andReturn(['config' => []])
+                                 ->once();
+
+               // mocking one get
+               $this->configModel->shouldReceive('get')
+                                 ->with('test', 'it')
+                                 ->andReturn($data)
+                                 ->once();
+
+               parent::testGetWithRefresh($data);
+       }
+
+
+       public function testGetWrongWithoutDB()
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(false)
+                                 ->times(2);
+
+               parent::testGetWrongWithoutDB();
+       }
+
+       /**
+        * @dataProvider dataTests
+        */
+       public function testDeleteWithoutDB($data)
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(false)
+                                 ->times(2);
+
+               parent::testDeleteWithoutDB($data);
+       }
+
+       public function testDeleteWithDB()
+       {
+               $this->configModel->shouldReceive('isConnected')
+                                 ->andReturn(true)
+                                 ->times(5);
+
+               // constructor loading
+               $this->configModel->shouldReceive('load')
+                                 ->andReturn(['config' => []])
+                                 ->once();
+
+               parent::testDeleteWithDB();
+       }
+}
index 84d17dc899842577ba4beaa5bab27f946a2d861a..852db4498fc1c0d78a72f1b3a8f3e89525dc1faa 100644 (file)
@@ -6,26 +6,19 @@ use Friendica\Core\Config;
 use Friendica\Database\DBA;
 use Friendica\Factory;
 use Friendica\Test\DatabaseTest;
-use Friendica\Util\BasePath;
 use Friendica\Util\BaseURL;
-use Friendica\Util\Config\ConfigFileLoader;
 
 class DBATest extends DatabaseTest
 {
        public function setUp()
        {
-               $basePath = BasePath::create(dirname(__DIR__) . '/../../');
-               $mode = new App\Mode($basePath);
-               $router = new App\Router();
-               $configLoader = new ConfigFileLoader($basePath, $mode);
-               $configCache = Factory\ConfigFactory::createCache($configLoader);
-               $profiler = Factory\ProfilerFactory::create($configCache);
-               $database = Factory\DBFactory::init($configCache, $profiler, $_SERVER);
-               $config = Factory\ConfigFactory::createConfig($configCache);
-               Factory\ConfigFactory::createPConfig($configCache, new Config\Cache\PConfigCache());
-               $logger = Factory\LoggerFactory::create('test', $database, $config, $profiler);
+               $configModel = new \Friendica\Model\Config\Config(self::$dba);
+               $config = Factory\ConfigFactory::createConfig(self::$configCache, $configModel);
+               Factory\ConfigFactory::createPConfig(self::$configCache, new Config\Cache\PConfigCache());
+               $logger = Factory\LoggerFactory::create('test', self::$dba, $config, self::$profiler);
                $baseUrl = new BaseURL($config, $_SERVER);
-               $this->app = new App($database, $config, $mode, $router, $baseUrl, $logger, $profiler, false);
+               $router = new App\Router();
+               $this->app = new App(self::$dba, $config, self::$mode, $router, $baseUrl, $logger, self::$profiler, false);
 
                parent::setUp();
 
index b005d8d53de60d5b897af99a4d620a6a77c570b7..d10f07493bfaa7636ba7e9eec4d7582cad487de5 100644 (file)
@@ -6,27 +6,24 @@ use Friendica\App;
 use Friendica\Core\Config\Cache\PConfigCache;
 use Friendica\Database\DBStructure;
 use Friendica\Factory;
+use Friendica\Model\Config\Config;
 use Friendica\Test\DatabaseTest;
-use Friendica\Util\BasePath;
 use Friendica\Util\BaseURL;
-use Friendica\Util\Config\ConfigFileLoader;
 
 class DBStructureTest extends DatabaseTest
 {
+       /**
+        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+        */
        public function setUp()
        {
-               $basePath = BasePath::create(dirname(__DIR__) . '/../../');
-               $mode = new App\Mode($basePath);
-               $router = new App\Router();
-               $configLoader = new ConfigFileLoader($basePath, $mode);
-               $configCache = Factory\ConfigFactory::createCache($configLoader);
-               $profiler = Factory\ProfilerFactory::create($configCache);
-               $database = Factory\DBFactory::init($configCache, $profiler, $_SERVER);
-               $config = Factory\ConfigFactory::createConfig($configCache);
-               Factory\ConfigFactory::createPConfig($configCache, new PConfigCache());
-               $logger = Factory\LoggerFactory::create('test', $database, $config, $profiler);
+               $configModel = new Config(self::$dba);
+               $config = Factory\ConfigFactory::createConfig(self::$configCache, $configModel);
+               Factory\ConfigFactory::createPConfig(self::$configCache, new PConfigCache());
+               $logger = Factory\LoggerFactory::create('test', self::$dba, $config, self::$profiler);
                $baseUrl = new BaseURL($config, $_SERVER);
-               $this->app = new App($database, $config, $mode, $router, $baseUrl, $logger, $profiler, false);
+               $router = new App\Router();
+               $this->app = new App(self::$dba, $config, self::$mode, $router, $baseUrl, $logger, self::$profiler, false);
 
                parent::setUp();
        }