Browse Source

Config FollowUp

- New Configuration (Config is now only holding the instance)
- New PConfiguration (PConfig is now only holding the instance)

- Config & PConfig-Adapter don't need "ConfigCache" anymore

- DB-Connection is now outside App->reload() for better dependency-chaining
tags/2019.03^2
Philipp Holzer 7 months ago
parent
commit
eafcf3592d
No account linked to committer's email address
59 changed files with 1754 additions and 1038 deletions
  1. 6
    3
      bin/auth_ejabberd.php
  2. 6
    3
      bin/console.php
  3. 7
    3
      bin/daemon.php
  4. 6
    2
      bin/worker.php
  5. 6
    3
      index.php
  6. 10
    62
      src/App.php
  7. 20
    60
      src/Core/Config.php
  8. 8
    1
      src/Core/Config/Adapter/AbstractDbaConfigAdapter.php
  9. 10
    12
      src/Core/Config/Adapter/IConfigAdapter.php
  10. 17
    12
      src/Core/Config/Adapter/IPConfigAdapter.php
  11. 123
    0
      src/Core/Config/Adapter/JITConfigAdapter.php
  12. 126
    0
      src/Core/Config/Adapter/JITPConfigAdapter.php
  13. 104
    0
      src/Core/Config/Adapter/PreloadConfigAdapter.php
  14. 126
    0
      src/Core/Config/Adapter/PreloadPConfigAdapter.php
  15. 75
    57
      src/Core/Config/Cache/ConfigCache.php
  16. 6
    6
      src/Core/Config/Cache/ConfigCacheLoader.php
  17. 65
    0
      src/Core/Config/Cache/IConfigCache.php
  18. 70
    0
      src/Core/Config/Cache/IPConfigCache.php
  19. 154
    0
      src/Core/Config/Configuration.php
  20. 0
    39
      src/Core/Config/IConfigCache.php
  21. 0
    44
      src/Core/Config/IPConfigCache.php
  22. 0
    172
      src/Core/Config/JITConfigAdapter.php
  23. 0
    136
      src/Core/Config/JITPConfigAdapter.php
  24. 150
    0
      src/Core/Config/PConfiguration.php
  25. 0
    123
      src/Core/Config/PreloadConfigAdapter.php
  26. 0
    125
      src/Core/Config/PreloadPConfigAdapter.php
  27. 5
    5
      src/Core/Console/AutomaticInstallation.php
  28. 3
    3
      src/Core/Console/Config.php
  29. 1
    1
      src/Core/Console/Typo.php
  30. 3
    3
      src/Core/Installer.php
  31. 22
    67
      src/Core/PConfig.php
  32. 1
    1
      src/Database/DBA.php
  33. 34
    19
      src/Factory/ConfigFactory.php
  34. 48
    0
      src/Factory/DBFactory.php
  35. 4
    4
      src/Factory/LoggerFactory.php
  36. 2
    2
      src/Module/Install.php
  37. 2
    2
      tests/DatabaseTest.php
  38. 8
    11
      tests/Util/AppMockTrait.php
  39. 6
    2
      tests/include/ApiTest.php
  40. 4
    14
      tests/src/App/ModeTest.php
  41. 1
    1
      tests/src/BaseObjectTest.php
  42. 1
    1
      tests/src/Core/Cache/CacheTest.php
  43. 2
    2
      tests/src/Core/Cache/MemcacheCacheDriverTest.php
  44. 1
    1
      tests/src/Core/Cache/MemcachedCacheDriverTest.php
  45. 2
    2
      tests/src/Core/Cache/RedisCacheDriverTest.php
  46. 7
    3
      tests/src/Core/Config/Cache/ConfigCacheLoaderTest.php
  47. 73
    10
      tests/src/Core/Config/Cache/ConfigCacheTest.php
  48. 215
    0
      tests/src/Core/Config/ConfigurationTest.php
  49. 186
    0
      tests/src/Core/Config/PConfigurationTest.php
  50. 1
    1
      tests/src/Core/Console/AutomaticInstallationConsoleTest.php
  51. 6
    6
      tests/src/Core/Console/ConfigConsoleTest.php
  52. 2
    2
      tests/src/Core/Console/ConsoleTest.php
  53. 1
    1
      tests/src/Core/Lock/LockTest.php
  54. 2
    2
      tests/src/Core/Lock/MemcacheCacheLockDriverTest.php
  55. 1
    1
      tests/src/Core/Lock/MemcachedCacheLockDriverTest.php
  56. 2
    2
      tests/src/Core/Lock/RedisCacheLockDriverTest.php
  57. 1
    1
      tests/src/Core/Lock/SemaphoreLockDriverTest.php
  58. 6
    2
      tests/src/Database/DBATest.php
  59. 6
    3
      tests/src/Database/DBStructureTest.php

+ 6
- 3
bin/auth_ejabberd.php View File

@@ -33,7 +33,7 @@
33 33
  */
34 34
 
35 35
 use Friendica\App;
36
-use Friendica\Core\Config;
36
+use Friendica\Core\Config\Cache;
37 37
 use Friendica\Factory;
38 38
 use Friendica\Util\BasePath;
39 39
 use Friendica\Util\ExAuth;
@@ -55,8 +55,11 @@ chdir($directory);
55 55
 require dirname(__DIR__) . '/vendor/autoload.php';
56 56
 
57 57
 $basedir = BasePath::create(dirname(__DIR__), $_SERVER);
58
-$configLoader = new Config\ConfigCacheLoader($basedir);
59
-$config = Factory\ConfigFactory::createCache($configLoader);
58
+$configLoader = new Cache\ConfigCacheLoader($basedir);
59
+$configCache = Factory\ConfigFactory::createCache($configLoader);
60
+Factory\DBFactory::init($configCache, $_SERVER);
61
+$config = Factory\ConfigFactory::createConfig($configCache);
62
+$pconfig = Factory\ConfigFactory::createPConfig($configCache);
60 63
 $logger = Factory\LoggerFactory::create('auth_ejabberd', $config);
61 64
 $profiler = Factory\ProfilerFactory::create($logger, $config);
62 65
 

+ 6
- 3
bin/console.php View File

@@ -3,13 +3,16 @@
3 3
 
4 4
 require dirname(__DIR__) . '/vendor/autoload.php';
5 5
 
6
-use Friendica\Core\Config;
6
+use Friendica\Core\Config\Cache;
7 7
 use Friendica\Factory;
8 8
 use Friendica\Util\BasePath;
9 9
 
10 10
 $basedir = BasePath::create(dirname(__DIR__), $_SERVER);
11
-$configLoader = new Config\ConfigCacheLoader($basedir);
12
-$config = Factory\ConfigFactory::createCache($configLoader);
11
+$configLoader = new Cache\ConfigCacheLoader($basedir);
12
+$configCache = Factory\ConfigFactory::createCache($configLoader);
13
+Factory\DBFactory::init($configCache, $_SERVER);
14
+$config = Factory\ConfigFactory::createConfig($configCache);
15
+$pconfig = Factory\ConfigFactory::createPConfig($configCache);
13 16
 $logger = Factory\LoggerFactory::create('console', $config);
14 17
 $profiler = Factory\ProfilerFactory::create($logger, $config);
15 18
 

+ 7
- 3
bin/daemon.php View File

@@ -9,6 +9,7 @@
9 9
 
10 10
 use Friendica\App;
11 11
 use Friendica\Core\Config;
12
+use Friendica\Core\Config\Cache;
12 13
 use Friendica\Core\Worker;
13 14
 use Friendica\Database\DBA;
14 15
 use Friendica\Factory;
@@ -34,8 +35,11 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) {
34 35
 require dirname(__DIR__) . '/vendor/autoload.php';
35 36
 
36 37
 $basedir = BasePath::create(dirname(__DIR__), $_SERVER);
37
-$configLoader = new Config\ConfigCacheLoader($basedir);
38
-$config = Factory\ConfigFactory::createCache($configLoader);
38
+$configLoader = new Cache\ConfigCacheLoader($basedir);
39
+$configCache = Factory\ConfigFactory::createCache($configLoader);
40
+Factory\DBFactory::init($configCache, $_SERVER);
41
+$config = Factory\ConfigFactory::createConfig($configCache);
42
+$pconfig = Factory\ConfigFactory::createPConfig($configCache);
39 43
 $logger = Factory\LoggerFactory::create('daemon', $config);
40 44
 $profiler = Factory\ProfilerFactory::create($logger, $config);
41 45
 
@@ -151,7 +155,7 @@ if (!$foreground) {
151 155
 	file_put_contents($pidfile, $pid);
152 156
 
153 157
 	// We lose the database connection upon forking
154
-	$a->loadDatabase();
158
+	Factory\DBFactory::init($configCache, $_SERVER);
155 159
 }
156 160
 
157 161
 Config::set('system', 'worker_daemon_mode', true);

+ 6
- 2
bin/worker.php View File

@@ -7,6 +7,7 @@
7 7
 
8 8
 use Friendica\App;
9 9
 use Friendica\Core\Config;
10
+use Friendica\Core\Config\Cache;
10 11
 use Friendica\Core\Update;
11 12
 use Friendica\Core\Worker;
12 13
 use Friendica\Factory;
@@ -32,8 +33,11 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) {
32 33
 require dirname(__DIR__) . '/vendor/autoload.php';
33 34
 
34 35
 $basedir = BasePath::create(dirname(__DIR__), $_SERVER);
35
-$configLoader = new Config\ConfigCacheLoader($basedir);
36
-$config = Factory\ConfigFactory::createCache($configLoader);
36
+$configLoader = new Cache\ConfigCacheLoader($basedir);
37
+$configCache = Factory\ConfigFactory::createCache($configLoader);
38
+Factory\DBFactory::init($configCache, $_SERVER);
39
+$config = Factory\ConfigFactory::createConfig($configCache);
40
+$pconfig = Factory\ConfigFactory::createPConfig($configCache);
37 41
 $logger = Factory\LoggerFactory::create('worker', $config);
38 42
 $profiler = Factory\ProfilerFactory::create($logger, $config);
39 43
 

+ 6
- 3
index.php View File

@@ -5,7 +5,7 @@
5 5
  */
6 6
 
7 7
 use Friendica\App;
8
-use Friendica\Core\Config;
8
+use Friendica\Core\Config\Cache;
9 9
 use Friendica\Factory;
10 10
 use Friendica\Util\BasePath;
11 11
 
@@ -16,8 +16,11 @@ if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
16 16
 require __DIR__ . '/vendor/autoload.php';
17 17
 
18 18
 $basedir = BasePath::create(__DIR__, $_SERVER);
19
-$configLoader = new Config\ConfigCacheLoader($basedir);
20
-$config = Factory\ConfigFactory::createCache($configLoader);
19
+$configLoader = new Cache\ConfigCacheLoader($basedir);
20
+$configCache = Factory\ConfigFactory::createCache($configLoader);
21
+Factory\DBFactory::init($configCache, $_SERVER);
22
+$config = Factory\ConfigFactory::createConfig($configCache);
23
+$pconfig = Factory\ConfigFactory::createPConfig($configCache);
21 24
 $logger = Factory\LoggerFactory::create('index', $config);
22 25
 $profiler = Factory\ProfilerFactory::create($logger, $config);
23 26
 

+ 10
- 62
src/App.php View File

@@ -8,8 +8,9 @@ use Detection\MobileDetect;
8 8
 use DOMDocument;
9 9
 use DOMXPath;
10 10
 use Exception;
11
-use Friendica\Core\Config\ConfigCache;
12
-use Friendica\Core\Config\ConfigCacheLoader;
11
+use Friendica\Core\Config\Cache\ConfigCacheLoader;
12
+use Friendica\Core\Config\Cache\IConfigCache;
13
+use Friendica\Core\Config\Configuration;
13 14
 use Friendica\Database\DBA;
14 15
 use Friendica\Factory\ConfigFactory;
15 16
 use Friendica\Network\HTTPException\InternalServerErrorException;
@@ -114,7 +115,7 @@ class App
114 115
 	private $logger;
115 116
 
116 117
 	/**
117
-	 * @var ConfigCache The cached config
118
+	 * @var Configuration The config
118 119
 	 */
119 120
 	private $config;
120 121
 
@@ -126,11 +127,11 @@ class App
126 127
 	/**
127 128
 	 * Returns the current config cache of this node
128 129
 	 *
129
-	 * @return ConfigCache
130
+	 * @return IConfigCache
130 131
 	 */
131
-	public function getConfig()
132
+	public function getConfigCache()
132 133
 	{
133
-		return $this->config;
134
+		return $this->config->getCache();
134 135
 	}
135 136
 
136 137
 	/**
@@ -195,14 +196,14 @@ class App
195 196
 	/**
196 197
 	 * @brief App constructor.
197 198
 	 *
198
-	 * @param ConfigCache      $config    The Cached Config
199
+	 * @param Configuration    $config    The Configuration
199 200
 	 * @param LoggerInterface  $logger    Logger of this application
200 201
 	 * @param Profiler         $profiler  The profiler of this application
201 202
 	 * @param bool             $isBackend Whether it is used for backend or frontend (Default true=backend)
202 203
 	 *
203 204
 	 * @throws Exception if the Basepath is not usable
204 205
 	 */
205
-	public function __construct(ConfigCache $config, LoggerInterface $logger, Profiler $profiler, $isBackend = true)
206
+	public function __construct(Configuration $config, LoggerInterface $logger, Profiler $profiler, $isBackend = true)
206 207
 	{
207 208
 		$this->config   = $config;
208 209
 		$this->logger   = $logger;
@@ -358,21 +359,11 @@ class App
358 359
 	 */
359 360
 	public function reload()
360 361
 	{
361
-		Core\Config::init($this->config);
362
-		Core\PConfig::init($this->config);
363
-
364
-		$this->loadDatabase();
365
-
366 362
 		$this->getMode()->determine($this->basePath);
367 363
 
368 364
 		$this->determineURLPath();
369 365
 
370 366
 		if ($this->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
371
-			$adapterType = $this->config->get('system', 'config_adapter');
372
-			$adapter = ConfigFactory::createConfig($adapterType, $this->config);
373
-			Core\Config::setAdapter($adapter);
374
-			$adapterP = ConfigFactory::createPConfig($adapterType, $this->config);
375
-			Core\PConfig::setAdapter($adapterP);
376 367
 			Core\Config::load();
377 368
 		}
378 369
 
@@ -383,7 +374,7 @@ class App
383 374
 			Core\Hook::loadHooks();
384 375
 			$loader = new ConfigCacheLoader($this->basePath);
385 376
 			Core\Hook::callAll('load_config', $loader);
386
-			$this->config->loadConfigArray($loader->loadCoreConfig('addon'), true);
377
+			$this->config->getCache()->load($loader->loadCoreConfig('addon'), true);
387 378
 		}
388 379
 
389 380
 		$this->loadDefaultTimezone();
@@ -453,49 +444,6 @@ class App
453 444
 		}
454 445
 	}
