From 513ef03421f172221fe2457b79910ea944a35375 Mon Sep 17 00:00:00 2001 From: Philipp Date: Sun, 5 Feb 2023 00:15:01 +0100 Subject: [PATCH] Revert node.config.php into Config table --- database.sql | 6 +- .../Config/Capability/IManageConfigValues.php | 2 +- src/Core/Config/Model/Config.php | 139 ---------- src/Core/Config/Model/ConfigTransaction.php | 20 +- src/Core/Config/Model/DatabaseConfig.php | 91 +++++++ src/Core/Config/Model/ReadOnlyFileConfig.php | 82 ++++++ src/Core/Config/Util/ConfigFileManager.php | 168 ------------- .../Config/Util/ConfigFileTransformer.php | 237 ------------------ src/Core/Config/Util/SerializeUtil.php | 107 ++++++++ src/DI.php | 17 +- src/Database/Database.php | 31 ++- src/Module/Admin/Summary.php | 4 - static/dbstructure.config.php | 6 +- static/dependencies.config.php | 4 +- tests/Util/CreateDatabaseTrait.php | 6 +- tests/src/Core/Cache/DatabaseCacheTest.php | 4 +- .../Config/Cache/ConfigFileManagerTest.php | 85 ------- tests/src/Core/Config/ConfigTest.php | 33 +-- .../src/Core/Config/ConfigTransactionTest.php | 34 +-- .../Config/Util/ConfigFileTransformerTest.php | 110 -------- tests/src/Core/InstallerTest.php | 6 +- tests/src/Core/Lock/SemaphoreLockTest.php | 9 +- .../Storage/Repository/StorageManagerTest.php | 4 +- tests/src/Core/SystemTest.php | 2 +- tests/src/Model/UserTest.php | 2 +- tests/src/Util/BaseURLTest.php | 15 +- update.php | 30 +++ 27 files changed, 425 insertions(+), 829 deletions(-) delete mode 100644 src/Core/Config/Model/Config.php create mode 100644 src/Core/Config/Model/DatabaseConfig.php create mode 100644 src/Core/Config/Model/ReadOnlyFileConfig.php delete mode 100644 src/Core/Config/Util/ConfigFileTransformer.php create mode 100644 src/Core/Config/Util/SerializeUtil.php delete mode 100644 tests/src/Core/Config/Util/ConfigFileTransformerTest.php diff --git a/database.sql b/database.sql index b6ee05e84e..e890d7421a 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2023.03-dev (Giant Rhubarb) --- DB_UPDATE_VERSION 1513 +-- DB_UPDATE_VERSION 1514 -- ------------------------------------------ @@ -499,10 +499,12 @@ CREATE TABLE IF NOT EXISTS `cache` ( -- TABLE config -- CREATE TABLE IF NOT EXISTS `config` ( + `id` int unsigned NOT NULL auto_increment COMMENT '', `cat` varbinary(50) NOT NULL DEFAULT '' COMMENT 'The category of the entry', `k` varbinary(50) NOT NULL DEFAULT '' COMMENT 'The key of the entry', `v` mediumtext COMMENT '', - PRIMARY KEY(`cat`,`k`) + PRIMARY KEY(`id`), + UNIQUE INDEX `cat_k` (`cat`,`k`) ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='main configuration storage'; -- diff --git a/src/Core/Config/Capability/IManageConfigValues.php b/src/Core/Config/Capability/IManageConfigValues.php index 2c3d6da3c8..4f785d0077 100644 --- a/src/Core/Config/Capability/IManageConfigValues.php +++ b/src/Core/Config/Capability/IManageConfigValues.php @@ -31,7 +31,7 @@ use Friendica\Core\Config\ValueObject\Cache; interface IManageConfigValues { /** - * Reloads all configuration values (from filesystem and environment variables) + * Reloads all configuration values from the persistence layer * * All configuration values of the system are stored in the cache. * diff --git a/src/Core/Config/Model/Config.php b/src/Core/Config/Model/Config.php deleted file mode 100644 index 46d5643b34..0000000000 --- a/src/Core/Config/Model/Config.php +++ /dev/null @@ -1,139 +0,0 @@ -. - * - */ - -namespace Friendica\Core\Config\Model; - -use Friendica\Core\Config\Capability\IManageConfigValues; -use Friendica\Core\Config\Capability\ISetConfigValuesTransactionally; -use Friendica\Core\Config\Exception\ConfigFileException; -use Friendica\Core\Config\Exception\ConfigPersistenceException; -use Friendica\Core\Config\Util\ConfigFileManager; -use Friendica\Core\Config\ValueObject\Cache; - -/** - * Configuration model, which manages the whole system configuration - */ -class Config implements IManageConfigValues -{ - /** @var Cache */ - protected $configCache; - - /** @var ConfigFileManager */ - protected $configFileManager; - - /** - * @param ConfigFileManager $configFileManager The configuration file manager to save back configs - * @param Cache $configCache The configuration cache (based on the config-files) - */ - public function __construct(ConfigFileManager $configFileManager, Cache $configCache) - { - $this->configFileManager = $configFileManager; - $this->configCache = $configCache; - } - - /** - * Load all configuration values from a given cache and saves it back in the configuration node store - * @see ConfigFileManager::CONFIG_DATA_FILE - * - * All configuration values of the system are stored in the cache. - * - * @param Cache $cache a new cache - * - * @return void - * - * @throws ConfigPersistenceException In case the persistence layer throws errors - */ - public function setCacheAndSave(Cache $cache) - { - $this->configCache = $cache; - $this->save(); - } - - /** - * {@inheritDoc} - */ - public function getCache(): Cache - { - return $this->configCache; - } - - /** {@inheritDoc} */ - public function beginTransaction(): ISetConfigValuesTransactionally - { - return new ConfigTransaction($this); - } - - /** - * Saves the current Configuration back into the data config. - * @see ConfigFileManager::CONFIG_DATA_FILE - */ - protected function save() - { - try { - $this->configFileManager->saveData($this->configCache); - // reload after the save to possible reload default values of lower source-priorities again - $this->reload(); - } catch (ConfigFileException $e) { - throw new ConfigPersistenceException('Cannot save config', $e); - } - } - - /** {@inheritDoc} */ - public function reload() - { - $configCache = new Cache(); - - try { - $this->configFileManager->setupCache($configCache); - } catch (ConfigFileException $e) { - throw new ConfigPersistenceException('Cannot reload config', $e); - } - $this->configCache = $configCache; - } - - /** {@inheritDoc} */ - public function get(string $cat, string $key = null, $default_value = null) - { - return $this->configCache->get($cat, $key) ?? $default_value; - } - - /** {@inheritDoc} */ - public function set(string $cat, string $key, $value): bool - { - if ($this->configCache->set($cat, $key, $value, Cache::SOURCE_DATA)) { - $this->save(); - return true; - } else { - return false; - } - } - - /** {@inheritDoc} */ - public function delete(string $cat, string $key): bool - { - if ($this->configCache->delete($cat, $key)) { - $this->save(); - return true; - } else { - return false; - } - } -} diff --git a/src/Core/Config/Model/ConfigTransaction.php b/src/Core/Config/Model/ConfigTransaction.php index b9310301f3..771565af1e 100644 --- a/src/Core/Config/Model/ConfigTransaction.php +++ b/src/Core/Config/Model/ConfigTransaction.php @@ -34,20 +34,23 @@ class ConfigTransaction implements ISetConfigValuesTransactionally /** @var IManageConfigValues */ protected $config; /** @var Cache */ - protected $cache; + protected $setCache; + /** @var Cache */ + protected $delCache; /** @var bool field to check if something is to save */ protected $changedConfig = false; - public function __construct(IManageConfigValues $config) + public function __construct(DatabaseConfig $config) { - $this->config = $config; - $this->cache = clone $config->getCache(); + $this->config = $config; + $this->setCache = new Cache(); + $this->delCache = new Cache(); } /** {@inheritDoc} */ public function set(string $cat, string $key, $value): ISetConfigValuesTransactionally { - $this->cache->set($cat, $key, $value, Cache::SOURCE_DATA); + $this->setCache->set($cat, $key, $value, Cache::SOURCE_DATA); $this->changedConfig = true; return $this; @@ -57,7 +60,7 @@ class ConfigTransaction implements ISetConfigValuesTransactionally /** {@inheritDoc} */ public function delete(string $cat, string $key): ISetConfigValuesTransactionally { - $this->cache->delete($cat, $key); + $this->delCache->delete($cat, $key); $this->changedConfig = true; return $this; @@ -72,8 +75,9 @@ class ConfigTransaction implements ISetConfigValuesTransactionally } try { - $this->config->setCacheAndSave($this->cache); - $this->cache = clone $this->config->getCache(); + $this->config->setAndSave($this->setCache, $this->delCache); + $this->setCache = new Cache(); + $this->delCache = new Cache(); } catch (\Exception $e) { throw new ConfigPersistenceException('Cannot save config', $e); } diff --git a/src/Core/Config/Model/DatabaseConfig.php b/src/Core/Config/Model/DatabaseConfig.php new file mode 100644 index 0000000000..b9d75d7d5f --- /dev/null +++ b/src/Core/Config/Model/DatabaseConfig.php @@ -0,0 +1,91 @@ +database = $database; + $this->cache = $cache; + + $this->reload(); + } + + /** {@inheritDoc} */ + public function reload() + { + $config = $this->database->selectToArray('config'); + + foreach ($config as $entry) { + $this->cache->set($entry['cat'], $entry['k'], SerializeUtil::maybeUnserialize($entry['v']), Cache::SOURCE_DATA); + } + } + + public function setAndSave(Cache $setCache, Cache $delCache): bool + { + $this->database->transaction(); + + foreach ($setCache->getAll() as $category => $data) { + foreach ($data as $key => $value) { + $this->cache->set($category, $key, $value, Cache::SOURCE_DATA); + $this->database->insert('config', ['cat' => $category, 'k' => $key, 'v' => serialize($value)], Database::INSERT_UPDATE); + } + } + + foreach ($delCache->getAll() as $category => $keys) { + foreach ($keys as $key => $value) { + $this->cache->delete($category, $key); + $this->database->delete('config', ['cat' => $category, 'k' => $key]); + } + } + + return $this->database->commit(); + } + + /** {@inheritDoc} */ + public function get(string $cat, string $key = null, $default_value = null) + { + return $this->cache->get($cat, $key) ?? $default_value; + } + + /** {@inheritDoc} */ + public function set(string $cat, string $key, $value): bool + { + $this->cache->set($cat, $key, $value, Cache::SOURCE_DATA); + return $this->database->insert('config', ['cat' => $cat, 'k' => $key, 'v' => serialize($value)], Database::INSERT_UPDATE); + } + + /** {@inheritDoc} */ + public function beginTransaction(): ISetConfigValuesTransactionally + { + return new ConfigTransaction($this); + } + + /** {@inheritDoc} */ + public function delete(string $cat, string $key): bool + { + $this->cache->delete($cat, $key); + return $this->database->delete('config', ['cat' => $cat, 'k' => $key]); + } + + /** {@inheritDoc} */ + public function getCache(): Cache + { + return $this->cache; + } +} diff --git a/src/Core/Config/Model/ReadOnlyFileConfig.php b/src/Core/Config/Model/ReadOnlyFileConfig.php new file mode 100644 index 0000000000..4b32720f02 --- /dev/null +++ b/src/Core/Config/Model/ReadOnlyFileConfig.php @@ -0,0 +1,82 @@ +. + * + */ + +namespace Friendica\Core\Config\Model; + +use Friendica\Core\Config\Capability\IManageConfigValues; +use Friendica\Core\Config\Capability\ISetConfigValuesTransactionally; +use Friendica\Core\Config\Exception\ConfigPersistenceException; +use Friendica\Core\Config\ValueObject\Cache; + +/** + * Creates a basic, readonly model for the file-based configuration + */ +class ReadOnlyFileConfig implements IManageConfigValues +{ + /** @var Cache */ + protected $configCache; + + /** + * @param Cache $configCache The configuration cache (based on the config-files) + */ + public function __construct(Cache $configCache) + { + $this->configCache = $configCache; + } + + /** + * {@inheritDoc} + */ + public function getCache(): Cache + { + return $this->configCache; + } + + /** {@inheritDoc} */ + public function beginTransaction(): ISetConfigValuesTransactionally + { + throw new ConfigPersistenceException('beginTransaction not allowed.'); + } + + /** {@inheritDoc} */ + public function reload() + { + throw new ConfigPersistenceException('reload not allowed.'); + } + + /** {@inheritDoc} */ + public function get(string $cat, string $key = null, $default_value = null) + { + return $this->configCache->get($cat, $key) ?? $default_value; + } + + /** {@inheritDoc} */ + public function set(string $cat, string $key, $value): bool + { + throw new ConfigPersistenceException('set not allowed.'); + } + + /** {@inheritDoc} */ + public function delete(string $cat, string $key): bool + { + throw new ConfigPersistenceException('Save not allowed'); + } +} diff --git a/src/Core/Config/Util/ConfigFileManager.php b/src/Core/Config/Util/ConfigFileManager.php index ab3784fd5c..5241474ec7 100644 --- a/src/Core/Config/Util/ConfigFileManager.php +++ b/src/Core/Config/Util/ConfigFileManager.php @@ -111,9 +111,6 @@ class ConfigFileManager // Now load every other config you find inside the 'config/' directory $this->loadCoreConfig($configCache); - // Now load the node.config.php file with the node specific config values (based on admin gui/console actions) - $this->loadDataConfig($configCache); - $configCache->load($this->loadEnvConfig(), Cache::SOURCE_ENV); // In case of install mode, add the found basepath (because there isn't a basepath set yet @@ -166,171 +163,6 @@ class ConfigFileManager } } - /** - * Tries to load the data config file with the overridden data - * - * @param Cache $configCache The Config cache - * - * @throws ConfigFileException In case the config file isn't loadable - */ - private function loadDataConfig(Cache $configCache) - { - $filename = $this->configDir . '/' . self::CONFIG_DATA_FILE; - - if (file_exists($filename) && (filesize($filename) > 0)) { - - // The fallback empty return content - $content = '' as prefix. - */ - $dataArray = eval('?>' . $content); - - if (is_array($dataArray)) { - $configCache->load($dataArray, Cache::SOURCE_DATA); - } - } - } - - /** - * Checks, if the node.config.php is writable - * - * @return bool - */ - public function dataIsWritable(): bool - { - $filename = $this->configDir . '/' . self::CONFIG_DATA_FILE; - - if (file_exists($filename)) { - return is_writable($filename); - } else { - return is_writable($this->configDir); - } - } - - /** - * Saves overridden config entries back into the data.config.php - * - * @param Cache $configCache The config cache - * - * @throws ConfigFileException In case the config file isn't writeable or the data is invalid - */ - public function saveData(Cache $configCache) - { - $filename = $this->configDir . '/' . self::CONFIG_DATA_FILE; - - if (file_exists($filename)) { - $fileExists = true; - } else { - $fileExists = false; - } - - /** - * Creates a read-write stream - * - * @see https://www.php.net/manual/en/function.fopen.php - * @note Open the file for reading and writing. If the file does not exist, it is created. - * If it exists, it is neither truncated (as opposed to 'w'), nor the call to this function fails - * (as is the case with 'x'). The file pointer is positioned on the beginning of the file. - * - */ - if (($configStream = @fopen($filename, 'c+')) === false) { - throw new ConfigFileException(sprintf('Cannot open file "%s" in mode c+', $filename)); - } - - try { - // We do want an exclusive lock, so we wait until every LOCK_SH (config reading) is unlocked - if (flock($configStream, LOCK_EX)) { - - /** - * If the file exists, we read the whole file again to avoid a race condition with concurrent threads that could have modified the file between the first config read of this thread and now - * Since we're currently exclusive locked, no other process can now change the config again - */ - if ($fileExists) { - // When reading the config file too fast, we get a wrong filesize, "clearstatcache" prevents that - clearstatcache(true, $filename); - $content = fread($configStream, filesize($filename)); - if (!$content) { - throw new ConfigFileException(sprintf('Cannot read file %s', $filename)); - } - - // Event truncating the whole content wouldn't automatically rewind the stream, - // so we need to do it manually - rewind($configStream); - - $dataArray = eval('?>' . $content); - - // Merge the new content into the existing file based config cache and use it - // as the new config cache - if (is_array($dataArray)) { - $fileConfigCache = new Cache(); - $fileConfigCache->load($dataArray, Cache::SOURCE_DATA); - $configCache = $fileConfigCache->merge($configCache); - } - } - - // Only SOURCE_DATA is wanted, the rest isn't part of the node.config.php file - $data = $configCache->getDataBySource(Cache::SOURCE_DATA); - - $encodedData = ConfigFileTransformer::encode($data); - if (!$encodedData) { - throw new ConfigFileException('config source cannot get encoded'); - } - - // Once again to avoid wrong, implicit "filesize" calls during the fwrite() or ftruncate() call - clearstatcache(true, $filename); - if (!ftruncate($configStream, 0) || - !fwrite($configStream, $encodedData) || - !fflush($configStream)) { - throw new ConfigFileException(sprintf('Cannot modify locked file %s', $filename)); - } - } else { - throw new ConfigFileException(sprintf('Cannot lock file %s', $filename)); - } - } finally { - // unlock and close the stream for every circumstances - flock($configStream, LOCK_UN); - fclose($configStream); - } - } - /** * Tries to load the specified addon-configuration and returns the config array. * diff --git a/src/Core/Config/Util/ConfigFileTransformer.php b/src/Core/Config/Util/ConfigFileTransformer.php deleted file mode 100644 index f159721644..0000000000 --- a/src/Core/Config/Util/ConfigFileTransformer.php +++ /dev/null @@ -1,237 +0,0 @@ -. - * - */ - -namespace Friendica\Core\Config\Util; - -/** - * Util to transform back the config array into a string - */ -class ConfigFileTransformer -{ - /** - * This method takes an array of config values and applies some standard rules for formatting on it - * - * Beware that the applied rules follow some basic formatting principles for node.config.php - * and doesn't support any custom formatting rules. - * - * f.e. associative array and list formatting are very complex with newlines and indentations, thus there are - * three hardcoded types of formatting for them. - * - * a negative example, what's NOT working: - * key => [ value1, [inner_value1, inner_value2], value2] - * Since this isn't necessary for config values, there's no further logic handling such complex-list-in-list scenarios - * - * @param array $data A full config array - * - * @return string The config stream, which can be saved - */ - public static function encode(array $data): string - { - // Add the typical header values - $dataString = ' value, - * 'key' => value, - * ... - * ] - * - * @param array $config The associative/key-value array - * @param int $level The current level of recursion (necessary for tab-indentation calculation) - * @param bool $inList If true, the current array resides inside another list. Different rules may be applicable - * - * @return string The config string - */ - protected static function extractAssociativeArray(array $config, int $level = 0, bool $inList = false): string - { - $string = ''; - - // Because we're in a list, we have to add a line-break first - if ($inList) { - $string .= PHP_EOL . str_repeat("\t", $level); - } - - // Add a typical Line break for a taxative list of key-value pairs - $string .= '[' . PHP_EOL; - - foreach ($config as $configKey => $configValue) { - $string .= str_repeat("\t", $level + 1) . - "'$configKey' => " . - static::transformConfigValue($configValue, $level) . - ',' . PHP_EOL; - } - - $string .= str_repeat("\t", $level) . ']'; - - return $string; - } - - /** - * Extracts a list and save it into a string - * output1 - simple: - * [ value, value, value ] - * - * output2 - complex: - * [ - * [ value, value, value ], - * value, - * [ - * key => value, - * key => value, - * ], - * ] - * - * @param array $config The list - * @param int $level The current level of recursion (necessary for tab-indentation calculation) - * @param bool $inList If true, the current array resides inside another list. Different rules may be applicable - * - * @return string The config string - */ - protected static function extractList(array $config, int $level = 0, bool $inList = false): string - { - $string = '['; - - $countConfigValues = count($config); - // multiline defines, if each entry uses a new line - $multiline = false; - - // Search if any value is an array, because then other formatting rules are applicable - foreach ($config as $item) { - if (is_array($item)) { - $multiline = true; - break; - } - } - - for ($i = 0; $i < $countConfigValues; $i++) { - $isArray = is_array($config[$i]); - - /** - * In case this is an array in an array, directly extract this array again and continue - * Skip any other logic since this isn't applicable for an array in an array - */ - if ($isArray) { - $string .= PHP_EOL . str_repeat("\t", $level + 1); - $string .= static::extractArray($config[$i], $level + 1, $inList) . ','; - continue; - } - - if ($multiline) { - $string .= PHP_EOL . str_repeat("\t", $level + 1); - } - - $string .= static::transformConfigValue($config[$i], $level, true); - - // add trailing commas or whitespaces for certain config entries - if (($i < ($countConfigValues - 1))) { - $string .= ','; - if (!$multiline) { - $string .= ' '; - } - } - } - - // Add a new line for the last bracket as well - if ($multiline) { - $string .= PHP_EOL . str_repeat("\t", $level); - } - - $string .= ']'; - - return $string; - } - - /** - * Transforms one config value and returns the corresponding text-representation - * - * @param mixed $value Any value to transform - * @param int $level The current level of recursion (necessary for tab-indentation calculation) - * @param bool $inList If true, the current array resides inside another list. Different rules may be applicable - * - * @return string - */ - protected static function transformConfigValue($value, int $level = 0, bool $inList = false): string - { - switch (gettype($value)) { - case "boolean": - return ($value ? 'true' : 'false'); - case "integer": - case "double": - return $value; - case "string": - return sprintf('\'%s\'', addcslashes($value, '\'\\')); - case "array": - return static::extractArray($value, ++$level, $inList); - case "NULL": - return "null"; - case "object": - if (method_exists($value, '__toString')) { - return sprintf('\'%s\'', $value); - } elseif ($value instanceof \Serializable) { - try { - return $value->serialize(); - } catch (\Exception $e) { - throw new \InvalidArgumentException(sprintf('Cannot serialize %s.', gettype($value)), $e); - } - } else { - throw new \InvalidArgumentException(sprintf('%s is an object without stringify.', gettype($value))); - } - case "resource": - case "resource (closed)": - throw new \InvalidArgumentException(sprintf('%s in configs are not supported yet.', gettype($value))); - case "unknown type": - throw new \InvalidArgumentException(sprintf('%s is an unknown value', $value)); - default: - throw new \InvalidArgumentException(sprintf('%s is currently unsupported', $value)); - } - } -} diff --git a/src/Core/Config/Util/SerializeUtil.php b/src/Core/Config/Util/SerializeUtil.php new file mode 100644 index 0000000000..cd855c2806 --- /dev/null +++ b/src/Core/Config/Util/SerializeUtil.php @@ -0,0 +1,107 @@ +setDependency(static::config(), static::profiler(), static::logger()); } /** diff --git a/src/Database/Database.php b/src/Database/Database.php index a5fe7f978a..9527fefb0f 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -36,6 +36,7 @@ use PDO; use PDOException; use PDOStatement; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; /** * This class is for the low level database stuff that does driver specific things. @@ -54,15 +55,15 @@ class Database /** * @var IManageConfigValues */ - protected $config; + protected $config = null; /** * @var Profiler */ - protected $profiler; + protected $profiler = null; /** * @var LoggerInterface */ - protected $logger; + protected $logger = null; protected $server_info = ''; /** @var PDO|mysqli */ protected $connection; @@ -80,18 +81,36 @@ class Database /** @var ViewDefinition */ protected $viewDefinition; - public function __construct(IManageConfigValues $config, Profiler $profiler, DbaDefinition $dbaDefinition, ViewDefinition $viewDefinition, LoggerInterface $logger) + public function __construct(IManageConfigValues $config, DbaDefinition $dbaDefinition, ViewDefinition $viewDefinition) { // We are storing these values for being able to perform a reconnect $this->config = $config; - $this->profiler = $profiler; $this->dbaDefinition = $dbaDefinition; $this->viewDefinition = $viewDefinition; - $this->logger = $logger; + + // Use dummy values - necessary for the first factory call of the logger itself + $this->logger = new NullLogger(); + $this->profiler = new Profiler($config); $this->connect(); } + /** + * @param IManageConfigValues $config + * @param Profiler $profiler + * @param LoggerInterface $logger + * + * @return void + * + * @todo Make this method obsolet - use a clean pattern instead ... + */ + public function setDependency(IManageConfigValues $config, Profiler $profiler, LoggerInterface $logger) + { + $this->logger = $logger; + $this->profiler = $profiler; + $this->config = $config; + } + /** * Tries to connect to database * diff --git a/src/Module/Admin/Summary.php b/src/Module/Admin/Summary.php index 9ca71e33d2..b4ea14cf02 100644 --- a/src/Module/Admin/Summary.php +++ b/src/Module/Admin/Summary.php @@ -114,10 +114,6 @@ class Summary extends BaseAdmin $warningtext[] = DI::l10n()->t('Friendica\'s configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from config/local.ini.php. See the Config help page for help with the transition.', DI::baseUrl()->get() . '/help/Config'); } - if (!DI::configFileManager()->dataIsWritable()) { - $warningtext[] = DI::l10n()->t('Friendica\'s configuration store "%s" isn\'t writable. Until then database updates won\'t be applied automatically, admin settings and console configuration changes won\'t be saved.', ConfigFileManager::CONFIG_DATA_FILE); - } - // Check server vitality if (!self::checkSelfHostMeta()) { $well_known = DI::baseUrl()->get() . Probe::HOST_META; diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 3eeacb705d..dcab1d0c87 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -55,7 +55,7 @@ use Friendica\Database\DBA; if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1513); + define('DB_UPDATE_VERSION', 1514); } return [ @@ -557,12 +557,14 @@ return [ "config" => [ "comment" => "main configuration storage", "fields" => [ + "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""], "cat" => ["type" => "varbinary(50)", "not null" => "1", "default" => "", "comment" => "The category of the entry"], "k" => ["type" => "varbinary(50)", "not null" => "1", "default" => "", "comment" => "The key of the entry"], "v" => ["type" => "mediumtext", "comment" => ""], ], "indexes" => [ - "PRIMARY" => ["cat", "k"], + "PRIMARY" => ["id"], + "cat_k" => ["UNIQUE", "cat", "k"], ] ], "contact-relation" => [ diff --git a/static/dependencies.config.php b/static/dependencies.config.php index 5b7a345685..42f193ba53 100644 --- a/static/dependencies.config.php +++ b/static/dependencies.config.php @@ -108,7 +108,7 @@ return [ ], ], Config\Capability\IManageConfigValues::class => [ - 'instanceOf' => Config\Model\Config::class, + 'instanceOf' => Config\Model\DatabaseConfig::class, 'constructParams' => [ $_SERVER, ], @@ -137,7 +137,7 @@ return [ ], Database::class => [ 'constructParams' => [ - [Dice::INSTANCE => \Psr\Log\NullLogger::class], + [Dice::INSTANCE => Config\Model\ReadOnlyFileConfig::class], ], ], /** diff --git a/tests/Util/CreateDatabaseTrait.php b/tests/Util/CreateDatabaseTrait.php index 127d8da2f1..7cb13cc225 100644 --- a/tests/Util/CreateDatabaseTrait.php +++ b/tests/Util/CreateDatabaseTrait.php @@ -21,7 +21,7 @@ namespace Friendica\Test\Util; -use Friendica\Core\Config\Model\Config; +use Friendica\Core\Config\Model\ReadOnlyFileConfig; use Friendica\Core\Config\Util\ConfigFileManager; use Friendica\Core\Config\ValueObject\Cache; use Friendica\Database\Database; @@ -40,13 +40,13 @@ trait CreateDatabaseTrait public function getDbInstance(): Database { $configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/'); - $config = new Config($configFileManager, new Cache([ + $config = new ReadOnlyFileConfig(new Cache([ 'database' => [ 'disable_pdo' => true ], ])); - $database = new StaticDatabase($config, new Profiler($config), (new DbaDefinition($this->root->url()))->load(), (new ViewDefinition($this->root->url()))->load(), new NullLogger()); + $database = new StaticDatabase($config, (new DbaDefinition($this->root->url()))->load(), (new ViewDefinition($this->root->url()))->load()); $database->setTestmode(true); return $database; diff --git a/tests/src/Core/Cache/DatabaseCacheTest.php b/tests/src/Core/Cache/DatabaseCacheTest.php index 81804a806e..9088c38af0 100644 --- a/tests/src/Core/Cache/DatabaseCacheTest.php +++ b/tests/src/Core/Cache/DatabaseCacheTest.php @@ -57,12 +57,12 @@ class DatabaseCacheTest extends CacheTest $configFactory = new Config(); $configFileManager = (new Config())->createConfigFileManager($this->root->url(), []); $configCache = $configFactory->createCache($configFileManager); - $config = new \Friendica\Core\Config\Model\Config($configFileManager, $configCache); + $config = new \Friendica\Core\Config\Model\ReadOnlyFileConfig($configCache); $dbaDefinition = (new DbaDefinition($configCache->get('system', 'basepath')))->load(); $viewDefinition = (new ViewDefinition($configCache->get('system', 'basepath')))->load(); - $dba = new StaticDatabase($config, $profiler, $dbaDefinition, $viewDefinition, new NullLogger()); + $dba = new StaticDatabase($config, $dbaDefinition, $viewDefinition); $this->cache = new Cache\Type\DatabaseCache('database', $dba); return $this->cache; diff --git a/tests/src/Core/Config/Cache/ConfigFileManagerTest.php b/tests/src/Core/Config/Cache/ConfigFileManagerTest.php index e5b630a200..1385c8b19a 100644 --- a/tests/src/Core/Config/Cache/ConfigFileManagerTest.php +++ b/tests/src/Core/Config/Cache/ConfigFileManagerTest.php @@ -392,91 +392,6 @@ class ConfigFileManagerTest extends MockedTest self::assertEquals('newValue', $configCache->get('system', 'newKey')); } - public function testSaveData() - { - $this->delConfigFile('local.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('config2')) - ->setContent(file_get_contents($fileDir . 'B.config.php')); - - $configFileManager = (new Config())->createConfigFileManager($this->root->url(), - [ - 'FRIENDICA_CONFIG_DIR' => $this->root->getChild('config2')->url(), - ]); - $configCache = new Cache(); - - $configFileManager->setupCache($configCache); - - $specialChars = '!"§$%&/()(/&%$\'>set('system', 'test', 'it', Cache::SOURCE_DATA); - $configCache->set('config', 'test', 'it', Cache::SOURCE_DATA); - $configCache->set('system', 'test_2', 2, Cache::SOURCE_DATA); - $configCache->set('special_chars', 'special', $specialChars, Cache::SOURCE_DATA); - $configFileManager->saveData($configCache); - - // Reload the configCache with the new values - $configCache2 = new Cache(); - $configFileManager->setupCache($configCache2); - - self::assertEquals($configCache, $configCache2); - self::assertEquals([ - 'system' => [ - 'test' => 'it', - 'test_2' => 2 - ], - 'config' => [ - 'test' => 'it', - ], - 'special_chars' => [ - 'special' => $specialChars, - ]], $configCache2->getDataBySource(Cache::SOURCE_DATA)); - } - - /** - * If we delete something with the Cache::delete() functionality, be sure to probably reset it to the underlying key - */ - 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'); - - $configFileManager->saveData($configCache); - - // assert that system.default_timezone is now the restored 'UTC' from the defaults - $configCache = new Cache(); - - $configFileManager->setupCache($configCache); - - self::assertEquals('UTC', $configCache->get('system', 'default_timezone')); - } - /** * Test for empty node.config.php */ diff --git a/tests/src/Core/Config/ConfigTest.php b/tests/src/Core/Config/ConfigTest.php index f244044743..7a198d06e9 100644 --- a/tests/src/Core/Config/ConfigTest.php +++ b/tests/src/Core/Config/ConfigTest.php @@ -23,18 +23,21 @@ namespace Friendica\Test\src\Core\Config; use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts; use Friendica\Core\Config\Capability\IManageConfigValues; -use Friendica\Core\Config\Model\Config; +use Friendica\Core\Config\Model\DatabaseConfig; +use Friendica\Core\Config\Model\ReadOnlyFileConfig; use Friendica\Core\Config\Util\ConfigFileManager; use Friendica\Core\Config\Util\ConfigFileTransformer; use Friendica\Core\Config\ValueObject\Cache; -use Friendica\Test\MockedTest; +use Friendica\Test\DatabaseTest; +use Friendica\Test\Util\CreateDatabaseTrait; use Friendica\Test\Util\VFSTrait; use org\bovigo\vfs\vfsStream; -class ConfigTest extends MockedTest +class ConfigTest extends DatabaseTest { use ArraySubsetAsserts; use VFSTrait; + use CreateDatabaseTrait; /** @var Cache */ protected $configCache; @@ -77,7 +80,7 @@ class ConfigTest extends MockedTest public function getInstance() { $this->configFileManager->setupCache($this->configCache); - return new Config($this->configFileManager, $this->configCache); + return new DatabaseConfig($this->getDbInstance(), $this->configCache); } public function dataTests() @@ -170,7 +173,7 @@ class ConfigTest extends MockedTest { vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE) ->at($this->root->getChild('config')) - ->setContent(ConfigFileTransformer::encode($data)); + ->setContent(print_r($data, true)); $this->testedConfig = $this->getInstance(); self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); @@ -191,7 +194,7 @@ class ConfigTest extends MockedTest { vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE) ->at($this->root->getChild('config')) - ->setContent(ConfigFileTransformer::encode($data)); + ->setContent(print_r($data, true)); $this->testedConfig = $this->getInstance(); self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); @@ -276,7 +279,7 @@ class ConfigTest extends MockedTest { vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE) ->at($this->root->getChild('config')) - ->setContent(ConfigFileTransformer::encode($data1)); + ->setContent(print_r($data1, true)); $this->testedConfig = $this->getInstance(); self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); @@ -288,7 +291,7 @@ class ConfigTest extends MockedTest vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE) ->at($this->root->getChild('config')) - ->setContent(ConfigFileTransformer::encode($data2)); + ->setContent(print_r($data2, true)); $this->testedConfig->reload(); @@ -302,7 +305,7 @@ class ConfigTest extends MockedTest */ public function testLoadWrong() { - $this->testedConfig = new Config($this->configFileManager, new Cache()); + $this->testedConfig = new ReadOnlyFileConfig(new Cache()); self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); self::assertEmpty($this->testedConfig->getCache()->getAll()); @@ -354,7 +357,7 @@ class ConfigTest extends MockedTest { $this->configCache->load(['test' => ['it' => $data]], Cache::SOURCE_FILE); - $this->testedConfig = new Config($this->configFileManager, $this->configCache); + $this->testedConfig = new DatabaseConfig($this->getDbInstance(), $this->configCache); self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); self::assertEquals($data, $this->testedConfig->get('test', 'it')); @@ -388,9 +391,9 @@ class ConfigTest extends MockedTest { vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE) ->at($this->root->getChild('config')) - ->setContent(ConfigFileTransformer::encode([ + ->setContent(print_r([ 'config' => ['test' => 'it'], - ])); + ], true)); $this->testedConfig = $this->getInstance(); self::assertInstanceOf(Cache::class, $this->testedConfig->getCache()); @@ -526,7 +529,7 @@ class ConfigTest extends MockedTest public function testGetCategory(array $data, string $category, array $assertion) { $this->configCache = new Cache($data); - $config = new Config($this->configFileManager, $this->configCache); + $config = new ReadOnlyFileConfig($this->configCache); self::assertEquals($assertion, $config->get($category)); } @@ -538,9 +541,9 @@ class ConfigTest extends MockedTest { vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE) ->at($this->root->getChild('config')) - ->setContent(ConfigFileTransformer::encode([ + ->setContent(print_r([ 'config' => ['sitename' => 'overritten'], - ])); + ], true)); $config = $this->getInstance(); self::assertEquals('overritten', $config->get('config', 'sitename')); diff --git a/tests/src/Core/Config/ConfigTransactionTest.php b/tests/src/Core/Config/ConfigTransactionTest.php index c6eb7e2685..30e6d9885a 100644 --- a/tests/src/Core/Config/ConfigTransactionTest.php +++ b/tests/src/Core/Config/ConfigTransactionTest.php @@ -22,18 +22,21 @@ namespace Friendica\Test\src\Core\Config; use Friendica\Core\Config\Capability\ISetConfigValuesTransactionally; -use Friendica\Core\Config\Model\Config; +use Friendica\Core\Config\Model\DatabaseConfig; +use Friendica\Core\Config\Model\ReadOnlyFileConfig; use Friendica\Core\Config\Model\ConfigTransaction; use Friendica\Core\Config\Util\ConfigFileManager; use Friendica\Core\Config\ValueObject\Cache; +use Friendica\Database\Database; +use Friendica\Test\DatabaseTest; +use Friendica\Test\FixtureTest; use Friendica\Test\MockedTest; +use Friendica\Test\Util\Database\StaticDatabase; use Friendica\Test\Util\VFSTrait; use Mockery\Exception\InvalidCountException; -class ConfigTransactionTest extends MockedTest +class ConfigTransactionTest extends FixtureTest { - use VFSTrait; - /** @var ConfigFileManager */ protected $configFileManager; @@ -41,8 +44,6 @@ class ConfigTransactionTest extends MockedTest { parent::setUp(); - $this->setUpVfsDir(); - $this->configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/'); } @@ -57,7 +58,7 @@ class ConfigTransactionTest extends MockedTest public function testInstance() { - $config = new Config($this->configFileManager, new Cache()); + $config = new DatabaseConfig($this->dice->create(Database::class), new Cache()); $configTransaction = new ConfigTransaction($config); self::assertInstanceOf(ISetConfigValuesTransactionally::class, $configTransaction); @@ -66,17 +67,13 @@ class ConfigTransactionTest extends MockedTest public function testConfigTransaction() { - $config = new Config($this->configFileManager, new Cache()); + $config = new DatabaseConfig($this->dice->create(Database::class), new Cache()); $config->set('config', 'key1', 'value1'); $config->set('system', 'key2', 'value2'); $config->set('system', 'keyDel', 'valueDel'); $config->set('delete', 'keyDel', 'catDel'); $configTransaction = new ConfigTransaction($config); - // the config file knows it as well immediately - $tempData = include $this->root->url() . '/config/' . ConfigFileManager::CONFIG_DATA_FILE; - self::assertEquals('value1', $tempData['config']['key1'] ?? null); - self::assertEquals('value2', $tempData['system']['key2'] ?? null); // new key-value $configTransaction->set('transaction', 'key3', 'value3'); @@ -93,11 +90,6 @@ class ConfigTransactionTest extends MockedTest self::assertEquals('valueDel', $config->get('system', 'keyDel')); self::assertEquals('catDel', $config->get('delete', 'keyDel')); // The config file still doesn't know it either - $tempData = include $this->root->url() . '/config/' . ConfigFileManager::CONFIG_DATA_FILE; - self::assertEquals('value1', $tempData['config']['key1'] ?? null); - self::assertEquals('value2', $tempData['system']['key2'] ?? null); - self::assertEquals('catDel', $tempData['delete']['keyDel'] ?? null); - self::assertNull($tempData['transaction']['key3'] ?? null); // save it back! $configTransaction->commit(); @@ -107,12 +99,6 @@ class ConfigTransactionTest extends MockedTest self::assertEquals('value3', $config->get('transaction', 'key3')); self::assertNull($config->get('system', 'keyDel')); self::assertNull($config->get('delete', 'keyDel')); - $tempData = include $this->root->url() . '/config/' . ConfigFileManager::CONFIG_DATA_FILE; - self::assertEquals('changedValue1', $tempData['config']['key1'] ?? null); - self::assertEquals('value2', $tempData['system']['key2'] ?? null); - self::assertEquals('value3', $tempData['transaction']['key3'] ?? null); - self::assertNull($tempData['system']['keyDel'] ?? null); - self::assertNull($tempData['delete']['keyDel'] ?? null); // the whole category should be gone self::assertNull($tempData['delete'] ?? null); } @@ -124,7 +110,7 @@ class ConfigTransactionTest extends MockedTest { $this->configFileManager = \Mockery::spy(ConfigFileManager::class); - $config = new Config($this->configFileManager, new Cache()); + $config = new DatabaseConfig($this->dice->create(Database::class), new Cache()); $configTransaction = new ConfigTransaction($config); // commit empty transaction diff --git a/tests/src/Core/Config/Util/ConfigFileTransformerTest.php b/tests/src/Core/Config/Util/ConfigFileTransformerTest.php deleted file mode 100644 index c11a770ad8..0000000000 --- a/tests/src/Core/Config/Util/ConfigFileTransformerTest.php +++ /dev/null @@ -1,110 +0,0 @@ -. - * - */ - -namespace Friendica\Test\src\Core\Config\Util; - -use Friendica\Core\Config\Util\ConfigFileTransformer; -use Friendica\Test\MockedTest; -use Friendica\Test\Util\SerializableObjectDouble; -use ParagonIE\HiddenString\HiddenString; -use function PHPUnit\Framework\assertEquals; - -class ConfigFileTransformerTest extends MockedTest -{ - public function dataTests() - { - return [ - 'default' => [ - 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/A.node.config.php'), - ], - 'extended' => [ - 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/B.node.config.php'), - ], - 'friendica.local' => [ - 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/C.node.config.php'), - ], - 'friendica.local.2' => [ - 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/D.node.config.php'), - ], - 'object_invalid' => [ - 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/object.node.config.php'), - 'assertException' => true, - ], - 'resource' => [ - 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/ressource.node.config.php'), - 'assertException' => false, - 'assertion' => << [ - 'ressources_not_allowed' => '', - ], -]; - -EOF, - ], - 'object_valid' => [ - 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/object_valid.node.config.php'), - 'assertException' => false, - 'assertion' => << [ - 'toString' => 'test', - 'serializable' => 'serialized', - ], -]; - -EOF, - ], - 'test_types' => [ - 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/types.node.config.php'), - ], - 'small_types' => [ - 'configFile' => (dirname(__DIR__, 4) . '/datasets/config/transformer/small_types.node.config.php'), - ] - ]; - } - - /** - * Tests if the given config will be decoded into an array and encoded into the same string again - * - * @dataProvider dataTests - */ - public function testConfigFile(string $configFile, bool $assertException = false, $assertion = null) - { - $dataArray = include $configFile; - - if ($assertException) { - self::expectException(\InvalidArgumentException::class); - } - - $newConfig = ConfigFileTransformer::encode($dataArray); - - if (empty($assertion)) { - self::assertEquals(file_get_contents($configFile), $newConfig); - } else { - self::assertEquals($assertion, $newConfig); - } - } -} diff --git a/tests/src/Core/InstallerTest.php b/tests/src/Core/InstallerTest.php index 415b1d3e8b..376703a270 100644 --- a/tests/src/Core/InstallerTest.php +++ b/tests/src/Core/InstallerTest.php @@ -63,7 +63,7 @@ class InstallerTest extends MockedTest ->with(L10n::class) ->andReturn($this->l10nMock); - DI::init($this->dice); + DI::init($this->dice, true); } public static function tearDownAfterClass(): void @@ -361,7 +361,7 @@ class InstallerTest extends MockedTest ->with(ICanSendHttpRequests::class) ->andReturn($networkMock); - DI::init($this->dice); + DI::init($this->dice, true); // Mocking that we can use CURL $this->setFunctions(['curl_init' => true]); @@ -408,7 +408,7 @@ class InstallerTest extends MockedTest ->with(ICanSendHttpRequests::class) ->andReturn($networkMock); - DI::init($this->dice); + DI::init($this->dice, true); // Mocking that we can use CURL $this->setFunctions(['curl_init' => true]); diff --git a/tests/src/Core/Lock/SemaphoreLockTest.php b/tests/src/Core/Lock/SemaphoreLockTest.php index 6473935cab..41e73891ee 100644 --- a/tests/src/Core/Lock/SemaphoreLockTest.php +++ b/tests/src/Core/Lock/SemaphoreLockTest.php @@ -24,11 +24,8 @@ namespace Friendica\Test\src\Core\Lock; use Dice\Dice; use Friendica\App; use Friendica\Core\Config\Capability\IManageConfigValues; -use Friendica\Core\Config\Model\Config; -use Friendica\Core\Config\Type\JitConfig; -use Friendica\Core\Config\Util\ConfigFileManager; +use Friendica\Core\Config\Model\ReadOnlyFileConfig; use Friendica\Core\Config\ValueObject\Cache; -use Friendica\Core\Lock\Type\SemaphoreLock; use Friendica\Core\System; use Friendica\DI; use Mockery; @@ -46,11 +43,11 @@ class SemaphoreLockTest extends LockTest $dice->shouldReceive('create')->with(App::class)->andReturn($app); $configCache = new Cache(['system' => ['temppath' => '/tmp']]); - $configMock = new Config(Mockery::mock(ConfigFileManager::class), $configCache); + $configMock = new ReadOnlyFileConfig($configCache); $dice->shouldReceive('create')->with(IManageConfigValues::class)->andReturn($configMock); // @todo Because "get_temppath()" is using static methods, we have to initialize the BaseObject - DI::init($dice); + DI::init($dice, true); parent::setUp(); } diff --git a/tests/src/Core/Storage/Repository/StorageManagerTest.php b/tests/src/Core/Storage/Repository/StorageManagerTest.php index 7a976832f7..446e93a7aa 100644 --- a/tests/src/Core/Storage/Repository/StorageManagerTest.php +++ b/tests/src/Core/Storage/Repository/StorageManagerTest.php @@ -75,19 +75,19 @@ class StorageManagerTest extends DatabaseTest vfsStream::newDirectory(Type\FilesystemConfig::DEFAULT_BASE_FOLDER, 0777)->at($this->root); $this->logger = new NullLogger(); + $this->database = $this->getDbInstance(); $configFactory = new Config(); $configFileManager = $configFactory->createConfigFileManager($this->root->url()); $configCache = $configFactory->createCache($configFileManager); - $this->config = new \Friendica\Core\Config\Model\Config($configFileManager, $configCache); + $this->config = new \Friendica\Core\Config\Model\DatabaseConfig($this->database, $configCache); $this->config->set('storage', 'name', 'Database'); $this->config->set('storage', 'filesystem_path', $this->root->getChild(Type\FilesystemConfig::DEFAULT_BASE_FOLDER) ->url()); $this->l10n = \Mockery::mock(L10n::class); - $this->database = $this->getDbInstance(); } protected function tearDown(): void diff --git a/tests/src/Core/SystemTest.php b/tests/src/Core/SystemTest.php index eaa704d9d9..9cfbe052ca 100644 --- a/tests/src/Core/SystemTest.php +++ b/tests/src/Core/SystemTest.php @@ -36,7 +36,7 @@ class SystemTest extends TestCase $dice = \Mockery::mock(Dice::class); $dice->shouldReceive('create')->with(BaseURL::class)->andReturn($baseUrl); - DI::init($dice); + DI::init($dice, true); } private function assertGuid($guid, $length, $prefix = '') diff --git a/tests/src/Model/UserTest.php b/tests/src/Model/UserTest.php index b2b9bba927..f1785f99d7 100644 --- a/tests/src/Model/UserTest.php +++ b/tests/src/Model/UserTest.php @@ -47,7 +47,7 @@ class UserTest extends MockedTest /** @var Dice|MockInterface $diceMock */ $diceMock = $diceMock->addRules(include __DIR__ . '/../../../static/dependencies.config.php'); $diceMock->shouldReceive('create')->withArgs([Database::class])->andReturn($this->dbMock); - DI::init($diceMock); + DI::init($diceMock, true); $this->parent = [ 'uid' => 1, diff --git a/tests/src/Util/BaseURLTest.php b/tests/src/Util/BaseURLTest.php index 4095c344da..a72ffc607b 100644 --- a/tests/src/Util/BaseURLTest.php +++ b/tests/src/Util/BaseURLTest.php @@ -23,15 +23,18 @@ namespace Friendica\Test\src\Util; use Friendica\App\BaseURL; use Friendica\Core\Config\Capability\IManageConfigValues; -use Friendica\Core\Config\Model\Config; +use Friendica\Core\Config\Model\DatabaseConfig; +use Friendica\Core\Config\Model\ReadOnlyFileConfig; use Friendica\Core\Config\Util\ConfigFileManager; use Friendica\Core\Config\ValueObject\Cache; -use Friendica\Test\MockedTest; +use Friendica\Test\DatabaseTest; +use Friendica\Test\Util\CreateDatabaseTrait; use Friendica\Test\Util\VFSTrait; -class BaseURLTest extends MockedTest +class BaseURLTest extends DatabaseTest { use VFSTrait; + use CreateDatabaseTrait; protected function setUp(): void { @@ -302,8 +305,7 @@ class BaseURLTest extends MockedTest */ public function testSave($input, $save, $url) { - $configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/'); - $config = new Config($configFileManager, new Cache([ + $config = new DatabaseConfig($this->getDbInstance(), new Cache([ 'config' => [ 'hostname' => $input['hostname'] ?? null, ], @@ -332,8 +334,7 @@ class BaseURLTest extends MockedTest */ public function testSaveByUrl($input, $save, $url) { - $configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/'); - $config = new Config($configFileManager, new Cache([ + $config = new DatabaseConfig($this->getDbInstance(), new Cache([ 'config' => [ 'hostname' => $input['hostname'] ?? null, ], diff --git a/update.php b/update.php index 7d9a9d2363..db75f116d9 100644 --- a/update.php +++ b/update.php @@ -1253,3 +1253,33 @@ function update_1513() DI::config()->delete('system', 'git_friendica_version'); DI::config()->delete('twitter', 'application_name'); } + +function update_1514() +{ + if (file_exists(dirname(__FILE__) . '/config/node.config.php')) { + + $transactionalConfig = DI::config()->beginTransaction(); + $oldConfig = include dirname(__FILE__) . '/config/node.config.php'; + + if (is_array($oldConfig)) { + $categories = array_keys($oldConfig); + + foreach ($categories as $category) { + if (is_array($oldConfig[$category])) { + $keys = array_keys($oldConfig[$category]); + + foreach ($keys as $key) { + $transactionalConfig->set($category, $key, $oldConfig[$category][$key]); + } + } + } + } + + $transactionalConfig->commit(); + + // Rename the node.config.php so it won't get used, but it isn't deleted. + rename(dirname(__FILE__) . '/config/node.config.php', dirname(__FILE__) . '/config/node.config.php.bak'); + } + + return Update::SUCCESS; +}