Config fixings
- Delete now really overwrites static default/setting.config.php keys - Delete now really overwrites static default/setting.config.php categories - The Update::check() routine is added to different places - Merge the given config file with the new config before writing - Remove ConfigTransaction::get() because it's no more reliable
This commit is contained in:
parent
cdd57275eb
commit
5aa8e8adf1
13 changed files with 221 additions and 181 deletions
|
@ -82,6 +82,10 @@ $dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['auth_ejabb
|
||||||
|
|
||||||
\Friendica\DI::init($dice);
|
\Friendica\DI::init($dice);
|
||||||
\Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
|
\Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
|
||||||
|
|
||||||
|
// Check the database structure and possibly fixes it
|
||||||
|
\Friendica\Core\Update::check(\Friendica\DI::basePath(), true, \Friendica\DI::mode());
|
||||||
|
|
||||||
$appMode = $dice->create(Mode::class);
|
$appMode = $dice->create(Mode::class);
|
||||||
|
|
||||||
if ($appMode->isNormal()) {
|
if ($appMode->isNormal()) {
|
||||||
|
|
|
@ -33,6 +33,7 @@ if (php_sapi_name() !== 'cli') {
|
||||||
use Dice\Dice;
|
use Dice\Dice;
|
||||||
use Friendica\App\Mode;
|
use Friendica\App\Mode;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
|
use Friendica\Core\Update;
|
||||||
use Friendica\Core\Worker;
|
use Friendica\Core\Worker;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
|
@ -63,7 +64,9 @@ $dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['daemon']])
|
||||||
|
|
||||||
DI::init($dice);
|
DI::init($dice);
|
||||||
\Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
|
\Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
|
||||||
$a = DI::app();
|
|
||||||
|
// Check the database structure and possibly fixes it
|
||||||
|
Update::check(DI::basePath(), true, DI::mode());
|
||||||
|
|
||||||
if (DI::mode()->isInstall()) {
|
if (DI::mode()->isInstall()) {
|
||||||
die("Friendica isn't properly installed yet.\n");
|
die("Friendica isn't properly installed yet.\n");
|
||||||
|
|
|
@ -58,12 +58,11 @@ $dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['worker']])
|
||||||
|
|
||||||
DI::init($dice);
|
DI::init($dice);
|
||||||
\Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
|
\Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
|
||||||
$a = DI::app();
|
|
||||||
|
|
||||||
DI::mode()->setExecutor(Mode::WORKER);
|
DI::mode()->setExecutor(Mode::WORKER);
|
||||||
|
|
||||||
// Check the database structure and possibly fixes it
|
// Check the database structure and possibly fixes it
|
||||||
Update::check($a->getBasePath(), true, DI::mode());
|
Update::check(DI::basePath(), true, DI::mode());
|
||||||
|
|
||||||
// Quit when in maintenance
|
// Quit when in maintenance
|
||||||
if (!DI::mode()->has(App\Mode::MAINTENANCEDISABLED)) {
|
if (!DI::mode()->has(App\Mode::MAINTENANCEDISABLED)) {
|
||||||
|
|
|
@ -36,6 +36,9 @@ $dice = $dice->addRule(Friendica\App\Mode::class, ['call' => [['determineRunMode
|
||||||
|
|
||||||
\Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
|
\Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));
|
||||||
|
|
||||||
|
// Check the database structure and possibly fixes it
|
||||||
|
\Friendica\Core\Update::check(\Friendica\DI::basePath(), true, \Friendica\DI::mode());
|
||||||
|
|
||||||
$a = \Friendica\DI::app();
|
$a = \Friendica\DI::app();
|
||||||
|
|
||||||
\Friendica\DI::mode()->setExecutor(\Friendica\App\Mode::INDEX);
|
\Friendica\DI::mode()->setExecutor(\Friendica\App\Mode::INDEX);
|
||||||
|
|
|
@ -116,7 +116,7 @@ class Config implements IManageConfigValues
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public function delete(string $cat, string $key): bool
|
public function delete(string $cat, string $key): bool
|
||||||
{
|
{
|
||||||
if ($this->configCache->delete($cat, $key)) {
|
if ($this->configCache->delete($cat, $key, Cache::SOURCE_DATA)) {
|
||||||
$this->save();
|
$this->save();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -35,37 +35,13 @@ class ConfigTransaction implements ISetConfigValuesTransactionally
|
||||||
protected $config;
|
protected $config;
|
||||||
/** @var Cache */
|
/** @var Cache */
|
||||||
protected $cache;
|
protected $cache;
|
||||||
/** @var Cache */
|
|
||||||
protected $delCache;
|
|
||||||
/** @var bool field to check if something is to save */
|
/** @var bool field to check if something is to save */
|
||||||
protected $changedConfig = false;
|
protected $changedConfig = false;
|
||||||
|
|
||||||
public function __construct(IManageConfigValues $config)
|
public function __construct(IManageConfigValues $config)
|
||||||
{
|
{
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
$this->cache = new Cache();
|
$this->cache = clone $config->getCache();
|
||||||
$this->delCache = new Cache();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a particular user's config variable given the category name
|
|
||||||
* ($cat) and a $key from the current transaction.
|
|
||||||
*
|
|
||||||
* Isn't part of the interface because of it's rare use case
|
|
||||||
*
|
|
||||||
* @param string $cat The category of the configuration value
|
|
||||||
* @param string $key The configuration key to query
|
|
||||||
*
|
|
||||||
* @return mixed Stored value or null if it does not exist
|
|
||||||
*
|
|
||||||
* @throws ConfigPersistenceException In case the persistence layer throws errors
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function get(string $cat, string $key)
|
|
||||||
{
|
|
||||||
return !$this->delCache->get($cat, $key) ?
|
|
||||||
($this->cache->get($cat, $key) ?? $this->config->get($cat, $key)) :
|
|
||||||
null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
|
@ -81,8 +57,7 @@ class ConfigTransaction implements ISetConfigValuesTransactionally
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public function delete(string $cat, string $key): ISetConfigValuesTransactionally
|
public function delete(string $cat, string $key): ISetConfigValuesTransactionally
|
||||||
{
|
{
|
||||||
$this->cache->delete($cat, $key);
|
$this->cache->delete($cat, $key, Cache::SOURCE_DATA);
|
||||||
$this->delCache->set($cat, $key, 'deleted');
|
|
||||||
$this->changedConfig = true;
|
$this->changedConfig = true;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -97,13 +72,8 @@ class ConfigTransaction implements ISetConfigValuesTransactionally
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$newCache = $this->config->getCache()->merge($this->cache);
|
$this->config->load($this->cache);
|
||||||
$newCache = $newCache->diff($this->delCache);
|
$this->cache = clone $this->config->getCache();
|
||||||
$this->config->load($newCache);
|
|
||||||
|
|
||||||
// flush current cache
|
|
||||||
$this->cache = new Cache();
|
|
||||||
$this->delCache = new Cache();
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
throw new ConfigPersistenceException('Cannot save config', $e);
|
throw new ConfigPersistenceException('Cannot save config', $e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,33 +93,33 @@ class ConfigFileManager
|
||||||
* First loads the default value for all the configuration keys, then the legacy configuration files, then the
|
* First loads the default value for all the configuration keys, then the legacy configuration files, then the
|
||||||
* expected local.config.php
|
* expected local.config.php
|
||||||
*
|
*
|
||||||
* @param Cache $config The config cache to load to
|
* @param Cache $configCache The config cache to load to
|
||||||
* @param bool $raw Set up the raw config format
|
* @param bool $raw Set up the raw config format
|
||||||
*
|
*
|
||||||
* @throws ConfigFileException
|
* @throws ConfigFileException
|
||||||
*/
|
*/
|
||||||
public function setupCache(Cache $config, bool $raw = false)
|
public function setupCache(Cache $configCache, bool $raw = false)
|
||||||
{
|
{
|
||||||
// Load static config files first, the order is important
|
// Load static config files first, the order is important
|
||||||
$config->load($this->loadStaticConfig('defaults'), Cache::SOURCE_STATIC);
|
$configCache->load($this->loadStaticConfig('defaults'), Cache::SOURCE_STATIC);
|
||||||
$config->load($this->loadStaticConfig('settings'), Cache::SOURCE_STATIC);
|
$configCache->load($this->loadStaticConfig('settings'), Cache::SOURCE_STATIC);
|
||||||
|
|
||||||
// try to load the legacy config first
|
// try to load the legacy config first
|
||||||
$config->load($this->loadLegacyConfig('htpreconfig'), Cache::SOURCE_FILE);
|
$configCache->load($this->loadLegacyConfig('htpreconfig'), Cache::SOURCE_FILE);
|
||||||
$config->load($this->loadLegacyConfig('htconfig'), Cache::SOURCE_FILE);
|
$configCache->load($this->loadLegacyConfig('htconfig'), Cache::SOURCE_FILE);
|
||||||
|
|
||||||
// Now load every other config you find inside the 'config/' directory
|
// Now load every other config you find inside the 'config/' directory
|
||||||
$this->loadCoreConfig($config);
|
$this->loadCoreConfig($configCache);
|
||||||
|
|
||||||
// Now load the node.config.php file with the node specific config values (based on admin gui/console actions)
|
// Now load the node.config.php file with the node specific config values (based on admin gui/console actions)
|
||||||
$this->loadDataConfig($config);
|
$this->loadDataConfig($configCache);
|
||||||
|
|
||||||
$config->load($this->loadEnvConfig(), Cache::SOURCE_ENV);
|
$configCache->load($this->loadEnvConfig(), Cache::SOURCE_ENV);
|
||||||
|
|
||||||
// In case of install mode, add the found basepath (because there isn't a basepath set yet
|
// In case of install mode, add the found basepath (because there isn't a basepath set yet
|
||||||
if (!$raw && empty($config->get('system', 'basepath'))) {
|
if (!$raw && empty($configCache->get('system', 'basepath'))) {
|
||||||
// Setting at least the basepath we know
|
// Setting at least the basepath we know
|
||||||
$config->set('system', 'basepath', $this->baseDir, Cache::SOURCE_FILE);
|
$configCache->set('system', 'basepath', $this->baseDir, Cache::SOURCE_FILE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ class ConfigFileManager
|
||||||
|
|
||||||
if (file_exists($configName)) {
|
if (file_exists($configName)) {
|
||||||
return $this->loadConfigFile($configName);
|
return $this->loadConfigFile($configName);
|
||||||
} elseif (file_exists($iniName)) {
|
} else if (file_exists($iniName)) {
|
||||||
return $this->loadINIConfigFile($iniName);
|
return $this->loadINIConfigFile($iniName);
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
|
@ -149,31 +149,31 @@ class ConfigFileManager
|
||||||
/**
|
/**
|
||||||
* Tries to load the specified core-configuration into the config cache.
|
* Tries to load the specified core-configuration into the config cache.
|
||||||
*
|
*
|
||||||
* @param Cache $config The Config cache
|
* @param Cache $configCache The Config cache
|
||||||
*
|
*
|
||||||
* @throws ConfigFileException if the configuration file isn't readable
|
* @throws ConfigFileException if the configuration file isn't readable
|
||||||
*/
|
*/
|
||||||
private function loadCoreConfig(Cache $config)
|
private function loadCoreConfig(Cache $configCache)
|
||||||
{
|
{
|
||||||
// try to load legacy ini-files first
|
// try to load legacy ini-files first
|
||||||
foreach ($this->getConfigFiles(true) as $configFile) {
|
foreach ($this->getConfigFiles(true) as $configFile) {
|
||||||
$config->load($this->loadINIConfigFile($configFile), Cache::SOURCE_FILE);
|
$configCache->load($this->loadINIConfigFile($configFile), Cache::SOURCE_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to load supported config at last to overwrite it
|
// try to load supported config at last to overwrite it
|
||||||
foreach ($this->getConfigFiles() as $configFile) {
|
foreach ($this->getConfigFiles() as $configFile) {
|
||||||
$config->load($this->loadConfigFile($configFile), Cache::SOURCE_FILE);
|
$configCache->load($this->loadConfigFile($configFile), Cache::SOURCE_FILE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to load the data config file with the overridden data
|
* Tries to load the data config file with the overridden data
|
||||||
*
|
*
|
||||||
* @param Cache $config The Config cache
|
* @param Cache $configCache The Config cache
|
||||||
*
|
*
|
||||||
* @throws ConfigFileException In case the config file isn't loadable
|
* @throws ConfigFileException In case the config file isn't loadable
|
||||||
*/
|
*/
|
||||||
private function loadDataConfig(Cache $config)
|
private function loadDataConfig(Cache $configCache)
|
||||||
{
|
{
|
||||||
$filename = $this->configDir . '/' . self::CONFIG_DATA_FILE;
|
$filename = $this->configDir . '/' . self::CONFIG_DATA_FILE;
|
||||||
|
|
||||||
|
@ -194,37 +194,69 @@ class ConfigFileManager
|
||||||
|
|
||||||
$dataArray = eval('?>' . $content);
|
$dataArray = eval('?>' . $content);
|
||||||
|
|
||||||
if (!is_array($dataArray)) {
|
if (is_array($dataArray)) {
|
||||||
throw new ConfigFileException(sprintf('Error loading config file %s', $filename));
|
$configCache->load($dataArray, Cache::SOURCE_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
$config->load($dataArray, Cache::SOURCE_DATA);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves overridden config entries back into the data.config.phpR
|
* Saves overridden config entries back into the data.config.phpR
|
||||||
*
|
*
|
||||||
* @param Cache $config The config cache
|
* @param Cache $configCache The config cache
|
||||||
*
|
*
|
||||||
* @throws ConfigFileException In case the config file isn't writeable or the data is invalid
|
* @throws ConfigFileException In case the config file isn't writeable or the data is invalid
|
||||||
*/
|
*/
|
||||||
public function saveData(Cache $config)
|
public function saveData(Cache $configCache)
|
||||||
{
|
{
|
||||||
$data = $config->getDataBySource(Cache::SOURCE_DATA);
|
$filename = $this->configDir . '/' . self::CONFIG_DATA_FILE;
|
||||||
|
|
||||||
$encodedData = ConfigFileTransformer::encode($data);
|
if (file_exists($filename)) {
|
||||||
|
$fileExists = true;
|
||||||
if (!$encodedData) {
|
} else {
|
||||||
throw new ConfigFileException('config source cannot get encoded');
|
$fileExists = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$configStream = fopen($this->configDir . '/' . self::CONFIG_DATA_FILE, 'w');
|
$configStream = fopen($filename, 'c+');
|
||||||
|
|
||||||
if (flock($configStream, LOCK_EX)) {
|
try {
|
||||||
fwrite($configStream, $encodedData);
|
if (flock($configStream, LOCK_EX)) {
|
||||||
fflush($configStream);
|
|
||||||
flock($configStream, LOCK_UN);
|
if ($fileExists) {
|
||||||
|
clearstatcache(true, $filename);
|
||||||
|
$content = fread($configStream, filesize($filename));
|
||||||
|
rewind($configStream);
|
||||||
|
if (!$content) {
|
||||||
|
throw new ConfigFileException(sprintf('Couldn\'t read file %s', $filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
$dataArray = eval('?>' . $content);
|
||||||
|
|
||||||
|
if (is_array($dataArray)) {
|
||||||
|
$fileConfigCache = new Cache();
|
||||||
|
$fileConfigCache->load($dataArray, Cache::SOURCE_DATA);
|
||||||
|
$configCache = $fileConfigCache->merge($configCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $configCache->getDataBySource(Cache::SOURCE_DATA);
|
||||||
|
|
||||||
|
$encodedData = ConfigFileTransformer::encode($data);
|
||||||
|
|
||||||
|
if (!$encodedData) {
|
||||||
|
throw new ConfigFileException('config source cannot get encoded');
|
||||||
|
}
|
||||||
|
|
||||||
|
clearstatcache(true, $filename);
|
||||||
|
if (!ftruncate($configStream, 0) ||
|
||||||
|
!fwrite($configStream, $encodedData) ||
|
||||||
|
!fflush($configStream) ||
|
||||||
|
!flock($configStream, LOCK_UN)) {
|
||||||
|
throw new ConfigFileException(sprintf('Cannot modify locked file %s', $filename));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
fclose($configStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +274,7 @@ class ConfigFileManager
|
||||||
$filepath = $this->baseDir . DIRECTORY_SEPARATOR . // /var/www/html/
|
$filepath = $this->baseDir . DIRECTORY_SEPARATOR . // /var/www/html/
|
||||||
Addon::DIRECTORY . DIRECTORY_SEPARATOR . // addon/
|
Addon::DIRECTORY . DIRECTORY_SEPARATOR . // addon/
|
||||||
$name . DIRECTORY_SEPARATOR . // openstreetmap/
|
$name . DIRECTORY_SEPARATOR . // openstreetmap/
|
||||||
'config'. DIRECTORY_SEPARATOR . // config/
|
'config' . DIRECTORY_SEPARATOR . // config/
|
||||||
$name . ".config.php"; // openstreetmap.config.php
|
$name . ".config.php"; // openstreetmap.config.php
|
||||||
|
|
||||||
if (file_exists($filepath)) {
|
if (file_exists($filepath)) {
|
||||||
|
|
|
@ -34,6 +34,12 @@ class ConfigFileTransformer
|
||||||
$categories = array_keys($data);
|
$categories = array_keys($data);
|
||||||
|
|
||||||
foreach ($categories as $category) {
|
foreach ($categories as $category) {
|
||||||
|
|
||||||
|
if (is_null($data[$category])) {
|
||||||
|
$dataString .= "\t'$category' => null," . PHP_EOL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$dataString .= "\t'$category' => [" . PHP_EOL;
|
$dataString .= "\t'$category' => [" . PHP_EOL;
|
||||||
|
|
||||||
if (is_array($data[$category])) {
|
if (is_array($data[$category])) {
|
||||||
|
@ -66,7 +72,9 @@ class ConfigFileTransformer
|
||||||
{
|
{
|
||||||
$string = str_repeat("\t", $level + 2) . "'$key' => ";
|
$string = str_repeat("\t", $level + 2) . "'$key' => ";
|
||||||
|
|
||||||
if (is_array($value)) {
|
if (is_null($value)) {
|
||||||
|
$string .= "null,";
|
||||||
|
} elseif (is_array($value)) {
|
||||||
$string .= "[" . PHP_EOL;
|
$string .= "[" . PHP_EOL;
|
||||||
$string .= static::extractArray($value, ++$level);
|
$string .= static::extractArray($value, ++$level);
|
||||||
$string .= str_repeat("\t", $level + 1) . '],';
|
$string .= str_repeat("\t", $level + 1) . '],';
|
||||||
|
|
|
@ -65,7 +65,7 @@ class Cache
|
||||||
* @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
|
||||||
* @param int $source Sets a source of the initial config values
|
* @param int $source Sets a source of the initial config values
|
||||||
*/
|
*/
|
||||||
public function __construct(array $config = [], bool $hidePasswordOutput = true, $source = self::SOURCE_DEFAULT)
|
public function __construct(array $config = [], bool $hidePasswordOutput = true, int $source = self::SOURCE_DEFAULT)
|
||||||
{
|
{
|
||||||
$this->hidePasswordOutput = $hidePasswordOutput;
|
$this->hidePasswordOutput = $hidePasswordOutput;
|
||||||
$this->load($config, $source);
|
$this->load($config, $source);
|
||||||
|
@ -87,11 +87,10 @@ class Cache
|
||||||
$keys = array_keys($config[$category]);
|
$keys = array_keys($config[$category]);
|
||||||
|
|
||||||
foreach ($keys as $key) {
|
foreach ($keys as $key) {
|
||||||
$value = $config[$category][$key];
|
$this->set($category, $key, $config[$category][$key] ?? null, $source);
|
||||||
if (isset($value)) {
|
|
||||||
$this->set($category, $key, $value, $source);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$this->set($category, null, $config[$category], $source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,6 +149,8 @@ class Cache
|
||||||
$data[$category][$key] = $this->config[$category][$key];
|
$data[$category][$key] = $this->config[$category][$key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} elseif (is_int($this->source[$category])) {
|
||||||
|
$data[$category] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,40 +160,49 @@ class Cache
|
||||||
/**
|
/**
|
||||||
* Sets a value in the config cache. Accepts raw output from the config table
|
* Sets a value in the config cache. Accepts raw output from the config table
|
||||||
*
|
*
|
||||||
* @param string $cat Config category
|
* @param string $cat Config category
|
||||||
* @param string $key Config key
|
* @param ?string $key Config key
|
||||||
* @param mixed $value Value to set
|
* @param ?mixed $value Value to set
|
||||||
* @param int $source The source of the current config key
|
* @param int $source The source of the current config key
|
||||||
*
|
*
|
||||||
* @return bool True, if the value is set
|
* @return bool True, if the value is set
|
||||||
*/
|
*/
|
||||||
public function set(string $cat, string $key, $value, int $source = self::SOURCE_DEFAULT): bool
|
public function set(string $cat, string $key = null, $value = null, int $source = self::SOURCE_DEFAULT): bool
|
||||||
{
|
{
|
||||||
if (!isset($this->config[$cat])) {
|
if (!isset($this->config[$cat]) && $key !== null) {
|
||||||
$this->config[$cat] = [];
|
$this->config[$cat] = [];
|
||||||
$this->source[$cat] = [];
|
$this->source[$cat] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->source[$cat][$key]) &&
|
if ((isset($this->source[$cat][$key]) && $source < $this->source[$cat][$key]) ||
|
||||||
$source < $this->source[$cat][$key]) {
|
(is_int($this->source[$cat] ?? null) && $source < $this->source[$cat])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->hidePasswordOutput &&
|
if ($this->hidePasswordOutput &&
|
||||||
$key == 'password' &&
|
$key == 'password' &&
|
||||||
is_string($value)) {
|
is_string($value)) {
|
||||||
$this->config[$cat][$key] = new HiddenString((string)$value);
|
$this->setCatKeyValueSource($cat, $key, new HiddenString((string)$value), $source);
|
||||||
} else if (is_string($value)) {
|
} else if (is_string($value)) {
|
||||||
$this->config[$cat][$key] = self::toConfigValue($value);
|
$this->setCatKeyValueSource($cat, $key, self::toConfigValue($value), $source);
|
||||||
} else {
|
} else {
|
||||||
$this->config[$cat][$key] = $value;
|
$this->setCatKeyValueSource($cat, $key, $value, $source);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->source[$cat][$key] = $source;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function setCatKeyValueSource(string $cat, string $key = null, $value = null, int $source = self::SOURCE_DEFAULT)
|
||||||
|
{
|
||||||
|
if (isset($key)) {
|
||||||
|
$this->config[$cat][$key] = $value;
|
||||||
|
$this->source[$cat][$key] = $source;
|
||||||
|
} else {
|
||||||
|
$this->config[$cat] = $value;
|
||||||
|
$this->source[$cat] = $source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a DB value to a config value
|
* Formats a DB value to a config value
|
||||||
* - null = The db-value isn't set
|
* - null = The db-value isn't set
|
||||||
|
@ -222,24 +232,27 @@ class Cache
|
||||||
/**
|
/**
|
||||||
* Deletes a value from the config cache.
|
* Deletes a value from the config cache.
|
||||||
*
|
*
|
||||||
* @param string $cat Config category
|
* @param string $cat Config category
|
||||||
* @param string $key Config key
|
* @param ?string $key Config key (if not set, the whole category will get deleted)
|
||||||
|
* @param int $source The source of the current config key
|
||||||
*
|
*
|
||||||
* @return bool true, if deleted
|
* @return bool true, if deleted
|
||||||
*/
|
*/
|
||||||
public function delete(string $cat, string $key): bool
|
public function delete(string $cat, string $key = null, int $source = self::SOURCE_DEFAULT): bool
|
||||||
{
|
{
|
||||||
if (isset($this->config[$cat][$key])) {
|
if (isset($this->config[$cat][$key])) {
|
||||||
unset($this->config[$cat][$key]);
|
$this->config[$cat][$key] = null;
|
||||||
unset($this->source[$cat][$key]);
|
$this->source[$cat][$key] = $source;
|
||||||
if (count($this->config[$cat]) == 0) {
|
if (empty(array_filter($this->config[$cat], function($value) { return !is_null($value); }))) {
|
||||||
unset($this->config[$cat]);
|
$this->config[$cat] = null;
|
||||||
unset($this->source[$cat]);
|
$this->source[$cat] = $source;
|
||||||
}
|
}
|
||||||
return true;
|
} elseif (isset($this->config[$cat])) {
|
||||||
} else {
|
$this->config[$cat] = null;
|
||||||
return false;
|
$this->source[$cat] = $source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -302,39 +315,9 @@ class Cache
|
||||||
$newConfig[$category][$key] = $cache->config[$category][$key];
|
$newConfig[$category][$key] = $cache->config[$category][$key];
|
||||||
$newSource[$category][$key] = $cache->source[$category][$key];
|
$newSource[$category][$key] = $cache->source[$category][$key];
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
}
|
$newConfig[$category] = $cache->config[$category];
|
||||||
|
$newSource[$category] = $cache->source[$category];
|
||||||
$newCache = new Cache();
|
|
||||||
$newCache->config = $newConfig;
|
|
||||||
$newCache->source = $newSource;
|
|
||||||
|
|
||||||
return $newCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Diffs a new Cache into the existing one and returns the diffed Cache
|
|
||||||
*
|
|
||||||
* @param Cache $cache The cache, which should get deleted for the current Cache
|
|
||||||
*
|
|
||||||
* @return Cache The diffed Cache
|
|
||||||
*/
|
|
||||||
public function diff(Cache $cache): Cache
|
|
||||||
{
|
|
||||||
$newConfig = $this->config;
|
|
||||||
$newSource = $this->source;
|
|
||||||
|
|
||||||
$categories = array_keys($cache->config);
|
|
||||||
|
|
||||||
foreach ($categories as $category) {
|
|
||||||
if (is_array($cache->config[$category])) {
|
|
||||||
$keys = array_keys($cache->config[$category]);
|
|
||||||
|
|
||||||
foreach ($keys as $key) {
|
|
||||||
unset($newConfig[$category][$key]);
|
|
||||||
unset($newSource[$category][$key]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,8 @@ class CacheTest extends MockedTest
|
||||||
$configCache = new Cache();
|
$configCache = new Cache();
|
||||||
$configCache->load($data);
|
$configCache->load($data);
|
||||||
|
|
||||||
|
print_r($configCache);
|
||||||
|
|
||||||
self::assertConfigValues($data, $configCache);
|
self::assertConfigValues($data, $configCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,9 +113,9 @@ class CacheTest extends MockedTest
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the loadConfigArray() method with wrong/empty datasets
|
* Test the loadConfigArray() method with only a category
|
||||||
*/
|
*/
|
||||||
public function testLoadConfigArrayWrong()
|
public function testLoadConfigArrayWithOnlyCategory()
|
||||||
{
|
{
|
||||||
$configCache = new Cache();
|
$configCache = new Cache();
|
||||||
|
|
||||||
|
@ -123,9 +125,10 @@ class CacheTest extends MockedTest
|
||||||
|
|
||||||
// wrong dataset
|
// wrong dataset
|
||||||
$configCache->load(['system' => 'not_array']);
|
$configCache->load(['system' => 'not_array']);
|
||||||
self::assertEmpty($configCache->getAll());
|
self::assertEquals(['system' => 'not_array'], $configCache->getAll());
|
||||||
|
|
||||||
// incomplete dataset (key is integer ID of the array)
|
// incomplete dataset (key is integer ID of the array)
|
||||||
|
$configCache = new Cache();
|
||||||
$configCache->load(['system' => ['value']]);
|
$configCache->load(['system' => ['value']]);
|
||||||
self::assertEquals('value', $configCache->get('system', 0));
|
self::assertEquals('value', $configCache->get('system', 0));
|
||||||
}
|
}
|
||||||
|
@ -207,13 +210,16 @@ class CacheTest extends MockedTest
|
||||||
{
|
{
|
||||||
$configCache = new Cache($data);
|
$configCache = new Cache($data);
|
||||||
|
|
||||||
|
$assertion = [];
|
||||||
|
|
||||||
foreach ($data as $cat => $values) {
|
foreach ($data as $cat => $values) {
|
||||||
|
$assertion[$cat] = null;
|
||||||
foreach ($values as $key => $value) {
|
foreach ($values as $key => $value) {
|
||||||
$configCache->delete($cat, $key);
|
$configCache->delete($cat, $key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self::assertEmpty($configCache->getAll());
|
self::assertEquals($assertion, $configCache->getAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -385,32 +391,6 @@ class CacheTest extends MockedTest
|
||||||
self::assertEquals('added category', $mergedCache->get('new_category', 'test_23'));
|
self::assertEquals('added category', $mergedCache->get('new_category', 'test_23'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider dataTests
|
|
||||||
*/
|
|
||||||
public function testDiff($data)
|
|
||||||
{
|
|
||||||
$configCache = new Cache();
|
|
||||||
$configCache->load($data, Cache::SOURCE_FILE);
|
|
||||||
|
|
||||||
$configCache->set('system', 'test_2','with_data', Cache::SOURCE_DATA);
|
|
||||||
$configCache->set('config', 'test_override','with_another_data', Cache::SOURCE_DATA);
|
|
||||||
|
|
||||||
$newCache = new Cache();
|
|
||||||
$newCache->set('config', 'test_override','override it again', Cache::SOURCE_DATA);
|
|
||||||
$newCache->set('system', 'test_3','new value', Cache::SOURCE_DATA);
|
|
||||||
|
|
||||||
$mergedCache = $configCache->diff($newCache);
|
|
||||||
|
|
||||||
print_r($mergedCache);
|
|
||||||
|
|
||||||
self::assertEquals('with_data', $mergedCache->get('system', 'test_2'));
|
|
||||||
// existing entry was dropped
|
|
||||||
self::assertNull($mergedCache->get('config', 'test_override'));
|
|
||||||
// the newCache entry wasn't set, because we Diff
|
|
||||||
self::assertNull($mergedCache->get('system', 'test_3'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dataTestCat()
|
public function dataTestCat()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -441,4 +441,74 @@ class ConfigFileManagerTest extends MockedTest
|
||||||
'special' => $specialChars,
|
'special' => $specialChars,
|
||||||
]], $configCache2->getDataBySource(Cache::SOURCE_DATA));
|
]], $configCache2->getDataBySource(Cache::SOURCE_DATA));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we delete something with the Cache::delete() functionality, be sure to override the underlying source as well
|
||||||
|
*/
|
||||||
|
public function testDeleteKeyOverwrite()
|
||||||
|
{
|
||||||
|
$this->delConfigFile('node.config.php');
|
||||||
|
|
||||||
|
$fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||||
|
'..' . DIRECTORY_SEPARATOR .
|
||||||
|
'..' . DIRECTORY_SEPARATOR .
|
||||||
|
'..' . DIRECTORY_SEPARATOR .
|
||||||
|
'datasets' . DIRECTORY_SEPARATOR .
|
||||||
|
'config' . DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
|
vfsStream::newFile('B.config.php')
|
||||||
|
->at($this->root->getChild('config'))
|
||||||
|
->setContent(file_get_contents($fileDir . 'B.config.php'));
|
||||||
|
|
||||||
|
$configFileManager = (new Config())->createConfigFileManager($this->root->url());
|
||||||
|
$configCache = new Cache();
|
||||||
|
|
||||||
|
$configFileManager->setupCache($configCache);
|
||||||
|
|
||||||
|
$configCache->delete('system', 'default_timezone', Cache::SOURCE_DATA);
|
||||||
|
|
||||||
|
$configFileManager->saveData($configCache);
|
||||||
|
|
||||||
|
// assert that system.default_timezone is now null, even it's set with settings.conf.php
|
||||||
|
$configCache = new Cache();
|
||||||
|
|
||||||
|
$configFileManager->setupCache($configCache);
|
||||||
|
|
||||||
|
self::assertNull($configCache->get('system', 'default_timezone'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we delete something with the Cache::delete() functionality, be sure to override the underlying source as well
|
||||||
|
*/
|
||||||
|
public function testDeleteCategoryOverwrite()
|
||||||
|
{
|
||||||
|
$this->delConfigFile('node.config.php');
|
||||||
|
|
||||||
|
$fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
|
||||||
|
'..' . DIRECTORY_SEPARATOR .
|
||||||
|
'..' . DIRECTORY_SEPARATOR .
|
||||||
|
'..' . DIRECTORY_SEPARATOR .
|
||||||
|
'datasets' . DIRECTORY_SEPARATOR .
|
||||||
|
'config' . DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
|
vfsStream::newFile('B.config.php')
|
||||||
|
->at($this->root->getChild('config'))
|
||||||
|
->setContent(file_get_contents($fileDir . 'B.config.php'));
|
||||||
|
|
||||||
|
$configFileManager = (new Config())->createConfigFileManager($this->root->url());
|
||||||
|
$configCache = new Cache();
|
||||||
|
|
||||||
|
$configFileManager->setupCache($configCache);
|
||||||
|
|
||||||
|
$configCache->delete('system');
|
||||||
|
|
||||||
|
$configFileManager->saveData($configCache);
|
||||||
|
|
||||||
|
// assert that system.default_timezone is now null, even it's set with settings.conf.php
|
||||||
|
$configCache = new Cache();
|
||||||
|
|
||||||
|
$configFileManager->setupCache($configCache);
|
||||||
|
|
||||||
|
self::assertNull($configCache->get('system', 'default_timezone'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,7 +364,7 @@ class ConfigTest extends MockedTest
|
||||||
self::assertNull($this->testedConfig->get('test', 'it'));
|
self::assertNull($this->testedConfig->get('test', 'it'));
|
||||||
self::assertNull($this->testedConfig->getCache()->get('test', 'it'));
|
self::assertNull($this->testedConfig->getCache()->get('test', 'it'));
|
||||||
|
|
||||||
self::assertEmpty($this->testedConfig->getCache()->getAll());
|
self::assertEquals(['test' => null], $this->testedConfig->getCache()->getAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -54,10 +54,6 @@ class ConfigTransactionTest extends MockedTest
|
||||||
$config->set('delete', 'keyDel', 'catDel');
|
$config->set('delete', 'keyDel', 'catDel');
|
||||||
|
|
||||||
$configTransaction = new ConfigTransaction($config);
|
$configTransaction = new ConfigTransaction($config);
|
||||||
self::assertEquals('value1', $configTransaction->get('config', 'key1'));
|
|
||||||
self::assertEquals('value2', $configTransaction->get('system', 'key2'));
|
|
||||||
self::assertEquals('valueDel', $configTransaction->get('system', 'keyDel'));
|
|
||||||
self::assertEquals('catDel', $configTransaction->get('delete', 'keyDel'));
|
|
||||||
// the config file knows it as well immediately
|
// the config file knows it as well immediately
|
||||||
$tempData = include $this->root->url() . '/config/' . ConfigFileManager::CONFIG_DATA_FILE;
|
$tempData = include $this->root->url() . '/config/' . ConfigFileManager::CONFIG_DATA_FILE;
|
||||||
self::assertEquals('value1', $tempData['config']['key1'] ?? null);
|
self::assertEquals('value1', $tempData['config']['key1'] ?? null);
|
||||||
|
@ -77,11 +73,6 @@ class ConfigTransactionTest extends MockedTest
|
||||||
self::assertEquals('value1', $config->get('config', 'key1'));
|
self::assertEquals('value1', $config->get('config', 'key1'));
|
||||||
self::assertEquals('valueDel', $config->get('system', 'keyDel'));
|
self::assertEquals('valueDel', $config->get('system', 'keyDel'));
|
||||||
self::assertEquals('catDel', $config->get('delete', 'keyDel'));
|
self::assertEquals('catDel', $config->get('delete', 'keyDel'));
|
||||||
// but the transaction config of course knows it
|
|
||||||
self::assertEquals('value3', $configTransaction->get('transaction', 'key3'));
|
|
||||||
self::assertEquals('changedValue1', $configTransaction->get('config', 'key1'));
|
|
||||||
self::assertNull($configTransaction->get('system', 'keyDel'));
|
|
||||||
self::assertNull($configTransaction->get('delete', 'keyDel'));
|
|
||||||
// The config file still doesn't know it either
|
// The config file still doesn't know it either
|
||||||
$tempData = include $this->root->url() . '/config/' . ConfigFileManager::CONFIG_DATA_FILE;
|
$tempData = include $this->root->url() . '/config/' . ConfigFileManager::CONFIG_DATA_FILE;
|
||||||
self::assertEquals('value1', $tempData['config']['key1'] ?? null);
|
self::assertEquals('value1', $tempData['config']['key1'] ?? null);
|
||||||
|
@ -97,9 +88,6 @@ class ConfigTransactionTest extends MockedTest
|
||||||
self::assertEquals('value3', $config->get('transaction', 'key3'));
|
self::assertEquals('value3', $config->get('transaction', 'key3'));
|
||||||
self::assertNull($config->get('system', 'keyDel'));
|
self::assertNull($config->get('system', 'keyDel'));
|
||||||
self::assertNull($config->get('delete', 'keyDel'));
|
self::assertNull($config->get('delete', 'keyDel'));
|
||||||
self::assertEquals('value3', $configTransaction->get('transaction', 'key3'));
|
|
||||||
self::assertEquals('changedValue1', $configTransaction->get('config', 'key1'));
|
|
||||||
self::assertNull($configTransaction->get('system', 'keyDel'));
|
|
||||||
$tempData = include $this->root->url() . '/config/' . ConfigFileManager::CONFIG_DATA_FILE;
|
$tempData = include $this->root->url() . '/config/' . ConfigFileManager::CONFIG_DATA_FILE;
|
||||||
self::assertEquals('changedValue1', $tempData['config']['key1'] ?? null);
|
self::assertEquals('changedValue1', $tempData['config']['key1'] ?? null);
|
||||||
self::assertEquals('value2', $tempData['system']['key2'] ?? null);
|
self::assertEquals('value2', $tempData['system']['key2'] ?? null);
|
||||||
|
|
Loading…
Reference in a new issue