455 446
 
456
-	public function loadDatabase()
457
-	{
458
-		if (DBA::connected()) {
459
-			return;
460
-		}
461
-
462
-		$db_host = $this->config->get('database', 'hostname');
463
-		$db_user = $this->config->get('database', 'username');
464
-		$db_pass = $this->config->get('database', 'password');
465
-		$db_data = $this->config->get('database', 'database');
466
-		$charset = $this->config->get('database', 'charset');
467
-
468
-		// Use environment variables for mysql if they are set beforehand
469
-		if (!empty(getenv('MYSQL_HOST'))
470
-			&& !empty(getenv('MYSQL_USERNAME') || !empty(getenv('MYSQL_USER')))
471
-			&& getenv('MYSQL_PASSWORD') !== false
472
-			&& !empty(getenv('MYSQL_DATABASE')))
473
-		{
474
-			$db_host = getenv('MYSQL_HOST');
475
-			if (!empty(getenv('MYSQL_PORT'))) {
476
-				$db_host .= ':' . getenv('MYSQL_PORT');
477
-			}
478
-			if (!empty(getenv('MYSQL_USERNAME'))) {
479
-				$db_user = getenv('MYSQL_USERNAME');
480
-			} else {
481
-				$db_user = getenv('MYSQL_USER');
482
-			}
483
-			$db_pass = (string) getenv('MYSQL_PASSWORD');
484
-			$db_data = getenv('MYSQL_DATABASE');
485
-		}
486
-
487
-		$stamp1 = microtime(true);
488
-
489
-		if (DBA::connect($this->config, $this->profiler, $db_host, $db_user, $db_pass, $db_data, $charset)) {
490
-			// Loads DB_UPDATE_VERSION constant
491
-			Database\DBStructure::definition($this->basePath, false);
492
-		}
493
-
494
-		unset($db_host, $db_user, $db_pass, $db_data, $charset);
495
-
496
-		$this->profiler->saveTimestamp($stamp1, 'network', Core\System::callstack());
497
-	}
498
-
499 447
 	public function getScheme()
500 448
 	{
501 449
 		return $this->scheme;

+ 20
- 60
src/Core/Config.php View File

@@ -22,116 +22,76 @@ use Friendica\Core\Config\IConfigCache;
22 22
 class Config
23 23
 {
24 24
 	/**
25
-	 * @var Config\IConfigAdapter|null
25
+	 * @var Config\Configuration
26 26
 	 */
27
-	private static $adapter;
27
+	private static $config;
28 28
 
29 29
 	/**
30
-	 * @var Config\IConfigCache
31
-	 */
32
-	private static $cache;
33
-
34
-	/**
35
-	 * Initialize the config with only the cache
36
-	 *
37
-	 * @param Config\IConfigCache $cache  The configuration cache
38
-	 */
39
-	public static function init(Config\IConfigCache $cache)
40
-	{
41
-		self::$cache  = $cache;
42
-	}
43
-
44
-	/**
45
-	 * Add the adapter for DB-backend
30
+	 * Initialize the config
46 31
 	 *
47
-	 * @param Config\IConfigAdapter $adapter
32
+	 * @param Config\Configuration $config
48 33
 	 */
49
-	public static function setAdapter(Config\IConfigAdapter $adapter)
34
+	public static function init(Config\Configuration $config)
50 35
 	{
51
-		self::$adapter = $adapter;
36
+		self::$config = $config;
52 37
 	}
53 38
 
54 39
 	/**
55 40
 	 * @brief Loads all configuration values of family into a cached storage.
56 41
 	 *
57
-	 * All configuration values of the system are stored in the cache ( @see IConfigCache )
58
-	 *
59
-	 * @param string $family The category of the configuration value
42
+	 * @param string $cat The category of the configuration value
60 43
 	 *
61 44
 	 * @return void
62 45
 	 */
63
-	public static function load($family = "config")
46
+	public static function load($cat = "config")
64 47
 	{
65
-		if (!isset(self::$adapter) || !self::$adapter->isConnected()) {
66
-			return;
67
-		}
68
-
69
-		self::$adapter->load($family);
48
+		self::$config->load($cat);
70 49
 	}
71 50
 
72 51
 	/**
73 52
 	 * @brief Get a particular user's config variable given the category name
74 53
 	 * ($family) and a key.
75 54
 	 *
76
-	 * Get a particular config value from the given category ($family)
77
-	 * and the $key from a cached storage either from the self::$adapter
78
-	 * (@see IConfigAdapter ) or from the static::$cache (@see IConfigCache ).
79
-	 *
80
-	 * @param string  $family        The category of the configuration value
55
+	 * @param string  $cat        The category of the configuration value
81 56
 	 * @param string  $key           The configuration key to query
82 57
 	 * @param mixed   $default_value optional, The value to return if key is not set (default: null)
83 58
 	 * @param boolean $refresh       optional, If true the config is loaded from the db and not from the cache (default: false)
84 59
 	 *
85 60
 	 * @return mixed Stored value or null if it does not exist
86 61
 	 */
87
-	public static function get($family, $key, $default_value = null, $refresh = false)
62
+	public static function get($cat, $key, $default_value = null, $refresh = false)
88 63
 	{
89
-		if (!isset(self::$adapter) || !self::$adapter->isConnected()) {
90
-			return self::$cache->get($family, $key, $default_value);
91
-		}
92
-
93
-		return self::$adapter->get($family, $key, $default_value, $refresh);
64
+		return self::$config->get($cat, $key, $default_value, $refresh);
94 65
 	}
95 66
 
96 67
 	/**
97 68
 	 * @brief Sets a configuration value for system config
98 69
 	 *
99
-	 * Stores a config value ($value) in the category ($family) under the key ($key)
70
+	 * Stores a config value ($value) in the category ($cat) under the key ($key)
100 71
 	 *
101 72
 	 * Note: Please do not store booleans - convert to 0/1 integer values!
102 73
 	 *
103
-	 * @param string $family The category of the configuration value
74
+	 * @param string $cat The category of the configuration value
104 75
 	 * @param string $key    The configuration key to set
105 76
 	 * @param mixed  $value  The value to store
106 77
 	 *
107 78
 	 * @return bool Operation success
108 79
 	 */
109
-	public static function set($family, $key, $value)
80
+	public static function set($cat, $key, $value)
110 81
 	{
111
-		if (!isset(self::$adapter) || !self::$adapter->isConnected()) {
112
-			return self::$cache->set($family, $key, $value);
113
-		}
114
-
115
-		return self::$adapter->set($family, $key, $value);
82
+		return self::$config->set($cat, $key, $value);
116 83
 	}
117 84
 
118 85
 	/**
119 86
 	 * @brief Deletes the given key from the system configuration.
120 87
 	 *
121
-	 * Removes the configured value from the stored cache in self::$config
122
-	 * (@see ConfigCache ) and removes it from the database (@see IConfigAdapter ).
123
-	 *
124
-	 * @param string $family The category of the configuration value
88
+	 * @param string $cat The category of the configuration value
125 89
 	 * @param string $key    The configuration key to delete
126 90
 	 *
127
-	 * @return mixed
91
+	 * @return bool
128 92
 	 */
129
-	public static function delete($family, $key)
93
+	public static function delete($cat, $key)
130 94
 	{
131
-		if (!isset(self::$adapter) || !self::$adapter->isConnected()) {
132
-			self::$cache->delete($family, $key);
133
-		}
134
-
135
-		return self::$adapter->delete($family, $key);
95
+		return self::$config->delete($cat, $key);
136 96
 	}
137 97
 }

src/Core/Config/AbstractDbaConfigAdapter.php → src/Core/Config/Adapter/AbstractDbaConfigAdapter.php View File

@@ -1,12 +1,19 @@
1 1
 <?php
2 2
 
3
-namespace Friendica\Core\Config;
3
+namespace Friendica\Core\Config\Adapter;
4
+
5
+use Friendica\Database\DBA;
4 6
 
5 7
 abstract class AbstractDbaConfigAdapter
6 8
 {
7 9
 	/** @var bool */
8 10
 	protected $connected = true;
9 11
 
12
+	public function __construct()
13
+	{
14
+		$this->connected = DBA::connected();
15
+	}
16
+
10 17
 	public function isConnected()
11 18
 	{
12 19
 		return $this->connected;

src/Core/Config/IConfigAdapter.php → src/Core/Config/Adapter/IConfigAdapter.php View File

@@ -1,6 +1,6 @@
1 1
 <?php
2 2
 
3
-namespace Friendica\Core\Config;
3
+namespace Friendica\Core\Config\Adapter;
4 4
 
5 5
 /**
6 6
  *
@@ -13,7 +13,7 @@ interface IConfigAdapter
13 13
 	 *
14 14
 	 * @param string  $cat The category of the configuration values to load
15 15
 	 *
16
-	 * @return void
16
+	 * @return array
17 17
 	 */
18 18
 	public function load($cat = "config");
19 19
 
@@ -21,14 +21,12 @@ interface IConfigAdapter
21 21
 	 * Get a particular user's config variable given the category name
22 22
 	 * ($family) and a key.
23 23
 	 *
24
-	 * @param string  $cat           The category of the configuration value
25
-	 * @param string  $k             The configuration key to query
26
-	 * @param mixed   $default_value optional, The value to return if key is not set (default: null)
27
-	 * @param boolean $refresh       optional, If true the config is loaded from the db and not from the cache (default: false)
24
+	 * @param string  $cat The category of the configuration value
25
+	 * @param string  $key The configuration key to query
28 26
 	 *
29
-	 * @return mixed Stored value or null if it does not exist
27
+	 * @return mixed Stored value or "!<unset>!" if it does not exist
30 28
 	 */
31
-	public function get($cat, $k, $default_value = null, $refresh = false);
29
+	public function get($cat, $key);
32 30
 
33 31
 	/**
34 32
 	 * Stores a config value ($value) in the category ($family) under the key ($key)
@@ -37,23 +35,23 @@ interface IConfigAdapter
37 35
 	 * Note: Please do not store booleans - convert to 0/1 integer values!
38 36
 	 *
39 37
 	 * @param string $cat   The category of the configuration value
40
-	 * @param string $k     The configuration key to set
38
+	 * @param string $key   The configuration key to set
41 39
 	 * @param mixed  $value The value to store
42 40
 	 *
43 41
 	 * @return bool Operation success
44 42
 	 */
45
-	public function set($cat, $k, $value);
43
+	public function set($cat, $key, $value);
46 44
 
47 45
 	/**
48 46
 	 * Removes the configured value from the stored cache
49 47
 	 * and removes it from the database.
50 48
 	 *
51 49
 	 * @param string $cat The category of the configuration value
52
-	 * @param string $k   The configuration key to delete
50
+	 * @param string $key   The configuration key to delete
53 51
 	 *
54 52
 	 * @return mixed
55 53
 	 */
56
-	public function delete($cat, $k);
54
+	public function delete($cat, $key);
57 55
 
58 56
 	/**
59 57
 	 * Checks, if the current adapter is connected to the backend

src/Core/Config/IPConfigAdapter.php → src/Core/Config/Adapter/IPConfigAdapter.php View File

@@ -6,7 +6,7 @@
6 6
  * and open the template in the editor.
7 7
  */
8 8
 
9
-namespace Friendica\Core\Config;
9
+namespace Friendica\Core\Config\Adapter;
10 10
 
11 11
 /**
12 12
  *
@@ -20,7 +20,7 @@ interface IPConfigAdapter
20 20
 	 * @param string $uid The user_id
21 21
 	 * @param string $cat The category of the configuration value
22 22
 	 *
23
-	 * @return void
23
+	 * @return array
24 24
 	 */
25 25
 	public function load($uid, $cat);
26 26
 
@@ -30,13 +30,11 @@ interface IPConfigAdapter
30 30
 	 *
31 31
 	 * @param string  $uid           The user_id
32 32
 	 * @param string  $cat           The category of the configuration value
33
-	 * @param string  $k             The configuration key to query
34
-	 * @param mixed   $default_value optional, The value to return if key is not set (default: null)
35
-	 * @param boolean $refresh       optional, If true the config is loaded from the db and not from the cache (default: false)
33
+	 * @param string  $key           The configuration key to query
36 34
 	 *
37
-	 * @return mixed Stored value or null if it does not exist
35
+	 * @return mixed Stored value or "!<unset>!" if it does not exist
38 36
 	 */
39
-	public function get($uid, $cat, $k, $default_value = null, $refresh = false);
37
+	public function get($uid, $cat, $key);
40 38
 
41 39
 	/**
42 40
 	 * Stores a config value ($value) in the category ($family) under the key ($key)
@@ -46,12 +44,12 @@ interface IPConfigAdapter
46 44
 	 *
47 45
 	 * @param string $uid   The user_id
48 46
 	 * @param string $cat   The category of the configuration value
49
-	 * @param string $k     The configuration key to set
47
+	 * @param string $key   The configuration key to set
50 48
 	 * @param string $value The value to store
51 49
 	 *
52 50
 	 * @return bool Operation success
53 51
 	 */
54
-	public function set($uid, $cat, $k, $value);
52
+	public function set($uid, $cat, $key, $value);
55 53
 
56 54
 	/**
57 55
 	 * Removes the configured value from the stored cache
@@ -59,9 +57,16 @@ interface IPConfigAdapter
59 57
 	 *
60 58
 	 * @param string $uid The user_id
61 59
 	 * @param string $cat The category of the configuration value
62
-	 * @param string $k   The configuration key to delete
60
+	 * @param string $key The configuration key to delete
63 61
 	 *
64
-	 * @return mixed
62
+	 * @return bool
65 63
 	 */
66
-	public function delete($uid, $cat, $k);
64
+	public function delete($uid, $cat, $key);
65
+
66
+	/**
67
+	 * Checks, if the current adapter is connected to the backend
68
+	 *
69
+	 * @return bool
70
+	 */
71
+	public function isConnected();
67 72
 }

+ 123
- 0
src/Core/Config/Adapter/JITConfigAdapter.php View File

@@ -0,0 +1,123 @@
1
+<?php
2
+namespace Friendica\Core\Config\Adapter;
3
+
4
+use Friendica\Database\DBA;
5
+
6
+/**
7
+ * JustInTime Configuration Adapter
8
+ *
9
+ * Default Config Adapter. Provides the best performance for pages loading few configuration variables.
10
+ *
11
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
12
+ */
13
+class JITConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter
14
+{
15
+	private $in_db;
16
+
17
+	/**
18
+	 * {@inheritdoc}
19
+	 */
20
+	public function load($cat = "config")
21
+	{
22
+		$return = [];
23
+
24
+		if (!$this->isConnected()) {
25
+			return $return;
26
+		}
27
+
28
+		// We don't preload "system" anymore.
29
+		// This reduces the number of database reads a lot.
30
+		if ($cat === 'system') {
31
+			return $return;
32
+		}
33
+
34
+		$configs = DBA::select('config', ['v', 'k'], ['cat' => $cat]);
35
+		while ($config = DBA::fetch($configs)) {
36
+			$key = $config['k'];
37
+
38
+			$return[$key] = $config['v'];
39
+			$this->in_db[$cat][$key] = true;
40
+		}
41
+		DBA::close($configs);
42
+
43
+		return [$cat => $config];
44
+	}
45
+
46
+	/**
47
+	 * {@inheritdoc}
48
+	 */
49
+	public function get($cat, $key)
50
+	{
51
+		if (!$this->isConnected()) {
52
+			return '!<unset>!';
53
+		}
54
+
55
+		$config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]);
56
+		if (DBA::isResult($config)) {
57
+			// manage array value
58
+			$value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']);
59
+
60
+			$this->in_db[$cat][$key] = true;
61
+			return $value;
62
+		} else {
63
+
64
+			$this->in_db[$cat][$key] = false;
65
+			return '!<unset>!';
66
+		}
67
+	}
68
+
69
+	/**
70
+	 * {@inheritdoc}
71
+	 */
72
+	public function set($cat, $key, $value)
73
+	{
74
+		if (!$this->isConnected()) {
75
+			return false;
76
+		}
77
+
78
+		// We store our setting values in a string variable.
79
+		// So we have to do the conversion here so that the compare below works.
80
+		// The exception are array values.
81
+		$dbvalue = (!is_array($value) ? (string)$value : $value);
82
+
83
+		$stored = $this->get($cat, $key);
84
+
85
+		if (!isset($this->in_db[$cat])) {
86
+			$this->in_db[$cat] = [];
87
+		}
88
+		if (!isset($this->in_db[$cat][$key])) {
89
+			$this->in_db[$cat][$key] = false;
90
+		}
91
+
92
+		if (($stored === $dbvalue) && $this->in_db[$cat][$key]) {
93
+			return true;
94
+		}
95
+
96
+		// manage array value
97
+		$dbvalue = (is_array($value) ? serialize($value) : $dbvalue);
98
+
99
+		$result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true);
100
+
101
+		$this->in_db[$cat][$key] = $result;
102
+
103
+		return $result;
104
+	}
105
+
106
+	/**
107
+	 * {@inheritdoc}
108
+	 */
109
+	public function delete($cat, $key)
110
+	{
111
+		if (!$this->isConnected()) {
112
+			return false;
113
+		}
114
+
115
+		if (isset($this->cache[$cat][$key])) {
116
+			unset($this->in_db[$cat][$key]);
117
+		}
118
+
119
+		$result = DBA::delete('config', ['cat' => $cat, 'k' => $key]);
120
+
121
+		return $result;
122
+	}
123
+}

+ 126
- 0
src/Core/Config/Adapter/JITPConfigAdapter.php View File

@@ -0,0 +1,126 @@
1
+<?php
2
+namespace Friendica\Core\Config\Adapter;
3
+
4
+use Friendica\Database\DBA;
5
+
6
+/**
7
+ * JustInTime User Configuration Adapter
8
+ *
9
+ * Default PConfig Adapter. Provides the best performance for pages loading few configuration variables.
10
+ *
11
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
12
+ */
13
+class JITPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdapter
14
+{
15
+	private $in_db;
16
+
17
+	/**
18
+	 * {@inheritdoc}
19
+	 */
20
+	public function load($uid, $cat)
21
+	{
22
+		$return = [];
23
+
24
+		if (!$this->isConnected()) {
25
+			return $return;
26
+		}
27
+
28
+		$pconfigs = DBA::select('pconfig', ['v', 'k'], ['cat' => $cat, 'uid' => $uid]);
29
+		if (DBA::isResult($pconfigs)) {
30
+			while ($pconfig = DBA::fetch($pconfigs)) {
31
+				$key = $pconfig['k'];
32
+
33
+				$return[$key] = $pconfig['v'];
34
+
35
+				$this->in_db[$uid][$cat][$key] = true;
36
+			}
37
+		} else if ($cat != 'config') {
38
+			// Negative caching
39
+			$return[null] = "!<unset>!";
40
+		}
41
+		DBA::close($pconfigs);
42
+
43
+		return [$cat => $return];
44
+	}
45
+
46
+	/**
47
+	 * {@inheritdoc}
48
+	 */
49
+	public function get($uid, $cat, $key)
50
+	{
51
+		if (!$this->isConnected()) {
52
+			return null;
53
+		}
54
+
55
+		$pconfig = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]);
56
+		if (DBA::isResult($pconfig)) {
57
+			// manage array value
58
+			$value = (preg_match("|^a:[0-9]+:{.*}$|s", $pconfig['v']) ? unserialize($pconfig['v']) : $pconfig['v']);
59
+
60
+			$this->in_db[$uid][$cat][$key] = true;
61
+			return $value;
62
+		} else {
63
+
64
+			$this->in_db[$uid][$cat][$key] = false;
65
+			return '!<unset>!';
66
+		}
67
+	}
68
+
69
+	/**
70
+	 * {@inheritdoc}
71
+	 */
72
+	public function set($uid, $cat, $key, $value)
73
+	{
74
+		if (!$this->isConnected()) {
75
+			return false;
76
+		}
77
+
78
+		// We store our setting values in a string variable.
79
+		// So we have to do the conversion here so that the compare below works.
80
+		// The exception are array values.
81
+		$dbvalue = (!is_array($value) ? (string)$value : $value);
82
+
83
+		$stored = $this->get($uid, $cat, $key);
84
+
85
+		if (!isset($this->in_db[$uid])) {
86
+			$this->in_db[$uid] = [];
87
+		}
88
+		if (!isset($this->in_db[$uid][$cat])) {
89
+			$this->in_db[$uid][$cat] = [];
90
+		}
91
+		if (!isset($this->in_db[$uid][$cat][$key])) {
92
+			$this->in_db[$uid][$cat][$key] = false;
93
+		}
94
+
95
+		if (($stored === $dbvalue) && $this->in_db[$uid][$cat][$key]) {
96
+			return true;
97
+		}
98
+
99
+		// manage array value
100
+		$dbvalue = (is_array($value) ? serialize($value) : $dbvalue);
101
+
102
+		$result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true);
103
+
104
+		$this->in_db[$uid][$cat][$key] = $result;
105
+
106
+		return $result;
107
+	}
108
+
109
+	/**
110
+	 * {@inheritdoc}
111
+	 */
112
+	public function delete($uid, $cat, $key)
113
+	{
114
+		if (!$this->isConnected()) {
115
+			return false;
116
+		}
117
+
118
+		if (!empty($this->in_db[$uid][$cat][$key])) {
119
+			unset($this->in_db[$uid][$cat][$key]);
120
+		}
121
+
122
+		$result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]);
123
+
124
+		return $result;
125
+	}
126
+}

+ 104
- 0
src/Core/Config/Adapter/PreloadConfigAdapter.php View File

@@ -0,0 +1,104 @@
1
+<?php
2
+
3
+namespace Friendica\Core\Config\Adapter;
4
+
5
+use Friendica\Database\DBA;
6
+
7
+/**
8
+ * Preload Configuration Adapter
9
+ *
10
+ * Minimizes the number of database queries to retrieve configuration values at the cost of memory.
11
+ *
12
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
13
+ */
14
+class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter
15
+{
16
+	private $config_loaded = false;
17
+
18
+	/**
19
+	 * {@inheritdoc}
20
+	 */
21
+	public function load($cat = 'config')
22
+	{
23
+		$return = [];
24
+
25
+		if (!$this->isConnected()) {
26
+			return $return;
27
+		}
28
+
29
+		if ($this->config_loaded) {
30
+			return $return;
31
+		}
32
+
33
+		$configs = DBA::select('config', ['cat', 'v', 'k']);
34
+		while ($config = DBA::fetch($configs)) {
35
+			$return[$config['k']] = $config['v'];
36
+		}
37
+		DBA::close($configs);
38
+
39
+		$this->config_loaded = true;
40
+
41
+		return [$cat => $return];
42
+	}
43
+
44
+	/**
45
+	 * {@inheritdoc}
46
+	 */
47
+	public function get($cat, $key)
48
+	{
49
+		if (!$this->isConnected()) {
50
+			return null;
51
+		}
52
+
53
+		$config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]);
54
+		if (DBA::isResult($config)) {
55
+			// manage array value
56
+			$value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']);
57
+
58
+			return $value;
59
+		} else {
60
+
61
+			return '!<unset>!';
62
+		}
63
+	}
64
+
65
+	/**
66
+	 * {@inheritdoc}
67
+	 */
68
+	public function set($cat, $key, $value)
69
+	{
70
+		if (!$this->isConnected()) {
71
+			return false;
72
+		}
73
+
74
+		// We store our setting values as strings.
75
+		// So we have to do the conversion here so that the compare below works.
76
+		// The exception are array values.
77
+		$compare_value = !is_array($value) ? (string)$value : $value;
78
+
79
+		if ($this->get($cat, $key) === $compare_value) {
80
+			return true;
81
+		}
82
+
83
+		// manage array value
84
+		$dbvalue = is_array($value) ? serialize($value) : $value;
85
+
86
+		$result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true);
87
+
88
+		return $result;
89
+	}
90
+
91
+	/**
92
+	 * {@inheritdoc}
93
+	 */
94
+	public function delete($cat, $key)
95
+	{
96
+		if (!$this->isConnected()) {
97
+			return false;
98
+		}
99
+
100
+		$result = DBA::delete('config', ['cat' => $cat, 'k' => $key]);
101
+
102
+		return $result;
103
+	}
104
+}

+ 126
- 0
src/Core/Config/Adapter/PreloadPConfigAdapter.php View File

@@ -0,0 +1,126 @@
1
+<?php
2
+
3
+namespace Friendica\Core\Config\Adapter;
4
+
5
+use Friendica\Database\DBA;
6
+
7
+/**
8
+ * Preload User Configuration Adapter
9
+ *
10
+ * Minimizes the number of database queries to retrieve configuration values at the cost of memory.
11
+ *
12
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
13
+ */
14
+class PreloadPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdapter
15
+{
16
+	private $config_loaded = false;
17
+
18
+	/**
19
+	 * @param int $uid The UID of the current user
20
+	 */
21
+	public function __construct($uid = null)
22
+	{
23
+		parent::__construct();
24
+
25
+		if (isset($uid)) {
26
+			$this->load($uid, 'config');
27
+		}
28
+	}
29
+
30
+	/**
31
+	 * {@inheritdoc}
32
+	 */
33
+	public function load($uid, $cat)
34
+	{
35
+		$return = [];
36
+
37
+		if ($this->config_loaded) {
38
+			return $return;
39
+		}
40
+
41
+		if (empty($uid)) {
42
+			return $return;
43
+		}
44
+
45
+		$pconfigs = DBA::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]);
46
+		while ($pconfig = DBA::fetch($pconfigs)) {
47
+			$return[$pconfig['k']] = $pconfig['v'];
48
+		}
49
+		DBA::close($pconfigs);
50
+
51
+		$this->config_loaded = true;
52
+
53
+		return [$cat => $return];
54
+	}
55
+
56
+	/**
57
+	 * {@inheritdoc}
58
+	 */
59
+	public function get($uid, $cat, $key)
60
+	{
61
+		if (!$this->isConnected()) {
62
+			return null;
63
+		}
64
+
65
+		if (!$this->config_loaded) {
66
+			$this->load($uid, $cat);
67
+		}
68
+
69
+		$config = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]);
70
+		if (DBA::isResult($config)) {
71
+			// manage array value
72
+			$value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']);
73
+
74
+			return $value;
75
+		} else {
76
+			return '!<unset>!';
77
+		}
78
+	}
79
+
80
+	/**
81
+	 * {@inheritdoc}
82
+	 */
83
+	public function set($uid, $cat, $key, $value)
84
+	{
85
+		if (!$this->isConnected()) {
86
+			return false;
87
+		}
88
+
89
+		if (!$this->config_loaded) {
90
+			$this->load($uid, $cat);
91
+		}
92
+		// We store our setting values as strings.
93
+		// So we have to do the conversion here so that the compare below works.
94
+		// The exception are array values.
95
+		$compare_value = !is_array($value) ? (string)$value : $value;
96
+
97
+		if ($this->get($uid, $cat, $key) === $compare_value) {
98
+			return true;
99
+		}
100
+
101
+		// manage array value
102
+		$dbvalue = is_array($value) ? serialize($value) : $value;
103
+
104
+		$result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true);
105
+
106
+		return $result;
107
+	}
108
+
109
+	/**
110
+	 * {@inheritdoc}
111
+	 */
112
+	public function delete($uid, $cat, $key)
113
+	{
114
+		if (!$this->isConnected()) {
115
+			return false;
116
+		}
117
+
118
+		if (!$this->config_loaded) {
119
+			$this->load($uid, $cat);
120
+		}
121
+
122
+		$result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]);
123
+
124
+		return $result;
125
+	}
126
+}

src/Core/Config/ConfigCache.php → src/Core/Config/Cache/ConfigCache.php View File

@@ -1,6 +1,6 @@
1 1
 <?php
2 2
 
3
-namespace Friendica\Core\Config;
3
+namespace Friendica\Core\Config\Cache;
4 4
 
5 5
 /**
6 6
  * The Friendica config cache for the application
@@ -11,6 +11,9 @@ namespace Friendica\Core\Config;
11 11
  */
12 12
 class ConfigCache implements IConfigCache, IPConfigCache
13 13
 {
14
+	/**
15
+	 * @var array
16
+	 */
14 17
 	private $config;
15 18
 
16 19
 	/**
@@ -18,24 +21,28 @@ class ConfigCache implements IConfigCache, IPConfigCache
18 21
 	 */
19 22
 	public function __construct(array $config = [])
20 23
 	{
21
-		$this->loadConfigArray($config);
24
+		$this->load($config);
22 25
 	}
23 26
 
24 27
 	/**
25
-	 * Tries to load the specified configuration array into the App->config array.
26
-	 * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config.
27
-	 *
28
-	 * @param array $config
29
-	 * @param bool  $overwrite Force value overwrite if the config key already exists
28
+	 * {@inheritdoc}
30 29
 	 */
31
-	public function loadConfigArray(array $config, $overwrite = false)
30
+	public function load(array $config, $overwrite = false)
32 31
 	{
33
-		foreach ($config as $category => $values) {
34
-			foreach ($values as $key => $value) {
35
-				if ($overwrite) {
36
-					$this->set($category, $key, $value);
37
-				} else {
38
-					$this->setDefault($category, $key, $value);
32
+		$categories = array_keys($config);
33
+
34
+		foreach ($categories as $category) {
35
+			if (isset($config[$category]) && is_array($config[$category])) {
36
+				$keys = array_keys($config[$category]);
37
+
38
+				foreach ($keys as $key) {
39
+					if (isset($config[$category][$key])) {
40
+						if ($overwrite) {
41
+							$this->set($category, $key, $config[$category][$key]);
42
+						} else {
43
+							$this->setDefault($category, $key, $config[$category][$key]);
44
+						}
45
+					}
39 46
 				}
40 47
 			}
41 48
 		}
@@ -44,23 +51,22 @@ class ConfigCache implements IConfigCache, IPConfigCache
44 51
 	/**
45 52
 	 * {@inheritdoc}
46 53
 	 */
47
-	public function get($cat, $key = null, $default = null)
54
+	public function get($cat, $key = null)
48 55
 	{
49
-		$return = $default;
50
-
51
-		if ($cat === 'config') {
52
-			if (isset($this->config[$key])) {
53
-				$return = $this->config[$key];
54
-			}
56
+		if (isset($this->config[$cat][$key])) {
57
+			return $this->config[$cat][$key];
55 58
 		} else {
56
-			if (isset($this->config[$cat][$key])) {
57
-				$return = $this->config[$cat][$key];
58
-			} elseif ($key == null && isset($this->config[$cat])) {
59
-				$return = $this->config[$cat];
60
-			}
59
+			return '!<unset>!';
61 60
 		}
61
+	}
62 62
 
63
-		return $return;
63
+	/**
64
+	 * {@inheritdoc}
65
+	 */
66
+	public function has($cat, $key = null)
67
+	{
68
+		return isset($this->config[$cat][$key])
69
+			&& $this->config[$cat][$key] !== '!<unset>!';
64 70
 	}
65 71
 
66 72
 	/**
@@ -85,52 +91,62 @@ class ConfigCache implements IConfigCache, IPConfigCache
85 91
 		// Only arrays are serialized in database, so we have to unserialize sparingly
86 92
 		$value = is_string($value) && preg_match("|^a:[0-9]+:{.*}$|s", $value) ? unserialize($value) : $value;
87 93
 
88
-		if ($cat === 'config') {
89
-			$this->config[$key] = $value;
90
-		} else {
91
-			if (!isset($this->config[$cat])) {
92
-				$this->config[$cat] = [];
93
-			}
94
-
95
-			$this->config[$cat][$key] = $value;
94
+		if (!isset($this->config[$cat])) {
95
+			$this->config[$cat] = [];
96 96
 		}
97 97
 
98
+		$this->config[$cat][$key] = $value;
99
+
98 100
 		return true;
99 101
 	}
100 102
 
103
+	/**
104
+	 * {@inheritdoc}
105
+	 */
106
+	public function hasP($uid, $cat, $key = null)
107
+	{
108
+		return isset($this->config[$uid][$cat][$key])
109
+			&& $this->config[$uid][$cat][$key] !== '!<unset>!';
110
+	}
111
+
101 112
 	/**
102 113
 	 * {@inheritdoc}
103 114
 	 */
104 115
 	public function delete($cat, $key)
105 116
 	{
106
-		if ($cat === 'config') {
107
-			if (isset($this->config[$key])) {
108
-				unset($this->config[$key]);
117
+		if (isset($this->config[$cat][$key])) {
118
+			unset($this->config[$cat][$key]);
119
+			if (count($this->config[$cat]) == 0) {
120
+				unset($this->config[$cat]);
109 121
 			}
122
+			return true;
110 123
 		} else {
111
-			if (isset($this->config[$cat][$key])) {
112
-				unset($this->config[$cat][$key]);
113
-				if (count($this->config[$cat]) == 0) {
114
-					unset($this->config[$cat]);
115
-				}
116
-			}
124
+			return false;
117 125
 		}
118 126
 	}
119 127
 
120 128
 	/**
121 129
 	 * {@inheritdoc}
122 130
 	 */
123
-	public function getP($uid, $cat, $key = null, $default = null)
131
+	public function loadP($uid, array $config)
124 132
 	{
125
-		$return = $default;
133
+		foreach ($config as $category => $values) {
134
+			foreach ($values as $key => $value) {
135
+				$this->setP($uid, $category, $key, $value);
136
+			}
137
+		}
138
+	}
126 139
 
140
+	/**
141
+	 * {@inheritdoc}
142
+	 */
143
+	public function getP($uid, $cat, $key = null)
144
+	{
127 145
 		if (isset($this->config[$uid][$cat][$key])) {
128
-			$return = $this->config[$uid][$cat][$key];
129
-		} elseif ($key === null && isset($this->config[$uid][$cat])) {
130
-			$return = $this->config[$uid][$cat];
146
+			return $this->config[$uid][$cat][$key];
147
+		} else {
148
+			return '!<unset>!';
131 149
 		}
132
-
133
-		return $return;
134 150
 	}
135 151
 
136 152
 	/**
@@ -145,15 +161,13 @@ class ConfigCache implements IConfigCache, IPConfigCache
145 161
 			$this->config[$uid] = [];
146 162
 		}
147 163
 
148
-		if (!isset($this->config[$uid][$cat]) || !is_array($this->config[$uid][$cat])) {
164
+		if (!isset($this->config[$uid][$cat])) {
149 165
 			$this->config[$uid][$cat] = [];
150 166
 		}
151 167
 
152
-		if ($key === null) {
153
-			$this->config[$uid][$cat] = $value;
154
-		} else {
155
-			$this->config[$uid][$cat][$key] = $value;
156
-		}
168
+		$this->config[$uid][$cat][$key] = $value;
169
+
170
+		return true;
157 171
 	}
158 172
 
159 173
 	/**
@@ -169,6 +183,10 @@ class ConfigCache implements IConfigCache, IPConfigCache
169 183
 					unset($this->config[$uid]);
170 184
 				}
171 185
 			}
186
+
187
+			return true;
188
+		} else {
189
+			return false;
172 190
 		}
173 191
 	}
174 192
 

src/Core/Config/ConfigCacheLoader.php → src/Core/Config/Cache/ConfigCacheLoader.php View File

@@ -1,6 +1,6 @@
1 1
 <?php
2 2
 
3
-namespace Friendica\Core\Config;
3
+namespace Friendica\Core\Config\Cache;
4 4
 
5 5
 use Friendica\Core\Addon;
6 6
 
@@ -40,13 +40,13 @@ class ConfigCacheLoader
40 40
 		// Setting at least the basepath we know
41 41
 		$config->set('system', 'basepath', $this->baseDir);
42 42
 
43
-		$config->loadConfigArray($this->loadCoreConfig('defaults'));
44
-		$config->loadConfigArray($this->loadCoreConfig('settings'));
43
+		$config->load($this->loadCoreConfig('defaults'));
44
+		$config->load($this->loadCoreConfig('settings'));
45 45
 
46
-		$config->loadConfigArray($this->loadLegacyConfig('htpreconfig'), true);
47
-		$config->loadConfigArray($this->loadLegacyConfig('htconfig'), true);
46
+		$config->load($this->loadLegacyConfig('htpreconfig'), true);
47
+		$config->load($this->loadLegacyConfig('htconfig'), true);
48 48
 
49
-		$config->loadConfigArray($this->loadCoreConfig('local'), true);
49
+		$config->load($this->loadCoreConfig('local'), true);
50 50
 	}
51 51
 
52 52
 	/**

+ 65
- 0
src/Core/Config/Cache/IConfigCache.php View File

@@ -0,0 +1,65 @@
1
+<?php
2
+
3
+namespace Friendica\Core\Config\Cache;
4
+
5
+/**
6
+ * The interface for a system-wide ConfigCache
7
+ */
8
+interface IConfigCache
9
+{
10
+	/**
11
+	 * Tries to load the specified configuration array into the config array.
12
+	 * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config.
13
+	 *
14
+	 * @param array $config
15
+	 * @param bool  $overwrite Force value overwrite if the config key already exists
16
+	 */
17
+	function load(array $config, $overwrite = false);
18
+
19
+	/**
20
+	 * Gets a value from the config cache.
21
+	 *
22
+	 * @param string $cat     Config category
23
+	 * @param string $key       Config key
24
+	 *
25
+	 * @return mixed Returns the value of the Config entry or '!<unset>!' if not set
26
+	 */
27
+	function get($cat, $key = null);
28
+
29
+	/**
30
+	 * Sets a value in the config cache. Accepts raw output from the config table
31
+	 *
32
+	 * @param string $cat   Config category
33
+	 * @param string $key   Config key
34
+	 * @param mixed  $value Value to set
35
+	 *
36
+	 * @return bool True, if the value is set
37
+	 */
38
+	function set($cat, $key, $value);
39
+
40
+	/**
41
+	 * Deletes a value from the config cache.
42
+	 *
43
+	 * @param string $cat  Config category
44
+	 * @param string $key  Config key
45
+	 *
46
+	 * @return bool true, if deleted
47
+	 */
48
+	function delete($cat, $key);
49
+
50
+	/**
51
+	 * Checks if a value is set in the config cache.
52
+	 *
53
+	 * @param string $cat  Config category
54
+	 * @param string $key  Config key
55
+	 * @return bool
56
+	 */
57
+	function has($cat, $key = null);
58
+
59
+	/**
60
+	 * Returns the whole configuration cache
61
+	 *
62
+	 * @return array
63
+	 */
64
+	function getAll();
65
+}

+ 70
- 0
src/Core/Config/Cache/IPConfigCache.php View File

@@ -0,0 +1,70 @@
1
+<?php
2
+
3
+namespace Friendica\Core\Config\Cache;
4
+
5
+/**
6
+ * The interface for a user-specific config cache
7
+ */
8
+interface IPConfigCache
9
+{
10
+	/**
11
+	 * Tries to load the specified configuration array into the user specific config array.
12
+	 * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config.
13
+	 *
14
+	 * @param int   $uid
15
+	 * @param array $config
16
+	 */
17
+	function loadP($uid, array $config);
18
+
19
+	/**
20
+	 * Retrieves a value from the user config cache
21
+	 *
22
+	 * @param int    $uid     User Id
23
+	 * @param string $cat     Config category
24
+	 * @param string $key     Config key
25
+	 *
26
+	 * @return string The value of the config entry or '!<unset>!' if not set
27
+	 */
28
+	function getP($uid, $cat, $key = null);
29
+
30
+	/**
31
+	 * Sets a value in the user config cache
32
+	 *
33
+	 * Accepts raw output from the pconfig table
34
+	 *
35
+	 * @param int    $uid   User Id
36
+	 * @param string $cat   Config category
37
+	 * @param string $key   Config key
38
+	 * @param mixed  $value Value to set
39
+	 */
40
+	function setP($uid, $cat, $key, $value);
41
+
42
+	/**
43
+	 * Deletes a value from the user config cache
44
+	 *
45
+	 * @param int    $uid User Id
46
+	 * @param string $cat Config category
47
+	 * @param string $key Config key
48
+	 *
49
+	 * @return bool true, if deleted
50
+	 */
51
+	function deleteP($uid, $cat, $key);
52
+
53
+
54
+	/**
55
+	 * Checks if a value is set in the user config cache.
56
+	 *
57
+	 * @param int    $uid  User Id
58
+	 * @param string $cat  Config category
59
+	 * @param string $key  Config key
60
+	 * @return bool
61
+	 */
62
+	function hasP($uid, $cat, $key = null);
63
+
64
+	/**
65
+	 * Returns the whole configuration cache
66
+	 *
67
+	 * @return array
68
+	 */
69
+	function getAll();
70
+}

+ 154
- 0
src/Core/Config/Configuration.php View File

@@ -0,0 +1,154 @@
1
+<?php
2
+
3
+namespace Friendica\Core\Config;
4
+
5
+/**
6
+ * This class is responsible for all system-wide configuration values in Friendica
7
+ * There are two types of storage
8
+ * - The Config-Files    (loaded into the FileCache @see Cache\IConfigCache )
9
+ * - The Config-DB-Table (per Config-DB-adapter @see Adapter\IConfigAdapter )
10
+ */
11
+class Configuration
12
+{
13
+	/**
14
+	 * @var Cache\IConfigCache
15
+	 */
16
+	private $configCache;
17
+
18
+	/**
19
+	 * @var Adapter\IConfigAdapter
20
+	 */
21
+	private $configAdapter;
22
+
23
+	/**
24
+	 * @param Cache\IConfigCache     $configCache   The configuration cache (based on the config-files)
25
+	 * @param Adapter\IConfigAdapter $configAdapter The configuration DB-backend
26
+	 */
27
+	public function __construct(Cache\IConfigCache $configCache, Adapter\IConfigAdapter $configAdapter)
28
+	{
29
+		$this->configCache = $configCache;
30
+		$this->configAdapter = $configAdapter;
31
+
32
+		$this->load();
33
+	}
34
+
35
+	/**
36
+	 * Returns the Config Cache
37
+	 *
38
+	 * @return Cache\IConfigCache
39
+	 */
40
+	public function getCache()
41
+	{
42
+		return $this->configCache;
43
+	}
44
+
45
+	/**
46
+	 * @brief Loads all configuration values of family into a cached storage.
47
+	 *
48
+	 * All configuration values of the system are stored in the cache ( @see IConfigCache )
49
+	 *
50
+	 * @param string $cat The category of the configuration value
51
+	 *
52
+	 * @return void
53
+	 */
54
+	public function load($cat = 'config')
55
+	{
56
+		// If not connected, do nothing
57
+		if (!$this->configAdapter->isConnected()) {
58
+			return;
59
+		}
60
+
61
+		// load the whole category out of the DB into the cache
62
+		$this->configCache->load($this->configAdapter->load($cat), true);
63
+	}
64
+
65
+	/**
66
+	 * @brief Get a particular user's config variable given the category name
67
+	 * ($cat) and a $key.
68
+	 *
69
+	 * Get a particular config value from the given category ($cat)
70
+	 * and the $key from a cached storage either from the $this->configAdapter
71
+	 * (@see IConfigAdapter ) or from the $this->configCache (@see IConfigCache ).
72
+	 *
73
+	 * @param string  $cat        The category of the configuration value
74
+	 * @param string  $key           The configuration key to query
75
+	 * @param mixed   $default_value optional, The value to return if key is not set (default: null)
76
+	 * @param boolean $refresh       optional, If true the config is loaded from the db and not from the cache (default: false)
77
+	 *
78
+	 * @return mixed Stored value or null if it does not exist
79
+	 */
80
+	public function get($cat, $key, $default_value = null, $refresh = false)
81
+	{
82
+		// Return the value of the cache if found and no refresh is forced
83
+		if (!$refresh && $this->configCache->has($cat, $key)) {
84
+			return $this->configCache->get($cat, $key);
85
+		}
86
+
87
+		// if we don't find the value in the cache and the adapter isn't ready, return the default value
88
+		if (!$this->configAdapter->isConnected()) {
89
+			return $default_value;
90
+		}
91
+
92
+		// load DB value to cache
93
+		$dbvalue = $this->configAdapter->get($cat, $key);
94
+
95
+		if ($dbvalue !== '!<unset>!') {
96
+			$this->configCache->set($cat, $key, $dbvalue);
97
+			return $dbvalue;
98
+		} else {
99
+			return $default_value;
100
+		}
101
+	}
102
+
103
+	/**
104
+	 * @brief Sets a configuration value for system config
105
+	 *
106
+	 * Stores a config value ($value) in the category ($cat) under the key ($key)
107
+	 *
108
+	 * Note: Please do not store booleans - convert to 0/1 integer values!
109
+	 *
110
+	 * @param string $cat The category of the configuration value
111
+	 * @param string $key    The configuration key to set
112
+	 * @param mixed  $value  The value to store
113
+	 *
114
+	 * @return bool Operation success
115
+	 */
116
+	public function set($cat, $key, $value)
117
+	{
118
+		// set the cache first
119
+		$cached = $this->configCache->set($cat, $key, $value);
120
+
121
+		// If there is no connected adapter, we're finished
122
+		if (!$this->configAdapter->isConnected()) {
123
+			return $cached;
124
+		}
125
+
126
+		$stored = $this->configAdapter->set($cat, $key, $value);
127
+
128
+		return $cached && $stored;
129
+	}
130
+
131
+	/**
132
+	 * @brief Deletes the given key from the system configuration.
133
+	 *
134
+	 * Removes the configured value from the stored cache in $this->configCache
135
+	 * (@see ConfigCache ) and removes it from the database (@see IConfigAdapter ).
136
+	 *
137
+	 * @param string $cat The category of the configuration value
138
+	 * @param string $key    The configuration key to delete
139
+	 *
140
+	 * @return bool
141
+	 */
142
+	public function delete($cat, $key)
143
+	{
144
+		$cacheRemoved = $this->configCache->delete($cat, $key);
145
+
146
+		if (!$this->configAdapter->isConnected()) {
147
+			return $cacheRemoved;
148
+		}
149
+
150
+		$storeRemoved = $this->configAdapter->delete($cat, $key);
151
+
152
+		return $cacheRemoved || $storeRemoved;
153
+	}
154
+}

+ 0
- 39
src/Core/Config/IConfigCache.php View File

@@ -1,39 +0,0 @@
1
-<?php
2
-
3
-namespace Friendica\Core\Config;
4
-
5
-/**
6
- * The interface for a system-wide ConfigCache
7
- */
8
-interface IConfigCache
9
-{
10
-	/**
11
-	 * @param string $cat     Config category
12
-	 * @param string $key       Config key
13
-	 * @param mixed  $default Default value if it isn't set
14
-	 *
15
-	 * @return mixed Returns the value of the Config entry
16
-	 */
17
-	function get($cat, $key = null, $default = null);
18
-
19
-	/**
20
-	 * Sets a value in the config cache. Accepts raw output from the config table
21
-	 *
22
-	 * @param string $cat   Config category
23
-	 * @param string $key   Config key
24
-	 * @param mixed  $value Value to set
25
-	 *
26
-	 * @return bool True, if the value is set
27
-	 */
28
-	function set($cat, $key, $value);
29
-
30
-	/**
31
-	 * Deletes a value from the config cache
32
-	 *
33
-	 * @param string $cat  Config category
34
-	 * @param string $key  Config key
35
-	 */
36
-	function delete($cat, $key);
37
-
38
-	function getAll();
39
-}

+ 0
- 44
src/Core/Config/IPConfigCache.php View File

@@ -1,44 +0,0 @@
1
-<?php
2
-
3
-namespace Friendica\Core\Config;
4
-
5
-/**
6
- * The interface for a user-specific config cache
7
- */
8
-interface IPConfigCache
9
-{
10
-	/**
11
-	 * Retrieves a value from the user config cache
12
-	 *
13
-	 * @param int    $uid     User Id
14
-	 * @param string $cat     Config category
15
-	 * @param string $key     Config key
16
-	 * @param mixed  $default Default value if key isn't set
17
-	 *
18
-	 * @return string The value of the config entry
19
-	 */
20
-	function getP($uid, $cat, $key = null, $default = null);
21
-
22
-	/**
23
-	 * Sets a value in the user config cache
24
-	 *
25
-	 * Accepts raw output from the pconfig table
26
-	 *
27
-	 * @param int    $uid   User Id
28
-	 * @param string $cat   Config category
29
-	 * @param string $key   Config key
30
-	 * @param mixed  $value Value to set
31
-	 */
32
-	function setP($uid, $cat, $key, $value);
33
-
34
-	/**
35
-	 * Deletes a value from the user config cache
36
-	 *
37
-	 * @param int    $uid User Id
38
-	 * @param string $cat Config category
39
-	 * @param string $key Config key
40
-	 */
41
-	function deleteP($uid, $cat, $key);
42
-
43
-	function getAll();
44
-}

+ 0
- 172
src/Core/Config/JITConfigAdapter.php View File

@@ -1,172 +0,0 @@
1
-<?php
2
-namespace Friendica\Core\Config;
3
-
4
-use Friendica\Database\DBA;
5
-
6
-/**
7
- * JustInTime Configuration Adapter
8
- *
9
- * Default Config Adapter. Provides the best performance for pages loading few configuration variables.
10
- *
11
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
12
- */
13
-class JITConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter
14
-{
15
-	private $cache;
16
-	private $in_db;
17
-
18
-	/**
19
-	 * @var IConfigCache The config cache of this driver
20
-	 */
21
-	private $configCache;
22
-
23
-	/**
24
-	 * @param IConfigCache $configCache The config cache of this driver
25
-	 */
26
-	public function __construct(IConfigCache $configCache)
27
-	{
28
-		$this->configCache = $configCache;
29
-		$this->connected = DBA::connected();
30
-	}
31
-
32
-	/**
33
-	 * {@inheritdoc}
34
-	 */
35
-	public function load($cat = "config")
36
-	{
37
-		if (!$this->isConnected()) {
38
-			return;
39
-		}
40
-
41
-		// We don't preload "system" anymore.
42
-		// This reduces the number of database reads a lot.
43
-		if ($cat === 'system') {
44
-			return;
45
-		}
46
-
47
-		$configs = DBA::select('config', ['v', 'k'], ['cat' => $cat]);
48
-		while ($config = DBA::fetch($configs)) {
49
-			$k = $config['k'];
50
-
51
-			$this->configCache->set($cat, $k, $config['v']);
52
-
53
-			if ($cat !== 'config') {
54
-				$this->cache[$cat][$k] = $config['v'];
55
-				$this->in_db[$cat][$k] = true;
56
-			}
57
-		}
58
-		DBA::close($configs);
59
-	}
60
-
61
-	/**
62
-	 * {@inheritdoc}
63
-	 */
64
-	public function get($cat, $k, $default_value = null, $refresh = false)
65
-	{
66
-		if (!$this->isConnected()) {
67
-			return $default_value;
68
-		}
69
-
70
-		if (!$refresh) {
71
-			// Do we have the cached value? Then return it
72
-			if (isset($this->cache[$cat][$k])) {
73
-				if ($this->cache[$cat][$k] === '!<unset>!') {
74
-					return $default_value;
75
-				} else {
76
-					return $this->cache[$cat][$k];
77
-				}
78
-			}
79
-		}
80
-
81
-		$config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $k]);
82
-		if (DBA::isResult($config)) {
83
-			// manage array value
84
-			$value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']);
85
-
86
-			// Assign the value from the database to the cache
87
-			$this->cache[$cat][$k] = $value;
88
-			$this->in_db[$cat][$k] = true;
89
-			return $value;
90
-		} elseif ($this->configCache->get($cat, $k) !== null) {
91
-			// Assign the value (mostly) from config/local.config.php file to the cache
92
-			$this->cache[$cat][$k] = $this->configCache->get($cat, $k);
93
-			$this->in_db[$cat][$k] = false;
94
-
95
-			return $this->configCache->get($cat, $k);
96
-		} elseif ($this->configCache->get('config', $k) !== null) {
97
-			// Assign the value (mostly) from config/local.config.php file to the cache
98
-			$this->cache[$k] = $this->configCache->get('config', $k);
99
-			$this->in_db[$k] = false;
100
-
101
-			return $this->configCache->get('config', $k);
102
-		}
103
-
104
-		$this->cache[$cat][$k] = '!<unset>!';
105
-		$this->in_db[$cat][$k] = false;
106
-
107
-		return $default_value;
108
-	}
109
-
110
-	/**
111
-	 * {@inheritdoc}
112
-	 */
113
-	public function set($cat, $k, $value)
114
-	{
115
-		if (!$this->isConnected()) {
116
-			return false;
117
-		}
118
-
119
-		// We store our setting values in a string variable.
120
-		// So we have to do the conversion here so that the compare below works.
121
-		// The exception are array values.
122
-		$dbvalue = (!is_array($value) ? (string)$value : $value);
123
-
124
-		$stored = $this->get($cat, $k, null, true);
125
-
126
-		if (!isset($this->in_db[$cat])) {
127
-			$this->in_db[$cat] = [];
128
-		}
129
-		if (!isset($this->in_db[$cat][$k])) {
130
-			$this->in_db[$cat] = false;
131
-		}
132
-
133
-		if (($stored === $dbvalue) && $this->in_db[$cat][$k]) {
134
-			return true;
135
-		}
136
-
137
-		$this->configCache->set($cat, $k, $value);
138
-
139
-		// Assign the just added value to the cache
140
-		$this->cache[$cat][$k] = $dbvalue;
141
-
142
-		// manage array value
143
-		$dbvalue = (is_array($value) ? serialize($value) : $dbvalue);
144
-
145
-		$result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $k], true);
146
-
147
-		if ($result) {
148
-			$this->in_db[$cat][$k] = true;
149
-		}
150
-
151
-		return $result;
152
-	}
153
-
154
-	/**
155
-	 * {@inheritdoc}
156
-	 */
157
-	public function delete($cat, $k)
158
-	{
159
-		if (!$this->isConnected()) {
160
-			return false;
161
-		}
162
-
163
-		if (isset($this->cache[$cat][$k])) {
164
-			unset($this->cache[$cat][$k]);
165
-			unset($this->in_db[$cat][$k]);
166
-		}
167
-
168
-		$result = DBA::delete('config', ['cat' => $cat, 'k' => $k]);
169
-
170
-		return $result;
171
-	}
172
-}

+ 0
- 136
src/Core/Config/JITPConfigAdapter.php View File

@@ -1,136 +0,0 @@
1
-<?php
2
-namespace Friendica\Core\Config;
3
-
4
-use Friendica\Database\DBA;
5
-
6
-/**
7
- * JustInTime User Configuration Adapter
8
- *
9
- * Default PConfig Adapter. Provides the best performance for pages loading few configuration variables.
10
- *
11
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
12
- */
13
-class JITPConfigAdapter implements IPConfigAdapter
14
-{
15
-	private $in_db;
16
-
17
-	/**
18
-	 * The config cache of this adapter
19
-	 * @var IPConfigCache
20
-	 */
21
-	private $configCache;
22
-
23
-	/**
24
-	 * @param IPConfigCache $configCache The config cache of this adapter
25
-	 */
26
-	public function __construct(IPConfigCache $configCache)
27
-	{
28
-		$this->configCache = $configCache;
29
-	}
30
-
31
-	/**
32
-	 * {@inheritdoc}
33
-	 */
34
-	public function load($uid, $cat)
35
-	{
36
-		$pconfigs = DBA::select('pconfig', ['v', 'k'], ['cat' => $cat, 'uid' => $uid]);
37
-		if (DBA::isResult($pconfigs)) {
38
-			while ($pconfig = DBA::fetch($pconfigs)) {
39
-				$k = $pconfig['k'];
40
-
41
-				$this->configCache->setP($uid, $cat, $k, $pconfig['v']);
42
-
43
-				$this->in_db[$uid][$cat][$k] = true;
44
-			}
45
-		} else if ($cat != 'config') {
46
-			// Negative caching
47
-			$this->configCache->setP($uid, $cat, null, "!<unset>!");
48
-		}
49
-		DBA::close($pconfigs);
50
-	}
51
-
52
-	/**
53
-	 * {@inheritdoc}
54
-	 */
55
-	public function get($uid, $cat, $k, $default_value = null, $refresh = false)
56
-	{
57
-		if (!$refresh) {
58
-			// Looking if the whole family isn't set
59
-			if ($this->configCache->getP($uid, $cat) !== null) {
60
-				if ($this->configCache->getP($uid, $cat) === '!<unset>!') {
61
-					return $default_value;
62
-				}
63
-			}
64
-
65
-			if ($this->configCache->getP($uid, $cat, $k) !== null) {
66
-				if ($this->configCache->getP($uid, $cat, $k) === '!<unset>!') {
67
-					return $default_value;
68
-				}
69
-				return $this->configCache->getP($uid, $cat, $k);
70
-			}
71
-		}
72
-
73
-		$pconfig = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $k]);
74
-		if (DBA::isResult($pconfig)) {
75
-			$val = (preg_match("|^a:[0-9]+:{.*}$|s", $pconfig['v']) ? unserialize($pconfig['v']) : $pconfig['v']);
76
-
77
-			$this->configCache->setP($uid, $cat, $k, $val);
78
-
79
-			$this->in_db[$uid][$cat][$k] = true;
80
-
81
-			return $val;
82
-		} else {
83
-			$this->configCache->setP($uid, $cat, $k, '!<unset>!');
84
-
85
-			$this->in_db[$uid][$cat][$k] = false;
86
-
87
-			return $default_value;
88
-		}
89
-	}
90
-
91
-	/**
92
-	 * {@inheritdoc}
93
-	 */
94
-	public function set($uid, $cat, $k, $value)
95
-	{
96
-		// We store our setting values in a string variable.
97
-		// So we have to do the conversion here so that the compare below works.
98
-		// The exception are array values.
99
-		$dbvalue = (!is_array($value) ? (string)$value : $value);
100
-
101
-		$stored = $this->get($uid, $cat, $k, null, true);
102
-
103
-		if (($stored === $dbvalue) && $this->in_db[$uid][$cat][$k]) {
104
-			return true;
105
-		}
106
-
107
-		$this->configCache->setP($uid, $cat, $k, $value);
108
-
109
-		// manage array value
110
-		$dbvalue = (is_array($value) ? serialize($value) : $dbvalue);
111
-
112
-		$result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $k], true);
113
-
114
-		if ($result) {
115
-			$this->in_db[$uid][$cat][$k] = true;
116
-		}
117
-
118
-		return $result;
119
-	}
120
-
121
-	/**
122
-	 * {@inheritdoc}
123
-	 */
124
-	public function delete($uid, $cat, $k)
125
-	{
126
-		$this->configCache->deleteP($uid, $cat, $k);
127
-
128
-		if (!empty($this->in_db[$uid][$cat][$k])) {
129
-			unset($this->in_db[$uid][$cat][$k]);
130
-		}
131
-
132
-		$result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $k]);
133
-
134
-		return $result;
135
-	}
136
-}

+ 150
- 0
src/Core/Config/PConfiguration.php View File

@@ -0,0 +1,150 @@
1
+<?php
2
+
3
+namespace Friendica\Core\Config;
4
+
5
+/**
6
+ * This class is responsible for the user-specific configuration values in Friendica
7
+ * The values are set through the Config-DB-Table (per Config-DB-adapter @see Adapter\IPConfigAdapter )
8
+ *
9
+ * The configuration cache (@see Cache\IPConfigCache ) is used for temporary caching of database calls. This will
10
+ * increase the performance.
11
+ */
12
+class PConfiguration
13
+{
14
+	/**
15
+	 * @var Cache\IPConfigCache
16
+	 */
17
+	private $configCache;
18
+
19
+	/**
20
+	 * @var Adapter\IPConfigAdapter
21
+	 */
22
+	private $configAdapter;
23
+
24
+	/**
25
+	 * @param Cache\IPConfigCache     $configCache   The configuration cache
26
+	 * @param Adapter\IPConfigAdapter $configAdapter The configuration DB-backend
27
+	 */
28
+	public function __construct(Cache\IPConfigCache $configCache, Adapter\IPConfigAdapter $configAdapter)
29
+	{
30
+		$this->configCache = $configCache;
31
+		$this->configAdapter = $configAdapter;
32
+	}
33
+
34
+	/**
35
+	 * @brief Loads all configuration values of a user's config family into a cached storage.
36
+	 *
37
+	 * All configuration values of the given user are stored with the $uid in
38
+	 * the cache ( @see IPConfigCache )
39
+	 *
40
+	 * @param string $uid The user_id
41
+	 * @param string $cat The category of the configuration value
42
+	 *
43
+	 * @return void
44
+	 */
45
+	public function load($uid, $cat = 'config')
46
+	{
47
+		// If not connected, do nothing
48
+		if (!$this->configAdapter->isConnected()) {
49
+			return;
50
+		}
51
+
52
+		// load the whole category out of the DB into the cache
53
+		$this->configCache->loadP($uid, $this->configAdapter->load($uid, $cat));
54
+	}
55
+
56
+	/**
57
+	 * @brief Get a particular user's config variable given the category name
58
+	 * ($cat) and a key.
59
+	 *
60
+	 * Get a particular user's config value from the given category ($cat)
61
+	 * and the $key with the $uid from a cached storage either from the $this->configAdapter
62
+	 * (@see IConfigAdapter ) or from the $this->configCache (@see IConfigCache ).
63
+	 *
64
+	 * @param string  $uid           The user_id
65
+	 * @param string  $cat           The category of the configuration value
66
+	 * @param string  $key           The configuration key to query
67
+	 * @param mixed   $default_value optional, The value to return if key is not set (default: null)
68
+	 * @param boolean $refresh       optional, If true the config is loaded from the db and not from the cache (default: false)
69
+	 *
70
+	 * @return mixed Stored value or null if it does not exist
71
+	 */
72
+	public function get($uid, $cat, $key, $default_value = null, $refresh = false)
73
+	{
74
+		// Return the value of the cache if found and no refresh is forced
75
+		if (!$refresh && $this->configCache->hasP($uid, $cat, $key)) {
76
+			return $this->configCache->getP($uid, $cat, $key);
77
+		}
78
+
79
+		// if we don't find the value in the cache and the adapter isn't ready, return the default value
80
+		if (!$this->configAdapter->isConnected()) {
81
+			return $default_value;
82
+		}
83
+
84
+		// load DB value to cache
85
+		$dbvalue = $this->configAdapter->get($uid, $cat, $key);
86
+
87
+		if ($dbvalue !== '!<unset>!') {
88
+			$this->configCache->setP($uid, $cat, $key, $dbvalue);
89
+			return $dbvalue;
90
+		} else {
91
+			return $default_value;
92
+		}
93
+	}
94
+
95
+	/**
96
+	 * @brief Sets a configuration value for a user
97
+	 *
98
+	 * Stores a config value ($value) in the category ($family) under the key ($key)
99
+	 * for the user_id $uid.
100
+	 *
101
+	 * @note  Please do not store booleans - convert to 0/1 integer values!
102
+	 *
103
+	 * @param string $uid    The user_id
104
+	 * @param string $cat    The category of the configuration value
105
+	 * @param string $key    The configuration key to set
106
+	 * @param mixed  $value  The value to store
107
+	 *
108
+	 * @return bool Operation success
109
+	 */
110
+	public function set($uid, $cat, $key, $value)
111
+	{
112
+		// set the cache first
113
+		$cached = $this->configCache->setP($uid, $cat, $key, $value);
114
+
115
+		// If there is no connected adapter, we're finished
116
+		if (!$this->configAdapter->isConnected()) {
117
+			return $cached;
118
+		}
119
+
120
+		$stored = $this->configAdapter->set($uid, $cat, $key, $value);
121
+
122
+		return $cached && $stored;
123
+	}
124
+
125
+	/**
126
+	 * @brief Deletes the given key from the users's configuration.
127
+	 *
128
+	 * Removes the configured value from the stored cache in $this->configCache
129
+	 * (@see ConfigCache ) and removes it from the database (@see IConfigAdapter )
130
+	 * with the given $uid.
131
+	 *
132
+	 * @param string $uid The user_id
133
+	 * @param string $cat The category of the configuration value
134
+	 * @param string $key The configuration key to delete
135
+	 *
136
+	 * @return bool
137
+	 */
138
+	public function delete($uid, $cat, $key)
139
+	{
140
+		$cacheRemoved = $this->configCache->deleteP($uid, $cat, $key);
141
+
142
+		if (!$this->configAdapter->isConnected()) {
143
+			return $cacheRemoved;
144
+		}
145
+
146
+		$storeRemoved = $this->configAdapter->delete($uid, $cat, $key);
147
+
148
+		return $cacheRemoved || $storeRemoved;
149
+	}
150
+}

+ 0
- 123
src/Core/Config/PreloadConfigAdapter.php View File

@@ -1,123 +0,0 @@
1
-<?php
2
-
3
-namespace Friendica\Core\Config;
4
-
5
-use Exception;
6
-use Friendica\Database\DBA;
7
-
8
-/**
9
- * Preload Configuration Adapter
10
- *
11
- * Minimizes the number of database queries to retrieve configuration values at the cost of memory.
12
- *
13
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
14
- */
15
-class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter
16
-{
17
-	private $config_loaded = false;
18
-
19
-	/**
20
-	 * @var IConfigCache The config cache of this driver
21
-	 */
22
-	private $configCache;
23
-
24
-	/**
25
-	 * @param IConfigCache $configCache The config cache of this driver
26
-	 */
27
-	public function __construct(IConfigCache $configCache)
28
-	{
29
-		$this->configCache = $configCache;
30
-		$this->connected = DBA::connected();
31
-		$this->load();
32
-	}
33
-
34
-	/**
35
-	 * {@inheritdoc}
36
-	 */
37
-	public function load($family = 'config')
38
-	{
39
-		if (!$this->isConnected()) {
40
-			return;
41
-		}
42
-
43
-		if ($this->config_loaded) {
44
-			return;
45
-		}
46
-
47
-		$configs = DBA::select('config', ['cat', 'v', 'k']);
48
-		while ($config = DBA::fetch($configs)) {
49
-			$this->configCache->set($config['cat'], $config['k'], $config['v']);
50
-		}
51
-		DBA::close($configs);
52
-
53
-		$this->config_loaded = true;
54
-	}
55
-
56
-	/**
57
-	 * {@inheritdoc}
58
-	 */
59
-	public function get($cat, $k, $default_value = null, $refresh = false)
60
-	{
61
-		if (!$this->isConnected()) {
62
-			return $default_value;
63
-		}
64
-
65
-		if ($refresh) {
66
-			$config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $k]);
67
-			if (DBA::isResult($config)) {
68
-				$this->configCache->set($cat, $k, $config['v']);
69
-			}
70
-		}
71
-
72
-		$return = $this->configCache->get($cat, $k, $default_value);
73
-
74
-		return $return;
75
-	}
76
-
77
-	/**
78
-	 * {@inheritdoc}
79
-	 */
80
-	public function set($cat, $k, $value)
81
-	{
82
-		if (!$this->isConnected()) {
83
-			return false;
84
-		}
85
-
86
-		// We store our setting values as strings.
87
-		// So we have to do the conversion here so that the compare below works.
88
-		// The exception are array values.
89
-		$compare_value = !is_array($value) ? (string)$value : $value;
90
-
91
-		if ($this->configCache->get($cat, $k) === $compare_value) {
92
-			return true;
93
-		}
94
-
95
-		$this->configCache->set($cat, $k, $value);
96
-
97
-		// manage array value
98
-		$dbvalue = is_array($value) ? serialize($value) : $value;
99
-
100
-		$result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $k], true);
101
-		if (!$result) {
102
-			throw new Exception('Unable to store config value in [' . $cat . '][' . $k . ']');
103
-		}
104
-
105
-		return true;
106
-	}
107
-
108
-	/**
109
-	 * {@inheritdoc}
110
-	 */
111
-	public function delete($cat, $k)
112
-	{
113
-		if (!$this->isConnected()) {
114
-			return false;
115
-		}
116
-
117
-		$this->configCache->delete($cat, $k);
118
-
119
-		$result = DBA::delete('config', ['cat' => $cat, 'k' => $k]);
120
-
121
-		return $result;
122
-	}
123
-}

+ 0
- 125
src/Core/Config/PreloadPConfigAdapter.php View File

@@ -1,125 +0,0 @@
1
-<?php
2
-
3
-namespace Friendica\Core\Config;
4
-
5
-use Exception;
6
-use Friendica\Database\DBA;
7
-
8
-/**
9
- * Preload User Configuration Adapter
10
- *
11
- * Minimizes the number of database queries to retrieve configuration values at the cost of memory.
12
- *
13
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
14
- */
15
-class PreloadPConfigAdapter implements IPConfigAdapter
16
-{
17
-	private $config_loaded = false;
18
-
19
-	/**
20
-	 * The config cache of this adapter
21
-	 * @var IPConfigCache
22
-	 */
23
-	private $configCache;
24
-
25
-	/**
26
-	 * @param IPConfigCache $configCache The config cache of this adapter
27
-	 * @param int           $uid    The UID of the current user
28
-	 */
29
-	public function __construct(IPConfigCache $configCache, $uid = null)
30
-	{
31
-		$this->configCache = $configCache;
32
-		if (isset($uid)) {
33
-			$this->load($uid, 'config');
34
-		}
35
-	}
36
-
37
-	/**
38
-	 * {@inheritdoc}
39
-	 */
40
-	public function load($uid, $family)
41
-	{
42
-		if ($this->config_loaded) {
43
-			return;
44
-		}
45
-
46
-		if (empty($uid)) {
47
-			return;
48
-		}
49
-
50
-		$pconfigs = DBA::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]);
51
-		while ($pconfig = DBA::fetch($pconfigs)) {
52
-			$this->configCache->setP($uid, $pconfig['cat'], $pconfig['k'], $pconfig['v']);
53
-		}
54
-		DBA::close($pconfigs);
55
-
56
-		$this->config_loaded = true;
57
-	}
58
-
59
-	/**
60
-	 * {@inheritdoc}
61
-	 */
62
-	public function get($uid, $cat, $k, $default_value = null, $refresh = false)
63
-	{
64
-		if (!$this->config_loaded) {
65
-			$this->load($uid, $cat);
66
-		}
67
-
68
-		if ($refresh) {
69
-			$config = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $k]);
70
-			if (DBA::isResult($config)) {
71
-				$this->configCache->setP($uid, $cat, $k, $config['v']);
72
-			} else {
73
-				$this->configCache->deleteP($uid, $cat, $k);
74
-			}
75
-		}
76
-
77
-		return $this->configCache->getP($uid, $cat, $k, $default_value);;
78
-	}
79
-
80
-	/**
81
-	 * {@inheritdoc}
82
-	 */
83
-	public function set($uid, $cat, $k, $value)
84
-	{
85
-		if (!$this->config_loaded) {
86
-			$this->load($uid, $cat);
87
-		}
88
-		// We store our setting values as strings.
89
-		// So we have to do the conversion here so that the compare below works.
90
-		// The exception are array values.
91
-		$compare_value = !is_array($value) ? (string)$value : $value;
92
-
93
-		if ($this->configCache->getP($uid, $cat, $k) === $compare_value) {
94
-			return true;
95
-		}
96
-
97
-		$this->configCache->setP($uid, $cat, $k, $value);
98
-
99
-		// manage array value
100
-		$dbvalue = is_array($value) ? serialize($value) : $value;
101
-
102
-		$result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $k], true);
103
-		if (!$result) {
104
-			throw new Exception('Unable to store config value in [' . $uid . '][' . $cat . '][' . $k . ']');
105
-		}
106
-
107
-		return true;
108
-	}
109
-
110
-	/**
111
-	 * {@inheritdoc}
112
-	 */
113
-	public function delete($uid, $cat, $k)
114
-	{
115
-		if (!$this->config_loaded) {
116
-			$this->load($uid, $cat);
117
-		}
118
-
119
-		$this->configCache->deleteP($uid, $cat, $k);
120
-
121
-		$result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $k]);
122
-
123
-		return $result;
124
-	}
125
-}

+ 5
- 5
src/Core/Console/AutomaticInstallation.php View File

@@ -100,10 +100,10 @@ HELP;
100 100
 				}
101 101
 			}
102 102
 
103
-			$db_host = $a->getConfig()->get('database', 'hostname');
104
-			$db_user = $a->getConfig()->get('database', 'username');
105
-			$db_pass = $a->getConfig()->get('database', 'password');
106
-			$db_data = $a->getConfig()->get('database', 'database');
103
+			$db_host = $a->getConfigCache()->get('database', 'hostname');
104
+			$db_user = $a->getConfigCache()->get('database', 'username');
105
+			$db_pass = $a->getConfigCache()->get('database', 'password');
106
+			$db_data = $a->getConfigCache()->get('database', 'database');
107 107
 		} else {
108 108
 			// Creating config file
109 109
 			$this->out("Creating config file...\n");
@@ -146,7 +146,7 @@ HELP;
146 146
 
147 147
 		$installer->resetChecks();
148 148
 
149
-		if (!$installer->checkDB($a->getConfig(), $a->getProfiler(), $db_host, $db_user, $db_pass, $db_data)) {
149
+		if (!$installer->checkDB($a->getConfigCache(), $a->getProfiler(), $db_host, $db_user, $db_pass, $db_data)) {
150 150
 			$errorMessage = $this->extractErrors($installer->getChecks());
151 151
 			throw new RuntimeException($errorMessage);
152 152
 		}

+ 3
- 3
src/Core/Console/Config.php View File

@@ -124,9 +124,9 @@ HELP;
124 124
 			$cat = $this->getArgument(0);
125 125
 			Core\Config::load($cat);
126 126
 
127
-			if ($a->getConfig()->get($cat) !== null) {
127
+			if ($a->getConfigCache()->get($cat) !== null) {
128 128
 				$this->out("[{$cat}]");
129
-				$catVal = $a->getConfig()->get($cat);
129
+				$catVal = $a->getConfigCache()->get($cat);
130 130
 				foreach ($catVal as $key => $value) {
131 131
 					if (is_array($value)) {
132 132
 						foreach ($value as $k => $v) {
@@ -148,7 +148,7 @@ HELP;
148 148
 				$this->out('Warning: The JIT (Just In Time) Config adapter doesn\'t support loading the entire configuration, showing file config only');
149 149
 			}
150 150
 
151
-			$config = $a->getConfig()->getAll();
151
+			$config = $a->getConfigCache()->getAll();
152 152
 			foreach ($config as $cat => $section) {
153 153
 				if (is_array($section)) {
154 154
 					foreach ($section as $key => $value) {

+ 1
- 1
src/Core/Console/Typo.php View File

@@ -43,7 +43,7 @@ HELP;
43 43
 			throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
44 44
 		}
45 45
 
46
-		$php_path = BaseObject::getApp()->getConfig()->get('config', 'php_path', 'php');
46
+		$php_path = BaseObject::getApp()->getConfigCache()->get('config', 'php_path', 'php');
47 47
 
48 48
 		if ($this->getOption('v')) {
49 49
 			$this->out('Directory: src');

+ 3
- 3
src/Core/Installer.php View File

@@ -6,7 +6,7 @@ namespace Friendica\Core;
6 6
 
7 7
 use DOMDocument;
8 8
 use Exception;
9
-use Friendica\Core\Config\ConfigCache;
9
+use Friendica\Core\Config\Cache\IConfigCache;
10 10
 use Friendica\Database\DBA;
11 11
 use Friendica\Database\DBStructure;
12 12
 use Friendica\Object\Image;
@@ -583,7 +583,7 @@ class Installer
583 583
 	/**
584 584
 	 * Checking the Database connection and if it is available for the current installation
585 585
 	 *
586
-	 * @param ConfigCache $configCache The configuration cache
586
+	 * @param IConfigCache $configCache The configuration cache
587 587
 	 * @param Profiler    $profiler    The profiler of this app
588 588
 	 * @param string $dbhost           Hostname/IP of the Friendica Database
589 589
 	 * @param string $dbuser           Username of the Database connection credentials
@@ -593,7 +593,7 @@ class Installer
593 593
 	 * @return bool true if the check was successful, otherwise false
594 594
 	 * @throws Exception
595 595
 	 */
596
-	public function checkDB(ConfigCache $configCache, Profiler $profiler, $dbhost, $dbuser, $dbpass, $dbdata)
596
+	public function checkDB(IConfigCache $configCache, Profiler $profiler, $dbhost, $dbuser, $dbpass, $dbdata)
597 597
 	{
598 598
 		if (!DBA::connect($configCache, $profiler, $dbhost, $dbuser, $dbpass, $dbdata)) {
599 599
 			$this->addCheck(L10n::t('Could not connect to database.'), false, true, '');

+ 22
- 67
src/Core/PConfig.php View File

@@ -18,123 +18,78 @@ namespace Friendica\Core;
18 18
 class PConfig
19 19
 {
20 20
 	/**
21
-	 * @var Config\IPConfigAdapter
21
+	 * @var Config\PConfiguration
22 22
 	 */
23
-	private static $adapter;
24
-
25
-	/**
26
-	 * @var Config\IPConfigCache
27
-	 */
28
-	private static $cache;
23
+	private static $config;
29 24
 
30 25
 	/**
31 26
 	 * Initialize the config with only the cache
32 27
 	 *
33
-	 * @param Config\IPConfigCache $cache  The configuration cache
34
-	 */
35
-	public static function init(Config\IPConfigCache $cache)
36
-	{
37
-		self::$cache  = $cache;
38
-	}
39
-
40
-	/**
41
-	 * Add the adapter for DB-backend
42
-	 *
43
-	 * @param Config\IPConfigAdapter $adapter
28
+	 * @param Config\PConfiguration $config The configuration cache
44 29
 	 */
45
-	public static function setAdapter(Config\IPConfigAdapter $adapter)
30
+	public static function init(Config\PConfiguration $config)
46 31
 	{
47
-		self::$adapter = $adapter;
32
+		self::$config = $config;
48 33
 	}
49 34
 
50 35
 	/**
51 36
 	 * @brief Loads all configuration values of a user's config family into a cached storage.
52 37
 	 *
53
-	 * All configuration values of the given user are stored with the $uid in
54
-	 * the cache ( @see IPConfigCache )
55
-	 *
56
-	 * @param string $uid    The user_id
57
-	 * @param string $family The category of the configuration value
38
+	 * @param string $uid The user_id
39
+	 * @param string $cat The category of the configuration value
58 40
 	 *
59 41
 	 * @return void