Merge pull request #12593 from nupplaphil/feat/node.config.php

Replace `config` with `node.config.php`
This commit is contained in:
Hypolite Petovan 2023-01-03 11:43:55 -05:00 committed by GitHub
commit 19603fd6a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
57 changed files with 1345 additions and 1516 deletions

View file

@ -71,7 +71,7 @@ if (DI::mode()->isInstall()) {
DI::mode()->setExecutor(Mode::DAEMON);
DI::config()->load();
DI::config()->reload();
if (empty(DI::config()->get('system', 'pidfile'))) {
die(<<<TXT

View file

@ -1,6 +1,6 @@
-- ------------------------------------------
-- Friendica 2023.03-dev (Giant Rhubarb)
-- DB_UPDATE_VERSION 1507
-- DB_UPDATE_VERSION 1508
-- ------------------------------------------
@ -494,18 +494,6 @@ CREATE TABLE IF NOT EXISTS `cache` (
INDEX `k_expires` (`k`,`expires`)
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Stores temporary data';
--
-- TABLE config
--
CREATE TABLE IF NOT EXISTS `config` (
`id` int unsigned NOT NULL auto_increment COMMENT '',
`cat` varbinary(50) NOT NULL DEFAULT '' COMMENT '',
`k` varbinary(50) NOT NULL DEFAULT '' COMMENT '',
`v` mediumtext COMMENT '',
PRIMARY KEY(`id`),
UNIQUE INDEX `cat_k` (`cat`,`k`)
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='main configuration storage';
--
-- TABLE contact-relation
--

View file

@ -18,7 +18,6 @@ Database Tables
| [arrived-activity](help/database/db_arrived-activity) | Id of arrived activities |
| [attach](help/database/db_attach) | file attachments |
| [cache](help/database/db_cache) | Stores temporary data |
| [config](help/database/db_config) | main configuration storage |
| [contact](help/database/db_contact) | contact table |
| [contact-relation](help/database/db_contact-relation) | Contact relations |
| [conv](help/database/db_conv) | private messages |

View file

@ -1,25 +0,0 @@
Table config
===========
main configuration storage
Fields
------
| Field | Description | Type | Null | Key | Default | Extra |
| ----- | ----------- | ------------- | ---- | --- | ------- | -------------- |
| id | | int unsigned | NO | PRI | NULL | auto_increment |
| cat | | varbinary(50) | NO | | | |
| k | | varbinary(50) | NO | | | |
| v | | mediumtext | YES | | NULL | |
Indexes
------------
| Name | Fields |
| ------- | -------------- |
| PRIMARY | id |
| cat_k | UNIQUE, cat, k |
Return to [database documentation](help/database)

View file

@ -296,8 +296,7 @@ class App
*/
public function getBasePath(): string
{
// Don't use the basepath of the config table for basepath (it should always be the config-file one)
return $this->config->getCache()->get('system', 'basepath');
return $this->config->get('system', 'basepath');
}
/**

View file

@ -149,16 +149,7 @@ class Mode
$mode |= Mode::DBAVAILABLE;
if ($database->fetchFirst("SHOW TABLES LIKE 'config'") === false) {
return new Mode($mode);
}
$mode |= Mode::DBCONFIGAVAILABLE;
if (!empty($configCache->get('system', 'maintenance')) ||
// Don't use Config or Configuration here because we're possibly BEFORE initializing the Configuration,
// so this could lead to a dependency circle
!empty($database->selectFirst('config', ['v'], ['cat' => 'system', 'k' => 'maintenance'])['v'])) {
if (!empty($configCache->get('system', 'maintenance'))) {
return new Mode($mode);
}
@ -232,14 +223,14 @@ class Mode
}
/**
* Install mode is when the local config file is missing or the DB schema hasn't been installed yet.
* Install mode is when the local config file is missing or the database isn't available.
*
* @return bool Whether installation mode is active (local/database configuration files present or not)
*/
public function isInstall(): bool
{
return !$this->has(Mode::LOCALCONFIGPRESENT) ||
!$this->has(MODE::DBCONFIGAVAILABLE);
!$this->has(MODE::DBAVAILABLE);
}
/**
@ -251,7 +242,6 @@ class Mode
{
return $this->has(Mode::LOCALCONFIGPRESENT) &&
$this->has(Mode::DBAVAILABLE) &&
$this->has(Mode::DBCONFIGAVAILABLE) &&
$this->has(Mode::MAINTENANCEDISABLED);
}

View file

@ -99,7 +99,7 @@ HELP;
$this->out('Options: ' . var_export($this->options, true));
}
if (!$this->appMode->has(App\Mode::DBCONFIGAVAILABLE)) {
if (!$this->appMode->has(App\Mode::DBAVAILABLE)) {
$this->out('Database isn\'t ready or populated yet, database cache won\'t be available');
}

View file

@ -115,10 +115,6 @@ HELP;
throw new CommandArgsException('Too many arguments');
}
if (!$this->appMode->has(App\Mode::DBCONFIGAVAILABLE)) {
$this->out('Database isn\'t ready or populated yet, showing file config only');
}
if (count($this->args) == 3) {
$cat = $this->getArgument(0);
$key = $this->getArgument(1);
@ -157,7 +153,7 @@ HELP;
if (count($this->args) == 1) {
$cat = $this->getArgument(0);
$this->config->load($cat);
$this->config->reload();
$configCache = $this->config->getCache();
if ($configCache->get($cat) !== null) {
@ -178,11 +174,7 @@ HELP;
}
if (count($this->args) == 0) {
$this->config->load();
if ($this->config->get('system', 'config_adapter') == 'jit' && $this->appMode->has(App\Mode::DBCONFIGAVAILABLE)) {
$this->out('Warning: The JIT (Just In Time) Config adapter doesn\'t support loading the entire configuration, showing file config only');
}
$this->config->reload();
$config = $this->config->getCache()->getAll();
foreach ($config as $cat => $section) {

View file

@ -93,7 +93,7 @@ HELP;
$this->out('Options: ' . var_export($this->options, true));
}
if (!$this->appMode->has(App\Mode::DBCONFIGAVAILABLE)) {
if (!$this->appMode->has(App\Mode::DBAVAILABLE)) {
$this->out('Database isn\'t ready or populated yet, database cache won\'t be available');
}

View file

@ -100,16 +100,20 @@ HELP;
$enabled = intval($this->getArgument(0));
$this->config->set('system', 'maintenance', $enabled);
$transactionConfig = $this->config->beginTransaction();
$transactionConfig->set('system', 'maintenance', $enabled);
$reason = $this->getArgument(1);
if ($enabled && $this->getArgument(1)) {
$this->config->set('system', 'maintenance_reason', $this->getArgument(1));
$transactionConfig->set('system', 'maintenance_reason', $this->getArgument(1));
} else {
$this->config->set('system', 'maintenance_reason', '');
$transactionConfig->delete('system', 'maintenance_reason');
}
$transactionConfig->commit();
if ($enabled) {
$mode_str = "maintenance mode";
} else {

View file

@ -101,9 +101,10 @@ HELP;
$old_host = str_replace('http://', '@', Strings::normaliseLink($old_url));
$this->out('Entering maintenance mode');
$this->config->set('system', 'maintenance', true);
$this->config->set('system', 'maintenance_reason', 'Relocating node to ' . $new_url);
$this->config->beginTransaction()
->set('system', 'maintenance', true)
->set('system', 'maintenance_reason', 'Relocating node to ' . $new_url)
->commit();
try {
if (!$this->database->transaction()) {
throw new \Exception('Unable to start a transaction, please retry later.');
@ -189,8 +190,10 @@ HELP;
return 1;
} finally {
$this->out('Leaving maintenance mode');
$this->config->set('system', 'maintenance', false);
$this->config->set('system', 'maintenance_reason', '');
$this->config->beginTransaction()
->set('system', 'maintenance', false)
->delete('system', 'maintenance_reason')
->commit();
}
// send relocate

View file

@ -22,6 +22,7 @@
namespace Friendica\Core\Config\Capability;
use Friendica\Core\Config\Exception\ConfigPersistenceException;
use Friendica\Core\Config\Util\ConfigFileManager;
use Friendica\Core\Config\ValueObject\Cache;
/**
@ -30,36 +31,46 @@ use Friendica\Core\Config\ValueObject\Cache;
interface IManageConfigValues
{
/**
* Loads all configuration values of family into a cached storage.
* Reloads all configuration values (from filesystem and environment variables)
*
* All configuration values of the system are stored in the cache.
*
* @param string $cat The category of the configuration value
*
* @return void
*
* @throws ConfigPersistenceException In case the persistence layer throws errors
*/
public function load(string $cat = 'config');
public function reload();
/**
* Get a particular user's config variable given the category name
* ($cat) and a $key.
*
* Get a particular config value from the given category ($cat)
* and the $key from a cached storage either from the database or from the cache.
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to query
* @param mixed $default_value Deprecated, use `Config->get($cat, $key, null, $refresh) ?? $default_value` instead
* @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false)
*
* @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, $default_value = null, bool $refresh = false);
public function get(string $cat, string $key, $default_value = null);
/**
* 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 load(Cache $cache);
/**
* Sets a configuration value for system config
@ -78,6 +89,15 @@ interface IManageConfigValues
*/
public function set(string $cat, string $key, $value): bool;
/**
* Creates a transactional config value store, which is used to set a bunch of values at once
*
* It relies on the current instance, so after save(), the values of this config class will get altered at once too.
*
* @return ISetConfigValuesTransactionally
*/
public function beginTransaction(): ISetConfigValuesTransactionally;
/**
* Deletes the given key from the system configuration.
*

View file

@ -0,0 +1,68 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core\Config\Capability;
use Friendica\Core\Config\Exception\ConfigPersistenceException;
/**
* Interface for transactional saving of config values
* It buffers every set/delete until "save()" is called
*/
interface ISetConfigValuesTransactionally
{
/**
* Sets a configuration value for system config
*
* Stores a config value ($value) in the category ($cat) under the key ($key)
*
* Note: Please do not store booleans - convert to 0/1 integer values!
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to set
* @param mixed $value The value to store
*
* @return static the current instance
*
* @throws ConfigPersistenceException In case the persistence layer throws errors
*/
public function set(string $cat, string $key, $value): self;
/**
* Deletes the given key from the system configuration.
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to delete
*
* @return static the current instance
*
* @throws ConfigPersistenceException In case the persistence layer throws errors
*
*/
public function delete(string $cat, string $key): self;
/**
* Commits the changes of the current transaction
*
* @throws ConfigPersistenceException In case the persistence layer throws errors
*/
public function commit(): void;
}

View file

@ -21,12 +21,12 @@
namespace Friendica\Core\Config\Factory;
use Friendica\Core\Config\Capability;
use Friendica\Core\Config\Repository;
use Friendica\Core\Config\Type;
use Friendica\Core\Config\Util;
use Friendica\Core\Config\ValueObject\Cache;
/**
* The config factory for creating either the cache or the whole model
*/
class Config
{
/**
@ -54,9 +54,9 @@ class Config
* @param string $basePath The basepath of FRIENDICA
* @param array $server The $_SERVER array
*
* @return Util\ConfigFileLoader
* @return Util\ConfigFileManager
*/
public function createConfigFileLoader(string $basePath, array $server = []): Util\ConfigFileLoader
public function createConfigFileLoader(string $basePath, array $server = []): Util\ConfigFileManager
{
if (!empty($server[self::CONFIG_DIR_ENV]) && is_dir($server[self::CONFIG_DIR_ENV])) {
$configDir = $server[self::CONFIG_DIR_ENV];
@ -65,37 +65,20 @@ class Config
}
$staticDir = $basePath . DIRECTORY_SEPARATOR . self::STATIC_DIR;
return new Util\ConfigFileLoader($basePath, $configDir, $staticDir);
return new Util\ConfigFileManager($basePath, $configDir, $staticDir, new Util\ConfigFileTransformer());
}
/**
* @param Util\ConfigFileLoader $loader The Config Cache loader (INI/config/.htconfig)
* @param array $server
* @param Util\ConfigFileManager $configFileManager The Config Cache manager (INI/config/.htconfig)
* @param array $server
*
* @return Cache
*/
public function createCache(Util\ConfigFileLoader $loader, array $server = []): Cache
public function createCache(Util\ConfigFileManager $configFileManager, array $server = []): Cache
{
$configCache = new Cache();
$loader->setupCache($configCache, $server);
$configFileManager->setupCache($configCache, $server);
return $configCache;
}
/**
* @param Cache $configCache The config cache of this adapter
* @param Repository\Config $configRepo The configuration repository
*
* @return Capability\IManageConfigValues
*/
public function create(Cache $configCache, Repository\Config $configRepo)
{
if ($configCache->get('system', 'config_adapter') === 'preload') {
$configuration = new Type\PreloadConfig($configCache, $configRepo);
} else {
$configuration = new Type\JitConfig($configCache, $configRepo);
}
return $configuration;
}
}

View file

@ -0,0 +1,131 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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;
/** @var array */
protected $server;
/**
* @param ConfigFileManager $configFileManager The configuration file manager to save back configs
* @param Cache $configCache The configuration cache (based on the config-files)
* @param array $server The $_SERVER variable
*/
public function __construct(ConfigFileManager $configFileManager, Cache $configCache, array $server = [])
{
$this->configFileManager = $configFileManager;
$this->configCache = $configCache;
$this->server = $server;
}
/**
* {@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);
} catch (ConfigFileException $e) {
throw new ConfigPersistenceException('Cannot save config', $e);
}
}
/** {@inheritDoc} */
public function reload()
{
$configCache = new Cache();
try {
$this->configFileManager->setupCache($configCache, $this->server);
} catch (ConfigFileException $e) {
throw new ConfigPersistenceException('Cannot reload config', $e);
}
$this->configCache = $configCache;
}
/** {@inheritDoc} */
public function load(Cache $cache)
{
$this->configCache = $cache;
$this->save();
}
/** {@inheritDoc} */
public function get(string $cat, string $key, $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;
}
}
}

View file

@ -0,0 +1,102 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
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;
/**
* Transaction class for configurations, which sets values into a temporary buffer until "save()" is called
*/
class ConfigTransaction implements ISetConfigValuesTransactionally
{
/** @var IManageConfigValues */
protected $config;
/** @var Cache */
protected $cache;
/** @var Cache */
protected $delCache;
public function __construct(IManageConfigValues $config)
{
$this->config = $config;
$this->cache = new Cache();
$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} */
public function set(string $cat, string $key, $value): ISetConfigValuesTransactionally
{
$this->cache->set($cat, $key, $value, Cache::SOURCE_DATA);
return $this;
}
/** {@inheritDoc} */
public function delete(string $cat, string $key): ISetConfigValuesTransactionally
{
$this->cache->delete($cat, $key);
$this->delCache->set($cat, $key, 'deleted');
return $this;
}
/** {@inheritDoc} */
public function commit(): void
{
try {
$newCache = $this->config->getCache()->merge($this->cache);
$newCache = $newCache->diff($this->delCache);
$this->config->load($newCache);
// flush current cache
$this->cache = new Cache();
$this->delCache = new Cache();
} catch (\Exception $e) {
throw new ConfigPersistenceException('Cannot save config', $e);
}
}
}

View file

@ -1,191 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core\Config\Repository;
use Friendica\App\Mode;
use Friendica\Core\Config\Exception\ConfigPersistenceException;
use Friendica\Core\Config\Util\ValueConversion;
use Friendica\Database\Database;
/**
* The Config Repository, which is using the general DB-model backend for configs
*/
class Config
{
/** @var Database */
protected $db;
/** @var Mode */
protected $mode;
public function __construct(Database $db, Mode $mode)
{
$this->db = $db;
$this->mode = $mode;
}
protected static $table_name = 'config';
/**
* Checks if the model is currently connected
*
* @return bool
*/
public function isConnected(): bool
{
return $this->db->isConnected() && !$this->mode->isInstall();
}
/**
* Loads all configuration values and returns the loaded category as an array.
*
* @param string|null $cat The category of the configuration values to load
*
* @return array The config array
*
* @throws ConfigPersistenceException In case the persistence layer throws errors
*/
public function load(?string $cat = null): array
{
$return = [];
try {
if (empty($cat)) {
$configs = $this->db->select(static::$table_name, ['cat', 'v', 'k']);
} else {
$configs = $this->db->select(static::$table_name, ['cat', 'v', 'k'], ['cat' => $cat]);
}
while ($config = $this->db->fetch($configs)) {
$key = $config['k'];
$value = ValueConversion::toConfigValue($config['v']);
// just save it in case it is set
if (isset($value)) {
$return[$config['cat']][$key] = $value;
}
}
} catch (\Exception $exception) {
throw new ConfigPersistenceException(sprintf('Cannot load config category %s', $cat), $exception);
} finally {
$this->db->close($configs);
}
return $return;
}
/**
* Get a particular, system-wide config variable out of the DB with the
* given category name ($cat) and a key ($key).
*
* Note: Boolean variables are defined as 0/1 in the database
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to query
*
* @return array|string|null Stored value or null if it does not exist
*
* @throws ConfigPersistenceException In case the persistence layer throws errors
*/
public function get(string $cat, string $key)
{
if (!$this->isConnected()) {
return null;
}
try {
$config = $this->db->selectFirst(static::$table_name, ['v'], ['cat' => $cat, 'k' => $key]);
if ($this->db->isResult($config)) {
$value = ValueConversion::toConfigValue($config['v']);
// just return it in case it is set
if (isset($value)) {
return $value;
}
}
} catch (\Exception $exception) {
throw new ConfigPersistenceException(sprintf('Cannot get config with category %s and key %s', $cat, $key), $exception);
}
return null;
}
/**
* Stores a config value ($value) in the category ($cat) under the key ($key).
*
* Note: Please do not store booleans - convert to 0/1 integer values!
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to set
* @param mixed $value The value to store
*
* @return bool Operation success
*
* @throws ConfigPersistenceException In case the persistence layer throws errors
*/
public function set(string $cat, string $key, $value): bool
{
if (!$this->isConnected()) {
return false;
}
// We store our setting values in a string variable.
// So we have to do the conversion here so that the compare below works.
// The exception are array values.
$compare_value = (!is_array($value) ? (string)$value : $value);
$stored_value = $this->get($cat, $key);
if (isset($stored_value) && ($stored_value === $compare_value)) {
return true;
}
$dbValue = ValueConversion::toDbValue($value);
try {
return $this->db->update(static::$table_name, ['v' => $dbValue], ['cat' => $cat, 'k' => $key], true);
} catch (\Exception $exception) {
throw new ConfigPersistenceException(sprintf('Cannot set config with category %s and key %s', $cat, $key), $exception);
}
}
/**
* Removes the configured value from the database.
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to delete
*
* @return bool Operation success
*
* @throws ConfigPersistenceException In case the persistence layer throws errors
*/
public function delete(string $cat, string $key): bool
{
if (!$this->isConnected()) {
return false;
}
try {
return $this->db->delete(static::$table_name, ['cat' => $cat, 'k' => $key]);
} catch (\Exception $exception) {
throw new ConfigPersistenceException(sprintf('Cannot delete config with category %s and key %s', $cat, $key), $exception);
}
}
}

View file

@ -1,63 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core\Config\Type;
use Friendica\Core\Config\Repository\Config;
use Friendica\Core\Config\ValueObject\Cache;
use Friendica\Core\Config\Capability\IManageConfigValues;
/**
* This class is responsible for all system-wide configuration values in Friendica
* There are two types of storage
* - The Config-Files (loaded into the FileCache @see Cache)
* - The Config-Repository (per Config-Repository @see Config )
*/
abstract class AbstractConfig implements IManageConfigValues
{
/**
* @var Cache
*/
protected $configCache;
/**
* @var Config
*/
protected $configRepo;
/**
* @param Cache $configCache The configuration cache (based on the config-files)
* @param Config $configRepo The configuration repository
*/
public function __construct(Cache $configCache, Config $configRepo)
{
$this->configCache = $configCache;
$this->configRepo = $configRepo;
}
/**
* {@inheritDoc}
*/
public function getCache(): Cache
{
return $this->configCache;
}
}

View file

@ -1,139 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core\Config\Type;
use Friendica\Core\Config\ValueObject\Cache;
use Friendica\Core\Config\Repository\Config;
/**
* This class implements the Just-In-Time configuration, which will cache
* config values in a cache, once they are retrieved.
*
* Default Configuration type.
* Provides the best performance for pages loading few configuration variables.
*/
class JitConfig extends AbstractConfig
{
/**
* @var array Array of already loaded db values (even if there was no value)
*/
private $db_loaded;
/**
* @param Cache $configCache The configuration cache (based on the config-files)
* @param Config $configRepo The configuration model
*/
public function __construct(Cache $configCache, Config $configRepo)
{
parent::__construct($configCache, $configRepo);
$this->db_loaded = [];
$this->load();
}
/**
* {@inheritDoc}
*/
public function load(string $cat = 'config')
{
// If not connected, do nothing
if (!$this->configRepo->isConnected()) {
return;
}
$config = $this->configRepo->load($cat);
if (!empty($config[$cat])) {
foreach ($config[$cat] as $key => $value) {
$this->db_loaded[$cat][$key] = true;
}
}
// load the whole category out of the DB into the cache
$this->configCache->load($config, Cache::SOURCE_DB);
}
/**
* {@inheritDoc}
*/
public function get(string $cat, string $key, $default_value = null, bool $refresh = false)
{
// if the value isn't loaded or refresh is needed, load it to the cache
if ($this->configRepo->isConnected() &&
(empty($this->db_loaded[$cat][$key]) ||
$refresh)) {
$dbValue = $this->configRepo->get($cat, $key);
if (isset($dbValue)) {
$this->configCache->set($cat, $key, $dbValue, Cache::SOURCE_DB);
unset($dbValue);
}
$this->db_loaded[$cat][$key] = true;
}
// use the config cache for return
$result = $this->configCache->get($cat, $key);
return (isset($result)) ? $result : $default_value;
}
/**
* {@inheritDoc}
*/
public function set(string $cat, string $key, $value): bool
{
// set the cache first
$cached = $this->configCache->set($cat, $key, $value, Cache::SOURCE_DB);
// If there is no connected adapter, we're finished
if (!$this->configRepo->isConnected()) {
return $cached;
}
$stored = $this->configRepo->set($cat, $key, $value);
$this->db_loaded[$cat][$key] = $stored;
return $cached && $stored;
}
/**
* {@inheritDoc}
*/
public function delete(string $cat, string $key): bool
{
$cacheRemoved = $this->configCache->delete($cat, $key);
if (isset($this->db_loaded[$cat][$key])) {
unset($this->db_loaded[$cat][$key]);
}
if (!$this->configRepo->isConnected()) {
return $cacheRemoved;
}
$storeRemoved = $this->configRepo->delete($cat, $key);
return $cacheRemoved || $storeRemoved;
}
}

View file

@ -1,135 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core\Config\Type;
use Friendica\Core\Config\ValueObject\Cache;
use Friendica\Core\Config\Repository\Config;
/**
* This class implements the preload configuration, which will cache
* all config values per call in a cache.
*
* Minimizes the number of database queries to retrieve configuration values at the cost of memory.
*/
class PreloadConfig extends AbstractConfig
{
/** @var bool */
private $config_loaded;
/**
* @param Cache $configCache The configuration cache (based on the config-files)
* @param Config $configRepo The configuration model
*/
public function __construct(Cache $configCache, Config $configRepo)
{
parent::__construct($configCache, $configRepo);
$this->config_loaded = false;
$this->load();
}
/**
* {@inheritDoc}
*
* This loads all config values everytime load is called
*/
public function load(string $cat = 'config')
{
// Don't load the whole configuration twice
if ($this->config_loaded) {
return;
}
// If not connected, do nothing
if (!$this->configRepo->isConnected()) {
return;
}
$config = $this->configRepo->load();
$this->config_loaded = true;
// load the whole category out of the DB into the cache
$this->configCache->load($config, Cache::SOURCE_DB);
}
/**
* {@inheritDoc}
*/
public function get(string $cat, string $key, $default_value = null, bool $refresh = false)
{
if ($refresh) {
if ($this->configRepo->isConnected()) {
$config = $this->configRepo->get($cat, $key);
if (isset($config)) {
$this->configCache->set($cat, $key, $config, Cache::SOURCE_DB);
}
}
}
// use the config cache for return
$result = $this->configCache->get($cat, $key);
return (isset($result)) ? $result : $default_value;
}
/**
* {@inheritDoc}
*/
public function set(string $cat, string $key, $value): bool
{
if (!$this->config_loaded) {
$this->load();
}
// set the cache first
$cached = $this->configCache->set($cat, $key, $value, Cache::SOURCE_DB);
// If there is no connected adapter, we're finished
if (!$this->configRepo->isConnected()) {
return $cached;
}
$stored = $this->configRepo->set($cat, $key, $value);
return $cached && $stored;
}
/**
* {@inheritDoc}
*/
public function delete(string $cat, string $key): bool
{
if ($this->config_loaded) {
$this->load();
}
$cacheRemoved = $this->configCache->delete($cat, $key);
if (!$this->configRepo->isConnected()) {
return $cacheRemoved;
}
$storeRemoved = $this->configRepo->delete($cat, $key);
return $cacheRemoved || $storeRemoved;
}
}

View file

@ -26,22 +26,15 @@ use Friendica\Core\Config\Exception\ConfigFileException;
use Friendica\Core\Config\ValueObject\Cache;
/**
* The ConfigFileLoader loads config-files and stores them in a ConfigCache ( @see Cache )
* The ConfigFileLoader loads and saves config-files and stores them in a ConfigCache ( @see Cache )
*
* It is capable of loading the following config files:
* - *.config.php (current)
* - *.ini.php (deprecated)
* - *.htconfig.php (deprecated)
*/
class ConfigFileLoader
class ConfigFileManager
{
/**
* The default name of the user defined ini file
*
* @var string
*/
const CONFIG_INI = 'local';
/**
* The default name of the user defined legacy config file
*
@ -49,6 +42,13 @@ class ConfigFileLoader
*/
const CONFIG_HTCONFIG = 'htconfig';
/**
* The config file, where overrides per admin page/console are saved at
*
* @var string
*/
const CONFIG_DATA_FILE = 'node.config.php';
/**
* The sample string inside the configs, which shouldn't get loaded
*
@ -89,7 +89,7 @@ class ConfigFileLoader
*
* @param Cache $config The config cache to load to
* @param array $server The $_SERVER array
* @param bool $raw Setup the raw config format
* @param bool $raw Set up the raw config format
*
* @throws ConfigFileException
*/
@ -106,6 +106,9 @@ class ConfigFileLoader
// Now load every other config you find inside the 'config/' directory
$this->loadCoreConfig($config);
// Now load the node.config.php file with the node specific config values (based on admin gui/console actions)
$this->loadDataConfig($config);
$config->load($this->loadEnvConfig($server), Cache::SOURCE_ENV);
// In case of install mode, add the found basepath (because there isn't a basepath set yet
@ -158,6 +161,50 @@ class ConfigFileLoader
}
}
/**
* Tries to load the data config file with the overridden data
*
* @param Cache $config The Config cache
*
* @throws ConfigFileException In case the config file isn't loadable
*/
private function loadDataConfig(Cache $config)
{
$filename = $this->configDir . '/' . self::CONFIG_DATA_FILE;
if (file_exists($filename)) {
$dataArray = include $filename;
if (!is_array($dataArray)) {
throw new ConfigFileException(sprintf('Error loading config file %s', $filename));
}
$config->load($dataArray, Cache::SOURCE_DATA);
}
}
/**
* Saves overridden config entries back into the data.config.phpR
*
* @param Cache $config The config cache
*
* @throws ConfigFileException In case the config file isn't writeable or the data is invalid
*/
public function saveData(Cache $config)
{
$data = $config->getDataBySource(Cache::SOURCE_DATA);
$encodedData = ConfigFileTransformer::encode($data);
if (!$encodedData) {
throw new ConfigFileException('config source cannot get encoded');
}
if (!file_put_contents($this->configDir . '/' . self::CONFIG_DATA_FILE, $encodedData)) {
throw new ConfigFileException(sprintf('Cannot save data to file %s/%s', $this->configDir, self::CONFIG_DATA_FILE));
}
}
/**
* Tries to load the specified addon-configuration and returns the config array.
*
@ -353,12 +400,16 @@ class ConfigFileLoader
*/
private function loadConfigFile(string $filepath): array
{
$config = include($filepath);
if (file_exists($filepath)) {
$config = include $filepath;
if (!is_array($config)) {
throw new ConfigFileException('Error loading config file ' . $filepath);
if (!is_array($config)) {
throw new ConfigFileException('Error loading config file ' . $filepath);
}
return $config;
} else {
return [];
}
return $config;
}
}

View file

@ -0,0 +1,85 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core\Config\Util;
/**
* Util to transform back the config array into a string
*/
class ConfigFileTransformer
{
public static function encode(array $data): string
{
$dataString = '<?php' . PHP_EOL . PHP_EOL;
$dataString .= 'return [' . PHP_EOL;
$categories = array_keys($data);
foreach ($categories as $category) {
$dataString .= "\t'$category' => [" . PHP_EOL;
if (is_array($data[$category])) {
$keys = array_keys($data[$category]);
foreach ($keys as $key) {
$dataString .= static::mapConfigValue($key, $data[$category][$key]);
}
}
$dataString .= "\t]," . PHP_EOL;
}
$dataString .= "];" . PHP_EOL;
return $dataString;
}
protected static function extractArray(array $config, int $level = 0): string
{
$string = '';
foreach ($config as $configKey => $configValue) {
$string .= static::mapConfigValue($configKey, $configValue, $level);
}
return $string;
}
protected static function mapConfigValue(string $key, $value, $level = 0): string
{
$string = str_repeat("\t", $level + 2) . "'$key' => ";
if (is_array($value)) {
$string .= "[" . PHP_EOL;
$string .= static::extractArray($value, ++$level);
$string .= str_repeat("\t", $level + 1) . '],';
} elseif (is_bool($value)) {
$string .= ($value ? 'true' : 'false') . ",";
} elseif (is_numeric($value)) {
$string .= $value . ",";
} else {
$string .= sprintf('\'%s\',', addcslashes($value, '\'\\'));
}
$string .= PHP_EOL;
return $string;
}
}

View file

@ -21,13 +21,13 @@
namespace Friendica\Core\Config\ValueObject;
use Friendica\Core\Config\Util\ConfigFileLoader;
use Friendica\Core\Config\Util\ConfigFileManager;
use ParagonIE\HiddenString\HiddenString;
/**
* The Friendica config cache for the application
* Initial, all *.config.php files are loaded into this cache with the
* ConfigFileLoader ( @see ConfigFileLoader )
* ConfigFileManager ( @see ConfigFileManager )
*/
class Cache
{
@ -35,8 +35,8 @@ class Cache
const SOURCE_STATIC = 0;
/** @var int Indicates that the cache entry is set by file - Low Priority */
const SOURCE_FILE = 1;
/** @var int Indicates that the cache entry is set by the DB config table - Middle Priority */
const SOURCE_DB = 2;
/** @var int Indicates that the cache entry is manually set by the application (per admin page/console) - Middle Priority */
const SOURCE_DATA = 2;
/** @var int Indicates that the cache entry is set by a server environment variable - High Priority */
const SOURCE_ENV = 3;
/** @var int Indicates that the cache entry is fixed and must not be changed */
@ -128,6 +128,34 @@ class Cache
return $this->source[$cat][$key] ?? -1;
}
/**
* Returns the whole config array based on the given source type
*
* @param int $source Indicates the source of the config entry
*
* @return array The config array part of the given source
*/
public function getDataBySource(int $source): array
{
$data = [];
$categories = array_keys($this->source);
foreach ($categories as $category) {
if (is_array($this->source[$category])) {
$keys = array_keys($this->source[$category]);
foreach ($keys as $key) {
if ($this->source[$category][$key] === $source) {
$data[$category][$key] = $this->config[$category][$key];
}
}
}
}
return $data;
}
/**
* Sets a value in the config cache. Accepts raw output from the config table
*
@ -154,6 +182,8 @@ class Cache
$key == 'password' &&
is_string($value)) {
$this->config[$cat][$key] = new HiddenString((string)$value);
} else if (is_string($value)) {
$this->config[$cat][$key] = self::toConfigValue($value);
} else {
$this->config[$cat][$key] = $value;
}
@ -163,6 +193,32 @@ class Cache
return true;
}
/**
* Formats a DB value to a config value
* - null = The db-value isn't set
* - bool = The db-value is either '0' or '1'
* - array = The db-value is a serialized array
* - string = The db-value is a string
*
* Keep in mind that there aren't any numeric/integer config values in the database
*
* @param string|null $value
*
* @return null|array|string
*/
public static function toConfigValue(?string $value)
{
if (!isset($value)) {
return null;
}
if (preg_match("|^a:[0-9]+:{.*}$|s", $value)) {
return unserialize($value);
} else {
return $value;
}
}
/**
* Deletes a value from the config cache.
*
@ -223,4 +279,69 @@ class Cache
return $return;
}
/**
* Merges a new Cache into the existing one and returns the merged Cache
*
* @param Cache $cache The cache, which should get merged into this Cache
*
* @return Cache The merged Cache
*/
public function merge(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) {
$newConfig[$category][$key] = $cache->config[$category][$key];
$newSource[$category][$key] = $cache->source[$category][$key];
}
}
}
$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]);
}
}
}
$newCache = new Cache();
$newCache->config = $newConfig;
$newCache->source = $newSource;
return $newCache;
}
}

View file

@ -21,7 +21,7 @@
namespace Friendica\Core\KeyValueStorage\Type;
use Friendica\Core\Config\Util\ValueConversion;
use Friendica\Core\PConfig\Util\ValueConversion;
use Friendica\Core\KeyValueStorage\Exceptions\KeyValueStoragePersistenceException;
use Friendica\Database\Database;

View file

@ -22,7 +22,7 @@
namespace Friendica\Core\PConfig\Repository;
use Friendica\App\Mode;
use Friendica\Core\Config\Util\ValueConversion;
use Friendica\Core\PConfig\Util\ValueConversion;
use Friendica\Core\PConfig\Exception\PConfigPersistenceException;
use Friendica\Database\Database;

View file

@ -19,7 +19,7 @@
*
*/
namespace Friendica\Core\Config\Util;
namespace Friendica\Core\PConfig\Util;
/**
* Util class to help to convert from/to (p)config values

View file

@ -54,7 +54,7 @@ class Update
}
// Don't check the status if the last update was failed
if (DI::config()->get('system', 'update', Update::SUCCESS, true) == Update::FAILED) {
if (DI::config()->get('system', 'update', Update::SUCCESS) == Update::FAILED) {
return;
}
@ -119,7 +119,7 @@ class Update
DI::lock()->release('dbupdate', true);
}
$build = DI::config()->get('system', 'build', null, true);
$build = DI::config()->get('system', 'build', null);
if (empty($build) || ($build > DB_UPDATE_VERSION)) {
$build = DB_UPDATE_VERSION - 1;
@ -132,7 +132,7 @@ class Update
$stored = intval($build);
$current = intval(DB_UPDATE_VERSION);
if ($stored < $current || $force) {
DI::config()->load('database');
DI::config()->reload();
// Compare the current structure with the defined structure
// If the Lock is acquired, never release it automatically to avoid double updates
@ -141,7 +141,7 @@ class Update
Logger::notice('Update starting.', ['from' => $stored, 'to' => $current]);
// Checks if the build changed during Lock acquiring (so no double update occurs)
$retryBuild = DI::config()->get('system', 'build', null, true);
$retryBuild = DI::config()->get('system', 'build', null);
if ($retryBuild !== $build) {
Logger::notice('Update already done.', ['from' => $stored, 'to' => $current]);
DI::lock()->release('dbupdate');
@ -160,8 +160,10 @@ class Update
Logger::warning('Pre update failed', ['version' => $version]);
DI::config()->set('system', 'update', Update::FAILED);
DI::lock()->release('dbupdate');
DI::config()->set('system', 'maintenance', 0);
DI::config()->set('system', 'maintenance_reason', '');
DI::config()->beginTransaction()
->set('system', 'maintenance', false)
->delete('system', 'maintenance_reason')
->commit();
return $r;
} else {
Logger::notice('Pre update executed.', ['version' => $version]);
@ -181,8 +183,10 @@ class Update
Logger::error('Update ERROR.', ['from' => $stored, 'to' => $current, 'retval' => $retval]);
DI::config()->set('system', 'update', Update::FAILED);
DI::lock()->release('dbupdate');
DI::config()->set('system', 'maintenance', 0);
DI::config()->set('system', 'maintenance_reason', '');
DI::config()->beginTransaction()
->set('system', 'maintenance', false)
->delete('system', 'maintenance_reason')
->commit();
return $retval;
} else {
Logger::notice('Database structure update finished.', ['from' => $stored, 'to' => $current]);
@ -198,8 +202,10 @@ class Update
Logger::warning('Post update failed', ['version' => $version]);
DI::config()->set('system', 'update', Update::FAILED);
DI::lock()->release('dbupdate');
DI::config()->set('system', 'maintenance', 0);
DI::config()->set('system', 'maintenance_reason', '');
DI::config()->beginTransaction()
->set('system', 'maintenance', false)
->delete('system', 'maintenance_reason')
->commit();
return $r;
} else {
DI::config()->set('system', 'build', $version);
@ -210,8 +216,10 @@ class Update
DI::config()->set('system', 'build', $current);
DI::config()->set('system', 'update', Update::SUCCESS);
DI::lock()->release('dbupdate');
DI::config()->set('system', 'maintenance', 0);
DI::config()->set('system', 'maintenance_reason', '');
DI::config()->beginTransaction()
->set('system', 'maintenance', false)
->delete('system', 'maintenance_reason')
->commit();
Logger::notice('Update success.', ['from' => $stored, 'to' => $current]);
if ($sendMail) {

View file

@ -331,7 +331,7 @@ class Worker
$mypid = getmypid();
// Quit when in maintenance
if (DI::config()->get('system', 'maintenance', false, true)) {
if (DI::config()->get('system', 'maintenance', false)) {
Logger::notice('Maintenance mode - quit process', ['pid' => $mypid]);
return false;
}

View file

@ -74,7 +74,7 @@ class DBStructure
$old_tables = ['fserver', 'gcign', 'gcontact', 'gcontact-relation', 'gfollower' ,'glink', 'item-delivery-data',
'item-activity', 'item-content', 'item_id', 'participation', 'poll', 'poll_result', 'queue', 'retriever_rule',
'deliverq', 'dsprphotoq', 'ffinder', 'sign', 'spam', 'term', 'user-item', 'thread', 'item', 'challenge',
'auth_codes', 'tokens', 'clients', 'profile_check', 'host', 'conversation', 'fcontact'];
'auth_codes', 'tokens', 'clients', 'profile_check', 'host', 'conversation', 'fcontact', 'config'];
$tables = DBA::selectToArray('INFORMATION_SCHEMA.TABLES', ['TABLE_NAME'],
['TABLE_SCHEMA' => DBA::databaseName(), 'TABLE_TYPE' => 'BASE TABLE']);
@ -176,14 +176,16 @@ class DBStructure
public static function performUpdate(bool $enable_maintenance_mode = true, bool $verbose = false): string
{
if ($enable_maintenance_mode) {
DI::config()->set('system', 'maintenance', 1);
DI::config()->set('system', 'maintenance', true);
}
$status = self::update($verbose, true);
if ($enable_maintenance_mode) {
DI::config()->set('system', 'maintenance', 0);
DI::config()->set('system', 'maintenance_reason', '');
DI::config()->beginTransaction()
->set('system', 'maintenance', false)
->delete('system', 'maintenance_reason')
->commit();
}
return $status;

View file

@ -48,8 +48,6 @@ class Site extends BaseAdmin
self::checkFormSecurityTokenRedirectOnError('/admin/site', 'admin_site');
$a = DI::app();
if (!empty($_POST['republish_directory'])) {
Worker::add(Worker::PRIORITY_LOW, 'Directory');
return;
@ -146,9 +144,11 @@ class Site extends BaseAdmin
$relay_user_tags = !empty($_POST['relay_user_tags']);
$active_panel = (!empty($_POST['active_panel']) ? "#" . trim($_POST['active_panel']) : '');
$transactionConfig = DI::config()->beginTransaction();
// Has the directory url changed? If yes, then resubmit the existing profiles there
if ($global_directory != DI::config()->get('system', 'directory') && ($global_directory != '')) {
DI::config()->set('system', 'directory', $global_directory);
$transactionConfig->set('system', 'directory', $global_directory);
Worker::add(Worker::PRIORITY_LOW, 'Directory');
}
@ -194,131 +194,133 @@ class Site extends BaseAdmin
);
}
}
DI::config()->set('system', 'ssl_policy' , $ssl_policy);
DI::config()->set('system', 'maxloadavg' , $maxloadavg);
DI::config()->set('system', 'min_memory' , $min_memory);
DI::config()->set('system', 'optimize_tables' , $optimize_tables);
DI::config()->set('system', 'contact_discovery' , $contact_discovery);
DI::config()->set('system', 'synchronize_directory' , $synchronize_directory);
DI::config()->set('system', 'poco_requery_days' , $poco_requery_days);
DI::config()->set('system', 'poco_discovery' , $poco_discovery);
DI::config()->set('system', 'poco_local_search' , $poco_local_search);
DI::config()->set('system', 'nodeinfo' , $nodeinfo);
DI::config()->set('config', 'sitename' , $sitename);
DI::config()->set('config', 'sender_email' , $sender_email);
DI::config()->set('system', 'suppress_tags' , $suppress_tags);
DI::config()->set('system', 'shortcut_icon' , $shortcut_icon);
DI::config()->set('system', 'touch_icon' , $touch_icon);
$transactionConfig->set('system', 'ssl_policy' , $ssl_policy);
$transactionConfig->set('system', 'maxloadavg' , $maxloadavg);
$transactionConfig->set('system', 'min_memory' , $min_memory);
$transactionConfig->set('system', 'optimize_tables' , $optimize_tables);
$transactionConfig->set('system', 'contact_discovery' , $contact_discovery);
$transactionConfig->set('system', 'synchronize_directory' , $synchronize_directory);
$transactionConfig->set('system', 'poco_requery_days' , $poco_requery_days);
$transactionConfig->set('system', 'poco_discovery' , $poco_discovery);
$transactionConfig->set('system', 'poco_local_search' , $poco_local_search);
$transactionConfig->set('system', 'nodeinfo' , $nodeinfo);
$transactionConfig->set('config', 'sitename' , $sitename);
$transactionConfig->set('config', 'sender_email' , $sender_email);
$transactionConfig->set('system', 'suppress_tags' , $suppress_tags);
$transactionConfig->set('system', 'shortcut_icon' , $shortcut_icon);
$transactionConfig->set('system', 'touch_icon' , $touch_icon);
if ($banner == "") {
DI::config()->delete('system', 'banner');
$transactionConfig->delete('system', 'banner');
} else {
DI::config()->set('system', 'banner', $banner);
$transactionConfig->set('system', 'banner', $banner);
}
if (empty($email_banner)) {
DI::config()->delete('system', 'email_banner');
$transactionConfig->delete('system', 'email_banner');
} else {
DI::config()->set('system', 'email_banner', $email_banner);
$transactionConfig->set('system', 'email_banner', $email_banner);
}
if (empty($additional_info)) {
DI::config()->delete('config', 'info');
$transactionConfig->delete('config', 'info');
} else {
DI::config()->set('config', 'info', $additional_info);
$transactionConfig->set('config', 'info', $additional_info);
}
DI::config()->set('system', 'language', $language);
DI::config()->set('system', 'theme', $theme);
$transactionConfig->set('system', 'language', $language);
$transactionConfig->set('system', 'theme', $theme);
Theme::install($theme);
if ($theme_mobile == '---') {
DI::config()->delete('system', 'mobile-theme');
$transactionConfig->delete('system', 'mobile-theme');
} else {
DI::config()->set('system', 'mobile-theme', $theme_mobile);
$transactionConfig->set('system', 'mobile-theme', $theme_mobile);
}
if ($singleuser == '---') {
DI::config()->delete('system', 'singleuser');
$transactionConfig->delete('system', 'singleuser');
} else {
DI::config()->set('system', 'singleuser', $singleuser);
$transactionConfig->set('system', 'singleuser', $singleuser);
}
if (preg_match('/\d+(?:\s*[kmg])?/i', $maximagesize)) {
DI::config()->set('system', 'maximagesize', $maximagesize);
$transactionConfig->set('system', 'maximagesize', $maximagesize);
} else {
DI::sysmsg()->addNotice(DI::l10n()->t('%s is no valid input for maximum image size', $maximagesize));
}
DI::config()->set('system', 'max_image_length' , $maximagelength);
DI::config()->set('system', 'jpeg_quality' , $jpegimagequality);
$transactionConfig->set('system', 'max_image_length' , $maximagelength);
$transactionConfig->set('system', 'jpeg_quality' , $jpegimagequality);
DI::config()->set('config', 'register_policy' , $register_policy);
DI::config()->set('system', 'max_daily_registrations', $daily_registrations);
DI::config()->set('system', 'account_abandon_days' , $abandon_days);
DI::config()->set('config', 'register_text' , $register_text);
DI::config()->set('system', 'allowed_sites' , $allowed_sites);
DI::config()->set('system', 'allowed_email' , $allowed_email);
DI::config()->set('system', 'forbidden_nicknames' , $forbidden_nicknames);
DI::config()->set('system', 'system_actor_name' , $system_actor_name);
DI::config()->set('system', 'no_oembed_rich_content' , $no_oembed_rich_content);
DI::config()->set('system', 'allowed_oembed' , $allowed_oembed);
DI::config()->set('system', 'block_public' , $block_public);
DI::config()->set('system', 'publish_all' , $force_publish);
DI::config()->set('system', 'newuser_private' , $newuser_private);
DI::config()->set('system', 'enotify_no_content' , $enotify_no_content);
DI::config()->set('system', 'disable_embedded' , $disable_embedded);
DI::config()->set('system', 'allow_users_remote_self', $allow_users_remote_self);
DI::config()->set('system', 'explicit_content' , $explicit_content);
DI::config()->set('system', 'proxify_content' , $proxify_content);
DI::config()->set('system', 'cache_contact_avatar' , $cache_contact_avatar);
DI::config()->set('system', 'check_new_version_url' , $check_new_version_url);
$transactionConfig->set('config', 'register_policy' , $register_policy);
$transactionConfig->set('system', 'max_daily_registrations', $daily_registrations);
$transactionConfig->set('system', 'account_abandon_days' , $abandon_days);
$transactionConfig->set('config', 'register_text' , $register_text);
$transactionConfig->set('system', 'allowed_sites' , $allowed_sites);
$transactionConfig->set('system', 'allowed_email' , $allowed_email);
$transactionConfig->set('system', 'forbidden_nicknames' , $forbidden_nicknames);
$transactionConfig->set('system', 'system_actor_name' , $system_actor_name);
$transactionConfig->set('system', 'no_oembed_rich_content' , $no_oembed_rich_content);
$transactionConfig->set('system', 'allowed_oembed' , $allowed_oembed);
$transactionConfig->set('system', 'block_public' , $block_public);
$transactionConfig->set('system', 'publish_all' , $force_publish);
$transactionConfig->set('system', 'newuser_private' , $newuser_private);
$transactionConfig->set('system', 'enotify_no_content' , $enotify_no_content);
$transactionConfig->set('system', 'disable_embedded' , $disable_embedded);
$transactionConfig->set('system', 'allow_users_remote_self', $allow_users_remote_self);
$transactionConfig->set('system', 'explicit_content' , $explicit_content);
$transactionConfig->set('system', 'proxify_content' , $proxify_content);
$transactionConfig->set('system', 'cache_contact_avatar' , $cache_contact_avatar);
$transactionConfig->set('system', 'check_new_version_url' , $check_new_version_url);
DI::config()->set('system', 'block_extended_register', !$enable_multi_reg);
DI::config()->set('system', 'no_openid' , !$enable_openid);
DI::config()->set('system', 'no_regfullname' , !$enable_regfullname);
DI::config()->set('system', 'register_notification' , $register_notification);
DI::config()->set('system', 'community_page_style' , $community_page_style);
DI::config()->set('system', 'max_author_posts_community_page', $max_author_posts_community_page);
DI::config()->set('system', 'verifyssl' , $verifyssl);
DI::config()->set('system', 'proxyuser' , $proxyuser);
DI::config()->set('system', 'proxy' , $proxy);
DI::config()->set('system', 'curl_timeout' , $timeout);
DI::config()->set('system', 'imap_disabled' , !$mail_enabled && function_exists('imap_open'));
DI::config()->set('system', 'ostatus_disabled' , !$ostatus_enabled);
DI::config()->set('system', 'diaspora_enabled' , $diaspora_enabled);
$transactionConfig->set('system', 'block_extended_register', !$enable_multi_reg);
$transactionConfig->set('system', 'no_openid' , !$enable_openid);
$transactionConfig->set('system', 'no_regfullname' , !$enable_regfullname);
$transactionConfig->set('system', 'register_notification' , $register_notification);
$transactionConfig->set('system', 'community_page_style' , $community_page_style);
$transactionConfig->set('system', 'max_author_posts_community_page', $max_author_posts_community_page);
$transactionConfig->set('system', 'verifyssl' , $verifyssl);
$transactionConfig->set('system', 'proxyuser' , $proxyuser);
$transactionConfig->set('system', 'proxy' , $proxy);
$transactionConfig->set('system', 'curl_timeout' , $timeout);
$transactionConfig->set('system', 'imap_disabled' , !$mail_enabled && function_exists('imap_open'));
$transactionConfig->set('system', 'ostatus_disabled' , !$ostatus_enabled);
$transactionConfig->set('system', 'diaspora_enabled' , $diaspora_enabled);
DI::config()->set('config', 'private_addons' , $private_addons);
$transactionConfig->set('config', 'private_addons' , $private_addons);
DI::config()->set('system', 'force_ssl' , $force_ssl);
DI::config()->set('system', 'hide_help' , !$show_help);
$transactionConfig->set('system', 'force_ssl' , $force_ssl);
$transactionConfig->set('system', 'hide_help' , !$show_help);
DI::config()->set('system', 'dbclean' , $dbclean);
DI::config()->set('system', 'dbclean-expire-days' , $dbclean_expire_days);
DI::config()->set('system', 'dbclean_expire_conversation', $dbclean_expire_conv);
$transactionConfig->set('system', 'dbclean' , $dbclean);
$transactionConfig->set('system', 'dbclean-expire-days' , $dbclean_expire_days);
$transactionConfig->set('system', 'dbclean_expire_conversation', $dbclean_expire_conv);
if ($dbclean_unclaimed == 0) {
$dbclean_unclaimed = $dbclean_expire_days;
}
DI::config()->set('system', 'dbclean-expire-unclaimed', $dbclean_unclaimed);
$transactionConfig->set('system', 'dbclean-expire-unclaimed', $dbclean_unclaimed);
DI::config()->set('system', 'max_comments', $max_comments);
DI::config()->set('system', 'max_display_comments', $max_display_comments);
$transactionConfig->set('system', 'max_comments', $max_comments);
$transactionConfig->set('system', 'max_display_comments', $max_display_comments);
if ($temppath != '') {
$temppath = BasePath::getRealPath($temppath);
}
DI::config()->set('system', 'temppath', $temppath);
$transactionConfig->set('system', 'temppath', $temppath);
DI::config()->set('system', 'only_tag_search' , $only_tag_search);
DI::config()->set('system', 'compute_group_counts', $compute_group_counts);
$transactionConfig->set('system', 'only_tag_search' , $only_tag_search);
$transactionConfig->set('system', 'compute_group_counts', $compute_group_counts);
DI::config()->set('system', 'worker_queues' , $worker_queues);
DI::config()->set('system', 'worker_fastlane' , $worker_fastlane);
$transactionConfig->set('system', 'worker_queues' , $worker_queues);
$transactionConfig->set('system', 'worker_fastlane' , $worker_fastlane);
DI::config()->set('system', 'relay_directly' , $relay_directly);
DI::config()->set('system', 'relay_scope' , $relay_scope);
DI::config()->set('system', 'relay_server_tags', $relay_server_tags);
DI::config()->set('system', 'relay_deny_tags' , $relay_deny_tags);
DI::config()->set('system', 'relay_user_tags' , $relay_user_tags);
$transactionConfig->set('system', 'relay_directly' , $relay_directly);
$transactionConfig->set('system', 'relay_scope' , $relay_scope);
$transactionConfig->set('system', 'relay_server_tags', $relay_server_tags);
$transactionConfig->set('system', 'relay_deny_tags' , $relay_deny_tags);
$transactionConfig->set('system', 'relay_user_tags' , $relay_user_tags);
$transactionConfig->commit();
DI::baseUrl()->redirect('admin/site' . $active_panel);
}

View file

@ -157,7 +157,7 @@ class Friendica extends BaseModule
$visible_addons = Addon::getVisibleList();
$config->load('feature_lock');
$config->reload();
$locked_features = [];
$featureLocks = $config->get('config', 'feature_lock');
if (isset($featureLocks)) {

View file

@ -32,7 +32,7 @@ class DBUpdate
public static function execute()
{
// Just in case the last update wasn't failed
if (DI::config()->get('system', 'update', Update::SUCCESS, true) != Update::FAILED) {
if (DI::config()->get('system', 'update', Update::SUCCESS) != Update::FAILED) {
Update::run(DI::app()->getBasePath());
}
}

View file

@ -55,7 +55,7 @@
use Friendica\Database\DBA;
if (!defined('DB_UPDATE_VERSION')) {
define('DB_UPDATE_VERSION', 1507);
define('DB_UPDATE_VERSION', 1508);
}
return [
@ -553,19 +553,6 @@ return [
"k_expires" => ["k", "expires"],
]
],
"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" => ""],
"k" => ["type" => "varbinary(50)", "not null" => "1", "default" => "", "comment" => ""],
"v" => ["type" => "mediumtext", "comment" => ""],
],
"indexes" => [
"PRIMARY" => ["id"],
"cat_k" => ["UNIQUE", "cat", "k"],
]
],
"contact-relation" => [
"comment" => "Contact relations",
"fields" => [

View file

@ -76,7 +76,7 @@ return [
$_SERVER
]
],
Config\Util\ConfigFileLoader::class => [
Config\Util\ConfigFileManager::class => [
'instanceOf' => Config\Factory\Config::class,
'call' => [
['createConfigFileLoader', [
@ -98,9 +98,9 @@ return [
],
],
Config\Capability\IManageConfigValues::class => [
'instanceOf' => Config\Factory\Config::class,
'call' => [
['create', [], Dice::CHAIN_CALL],
'instanceOf' => Config\Model\Config::class,
'constructParams' => [
$_SERVER,
],
],
PConfig\Capability\IManagePersonalConfigValues::class => [

View file

@ -25,20 +25,24 @@ namespace Friendica\Test;
use Dice\Dice;
use Friendica\App\Arguments;
use Friendica\App\Router;
use Friendica\Core\Config\Factory\Config;
use Friendica\Core\Config\Util\ConfigFileManager;
use Friendica\Core\Config\ValueObject\Cache;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Session\Capability\IHandleSessions;
use Friendica\Core\Session\Type\Memory;
use Friendica\Database\Database;
use Friendica\Database\DBStructure;
use Friendica\DI;
use Friendica\Test\Util\Database\StaticDatabase;
use Friendica\Test\Util\VFSTrait;
/**
* Parent class for test cases requiring fixtures
*/
abstract class FixtureTest extends DatabaseTest
{
use VFSTrait;
/** @var Dice */
protected $dice;
@ -47,6 +51,8 @@ abstract class FixtureTest extends DatabaseTest
*/
protected function setUp(): void
{
$this->setUpVfsDir();
parent::setUp();
$server = $_SERVER;
@ -54,6 +60,10 @@ abstract class FixtureTest extends DatabaseTest
$this->dice = (new Dice())
->addRules(include __DIR__ . '/../static/dependencies.config.php')
->addRule(ConfigFileManager::class, [
'instanceOf' => Config::class,
'call' => [['createConfigFileLoader', [$this->root->url(), $server,],
Dice::CHAIN_CALL]]])
->addRule(Database::class, ['instanceOf' => StaticDatabase::class, 'shared' => true])
->addRule(IHandleSessions::class, ['instanceOf' => Memory::class, 'shared' => true, 'call' => null])
->addRule(Arguments::class, [
@ -64,7 +74,6 @@ abstract class FixtureTest extends DatabaseTest
]);
DI::init($this->dice);
/** @var IManageConfigValues $config */
$configCache = $this->dice->create(Cache::class);
$configCache->set('database', 'disable_pdo', true);

View file

@ -54,6 +54,21 @@ trait VFSTrait
$this->setConfigFile('defaults.config.php', true);
$this->setConfigFile('settings.config.php', true);
$this->setConfigFile('local.config.php');
$this->setDataFile('node.config.php');
}
protected function setDataFile(string $filename)
{
$file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
'datasets' . DIRECTORY_SEPARATOR .
'config' . DIRECTORY_SEPARATOR .
$filename;
if (file_exists($file)) {
vfsStream::newFile($filename)
->at($this->root->getChild('config'))
->setContent(file_get_contents($file));
}
}
/**

View file

@ -36,33 +36,6 @@ return [
'mail',
'post-delivery-data',
// Base test config to avoid notice messages
'config' => [
[
'cat' => 'system',
'k' => 'url',
'v' => 'http://localhost',
],
[
'cat' => 'config',
'k' => 'hostname',
'v' => 'localhost',
],
[
'cat' => 'system',
'k' => 'worker_dont_fork',
'v' => '1',
],
[
'cat' => 'system',
'k' => 'curl_timeout',
'v' => '1',
],
[
'cat' => 'system',
'k' => 'xrd_timeout',
'v' => '1',
],
],
'user' => [
[
'uid' => 42,

View file

@ -0,0 +1,22 @@
<?php
return [
'database' => [
'hostname' => 'testhost',
'username' => 'testuser',
'password' => 'testpw',
'database' => 'testdb',
'charset' => 'utf8mb4',
],
'config' => [
'admin_email' => 'admin@test.it',
'sitename' => 'Friendica Social Network',
'register_policy' => 2,
'register_text' => '',
],
'system' => [
'default_timezone' => 'UTC',
'language' => 'en',
'theme' => 'frio',
],
];

View file

@ -0,0 +1,39 @@
<?php
return [
'database' => [
'hostname' => 'testhost',
'username' => 'testuser',
'password' => 'testpw',
'database' => 'testdb',
'charset' => 'utf8mb4',
],
'config' => [
'admin_email' => 'admin@test.it',
'sitename' => 'Friendica Social Network',
'register_policy' => 2,
'register_text' => '',
'test' => [
'a' => [
'next' => 'value',
'bool' => false,
'innerArray' => [
'a' => 4.55,
'b' => false,
'string2' => 'false',
],
],
'v' => true,
'v3' => 1,
'v4' => 5.6443,
],
],
'system' => [
'default_timezone' => 'UTC',
'language' => 'en',
'theme' => 'frio',
'int' => 23,
'float' => 2.5,
'with special chars' => 'I can\'t follow this "$&§%"$%§$%&\'[),',
],
];

View file

@ -0,0 +1,48 @@
<?php
return [
'config' => [
'hostname' => 'friendica.local',
],
'system' => [
'disable_email_validation' => 1,
'disable_password_exposed' => 1,
'throttle_limit_day' => 100,
'throttle_limit_week' => 100,
'throttle_limit_month' => 100,
'temppath' => '/tmp/friendica.local',
'theme' => 'frio',
'url' => 'https://friendica.local',
'urlpath' => '',
'build' => 1508,
'maintenance' => false,
'dbupdate' => 1,
'update' => 0,
'spoolpath' => '/tmp/localhost/spool',
'actor_name' => 'friendica',
'site_prvkey' => '-----BEGIN PRIVATE KEY-----
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALgypZoZ2X7rYCHT
pXZRPKZYOJrtzAZoAD6a2FESfax/mW7tGF8/XGcsu4E8a0WUs18CDb09iDlECs0r
WFkyxOsS55FyDPVNOVheU6ziqmjTNggr1qR8iIpPW2xHAnFjCfvJxgaUfszdoeUV
mhA++BrxFGRpfcH49O+dVcjisJEVAgMBAAECgYEAq0QsRkSSvjgMgmdQCdsvEVwm
BafldG9vCsbfK0KOJ73c5A8AAk/fku88yMVs2J2SylwWekakStrBUFNlKkrSXEv3
r1l0b+dfniaTGJkawqgRh+U/0G9LN+cdZYt5EuhNhCbmIQB+FOI12jAx6COwEENi
824zrrwn0BU1VTOMwwECQQDnBqq0J9JCJAtjqX+3xd8DvTRYjYvtvXlQ8fwrGxBc
GwURNG8aMGTaj+sn2kVWNt4wLQqj/CTJ42y0bkKYMJftAkEAzBwSqfuMZD/+nEkM
wDQb1G2z+BaxLh5JJQo80WX9tORbspOkbEuPgFprO6NB0/vNH5m4AaL3jymokH1p
JfVoyQJBAN+GSsmOMdf+qepeiA0V7OXgPXJkWXvHtEZGK1bFk7maBvgThF+RbTMu
xjZD8IwvACEao03wWuPfIEEe4V4Avi0CQCc5FdUYg+gX7CO4XfzphpeR5U29fprw
MvotN3a99L04TO7KNISjGJZ/ya+SNeo4rzhtX9DgslYOmVf64aPrvxECQQDB79vF
Kx2HyacBSErXrlqqkPdFo8KxhKCAVhrs0VBU1WPswolzsZvRdFuielhGP49DjjE7
JV1Als1hl1xTduNb
-----END PRIVATE KEY-----
',
'site_pubkey' => '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4MqWaGdl+62Ah06V2UTymWDia
7cwGaAA+mthREn2sf5lu7RhfP1xnLLuBPGtFlLNfAg29PYg5RArNK1hZMsTrEueR
cgz1TTlYXlOs4qpo0zYIK9akfIiKT1tsRwJxYwn7ycYGlH7M3aHlFZoQPvga8RRk
aX3B+PTvnVXI4rCRFQIDAQAB
-----END PUBLIC KEY-----
',
],
];

View file

@ -0,0 +1,13 @@
<?php
return [
'config' => [
'hostname' => 'localhost',
],
'system' => [
'url' => 'http://localhost',
"worker_dont_fork" => 1,
"curl_timeout"=> 1,
"xrd_timeout"=> 1,
],
];

View file

@ -31,7 +31,7 @@ use Friendica\Core\Lock\Capability\ICanLock;
use Friendica\Database\Database;
use Friendica\Test\Util\VFSTrait;
use Friendica\Util\BasePath;
use Friendica\Core\Config\Util\ConfigFileLoader;
use Friendica\Core\Config\Util\ConfigFileManager;
use Friendica\Util\Profiler;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
@ -73,13 +73,13 @@ class DependencyCheckTest extends TestCase
*/
public function testConfigFileLoader()
{
/** @var ConfigFileLoader $configFileLoader */
$configFileLoader = $this->dice->create(ConfigFileLoader::class);
/** @var ConfigFileManager $configFileManager */
$configFileManager = $this->dice->create(ConfigFileManager::class);
self::assertInstanceOf(ConfigFileLoader::class, $configFileLoader);
self::assertInstanceOf(ConfigFileManager::class, $configFileManager);
$configCache = new Cache();
$configFileLoader->setupCache($configCache);
$configFileManager->setupCache($configCache);
self::assertNotEmpty($configCache->getAll());
self::assertArrayHasKey('database', $configCache->getAll());
@ -150,7 +150,6 @@ class DependencyCheckTest extends TestCase
self::assertTrue($mode->has(App\Mode::LOCALCONFIGPRESENT), 'No local config present');
self::assertTrue($mode->has(App\Mode::DBAVAILABLE), 'Database is not available');
self::assertTrue($mode->has(App\Mode::DBCONFIGAVAILABLE), 'Database config is not available');
self::assertTrue($mode->has(App\Mode::MAINTENANCEDISABLED), 'In maintenance mode');
self::assertTrue($mode->isNormal(), 'Not in normal mode');

View file

@ -102,29 +102,11 @@ class ModeTest extends MockedTest
self::assertFalse($mode->has(Mode::DBAVAILABLE));
}
public function testWithoutDatabaseSetup()
{
$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
$this->databaseMock->shouldReceive('connected')->andReturn(true)->once();
$this->databaseMock->shouldReceive('fetchFirst')
->with('SHOW TABLES LIKE \'config\'')->andReturn(false)->once();
$mode = (new Mode())->determine($this->basePathMock, $this->databaseMock, $this->configCacheMock);
self::assertFalse($mode->isNormal());
self::assertTrue($mode->isInstall());
self::assertTrue($mode->has(Mode::LOCALCONFIGPRESENT));
}
public function testWithMaintenanceMode()
{
$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
$this->databaseMock->shouldReceive('connected')->andReturn(true)->once();
$this->databaseMock->shouldReceive('fetchFirst')
->with('SHOW TABLES LIKE \'config\'')->andReturn(true)->once();
$this->configCacheMock->shouldReceive('get')->with('system', 'maintenance')
->andReturn(true)->once();
@ -133,7 +115,6 @@ class ModeTest extends MockedTest
self::assertFalse($mode->isNormal());
self::assertFalse($mode->isInstall());
self::assertTrue($mode->has(Mode::DBCONFIGAVAILABLE));
self::assertFalse($mode->has(Mode::MAINTENANCEDISABLED));
}
@ -142,20 +123,14 @@ class ModeTest extends MockedTest
$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
$this->databaseMock->shouldReceive('connected')->andReturn(true)->once();
$this->databaseMock->shouldReceive('fetchFirst')
->with('SHOW TABLES LIKE \'config\'')->andReturn(true)->once();
$this->configCacheMock->shouldReceive('get')->with('system', 'maintenance')
->andReturn(false)->once();
$this->databaseMock->shouldReceive('selectFirst')
->with('config', ['v'], ['cat' => 'system', 'k' => 'maintenance'])
->andReturn(['v' => null])->once();
$mode = (new Mode())->determine($this->basePathMock, $this->databaseMock, $this->configCacheMock);
self::assertTrue($mode->isNormal());
self::assertFalse($mode->isInstall());
self::assertTrue($mode->has(Mode::DBCONFIGAVAILABLE));
self::assertTrue($mode->has(Mode::MAINTENANCEDISABLED));
}
@ -167,20 +142,14 @@ class ModeTest extends MockedTest
$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
$this->databaseMock->shouldReceive('connected')->andReturn(true)->once();
$this->databaseMock->shouldReceive('fetchFirst')
->with('SHOW TABLES LIKE \'config\'')->andReturn(true)->once();
$this->configCacheMock->shouldReceive('get')->with('system', 'maintenance')
->andReturn(false)->once();
$this->databaseMock->shouldReceive('selectFirst')
->with('config', ['v'], ['cat' => 'system', 'k' => 'maintenance'])
->andReturn(['v' => '0'])->once();
$mode = (new Mode())->determine($this->basePathMock, $this->databaseMock, $this->configCacheMock);
self::assertTrue($mode->isNormal());
self::assertFalse($mode->isInstall());
self::assertTrue($mode->has(Mode::DBCONFIGAVAILABLE));
self::assertTrue($mode->has(Mode::MAINTENANCEDISABLED));
}

View file

@ -21,7 +21,7 @@
namespace Friendica\Test\src\Core\Config\Cache;
use Friendica\Core\Config\Cache;
use Friendica\Core\Config\ValueObject\Cache;
use Friendica\Test\MockedTest;
use ParagonIE\HiddenString\HiddenString;
use stdClass;
@ -49,7 +49,7 @@ class CacheTest extends MockedTest
];
}
private function assertConfigValues($data, \Friendica\Core\Config\ValueObject\Cache $configCache)
private function assertConfigValues($data, Cache $configCache)
{
foreach ($data as $cat => $values) {
foreach ($values as $key => $value) {
@ -64,7 +64,7 @@ class CacheTest extends MockedTest
*/
public function testLoadConfigArray($data)
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
$configCache->load($data);
self::assertConfigValues($data, $configCache);
@ -83,27 +83,27 @@ class CacheTest extends MockedTest
]
];
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache->load($data, \Friendica\Core\Config\ValueObject\Cache::SOURCE_DB);
$configCache = new Cache();
$configCache->load($data, Cache::SOURCE_DATA);
// doesn't override - Low Priority due Config file
$configCache->load($override, \Friendica\Core\Config\ValueObject\Cache::SOURCE_FILE);
$configCache->load($override, Cache::SOURCE_FILE);
self::assertConfigValues($data, $configCache);
// override the value - High Prio due Server Env
$configCache->load($override, \Friendica\Core\Config\ValueObject\Cache::SOURCE_ENV);
$configCache->load($override, Cache::SOURCE_ENV);
self::assertEquals($override['system']['test'], $configCache->get('system', 'test'));
self::assertEquals($override['system']['boolTrue'], $configCache->get('system', 'boolTrue'));
// Don't overwrite server ENV variables - even in load mode
$configCache->load($data, \Friendica\Core\Config\ValueObject\Cache::SOURCE_DB);
$configCache->load($data, Cache::SOURCE_DATA);
self::assertEquals($override['system']['test'], $configCache->get('system', 'test'));
self::assertEquals($override['system']['boolTrue'], $configCache->get('system', 'boolTrue'));
// Overwrite ENV variables with ENV variables
$configCache->load($data, \Friendica\Core\Config\ValueObject\Cache::SOURCE_ENV);
$configCache->load($data, Cache::SOURCE_ENV);
self::assertConfigValues($data, $configCache);
self::assertNotEquals($override['system']['test'], $configCache->get('system', 'test'));
@ -115,7 +115,7 @@ class CacheTest extends MockedTest
*/
public function testLoadConfigArrayWrong()
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
// empty dataset
$configCache->load([]);
@ -136,7 +136,7 @@ class CacheTest extends MockedTest
*/
public function testGetAll($data)
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
$configCache->load($data);
$all = $configCache->getAll();
@ -151,7 +151,7 @@ class CacheTest extends MockedTest
*/
public function testSetGet($data)
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
foreach ($data as $cat => $values) {
foreach ($values as $key => $value) {
@ -167,7 +167,7 @@ class CacheTest extends MockedTest
*/
public function testGetEmpty()
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
self::assertNull($configCache->get('something', 'value'));
}
@ -177,7 +177,7 @@ class CacheTest extends MockedTest
*/
public function testGetCat()
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache([
$configCache = new Cache([
'system' => [
'key1' => 'value1',
'key2' => 'value2',
@ -205,7 +205,7 @@ class CacheTest extends MockedTest
*/
public function testDelete($data)
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache($data);
$configCache = new Cache($data);
foreach ($data as $cat => $values) {
foreach ($values as $key => $value) {
@ -222,7 +222,7 @@ class CacheTest extends MockedTest
*/
public function testKeyDiffWithResult($data)
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache($data);
$configCache = new Cache($data);
$diffConfig = [
'fakeCat' => [
@ -239,7 +239,7 @@ class CacheTest extends MockedTest
*/
public function testKeyDiffWithoutResult($data)
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache($data);
$configCache = new Cache($data);
$diffConfig = $configCache->getAll();
@ -251,7 +251,7 @@ class CacheTest extends MockedTest
*/
public function testPasswordHide()
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache([
$configCache = new Cache([
'database' => [
'password' => 'supersecure',
'username' => 'notsecured',
@ -268,7 +268,7 @@ class CacheTest extends MockedTest
*/
public function testPasswordShow()
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache([
$configCache = new Cache([
'database' => [
'password' => 'supersecure',
'username' => 'notsecured',
@ -285,7 +285,7 @@ class CacheTest extends MockedTest
*/
public function testEmptyPassword()
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache([
$configCache = new Cache([
'database' => [
'password' => '',
'username' => '',
@ -299,7 +299,7 @@ class CacheTest extends MockedTest
public function testWrongTypePassword()
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache([
$configCache = new Cache([
'database' => [
'password' => new stdClass(),
'username' => '',
@ -309,7 +309,7 @@ class CacheTest extends MockedTest
self::assertNotEmpty($configCache->get('database', 'password'));
self::assertEmpty($configCache->get('database', 'username'));
$configCache = new \Friendica\Core\Config\ValueObject\Cache([
$configCache = new Cache([
'database' => [
'password' => 23,
'username' => '',
@ -327,19 +327,87 @@ class CacheTest extends MockedTest
public function testSetOverrides($data)
{
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache->load($data, \Friendica\Core\Config\ValueObject\Cache::SOURCE_DB);
$configCache = new Cache();
$configCache->load($data, Cache::SOURCE_DATA);
// test with wrong override
self::assertFalse($configCache->set('system', 'test', '1234567', \Friendica\Core\Config\ValueObject\Cache::SOURCE_FILE));
self::assertFalse($configCache->set('system', 'test', '1234567', Cache::SOURCE_FILE));
self::assertEquals($data['system']['test'], $configCache->get('system', 'test'));
// test with override (equal)
self::assertTrue($configCache->set('system', 'test', '8910', \Friendica\Core\Config\ValueObject\Cache::SOURCE_DB));
self::assertTrue($configCache->set('system', 'test', '8910', Cache::SOURCE_DATA));
self::assertEquals('8910', $configCache->get('system', 'test'));
// test with override (over)
self::assertTrue($configCache->set('system', 'test', '111213', \Friendica\Core\Config\ValueObject\Cache::SOURCE_ENV));
self::assertTrue($configCache->set('system', 'test', '111213', Cache::SOURCE_ENV));
self::assertEquals('111213', $configCache->get('system', 'test'));
}
/**
* @dataProvider dataTests
*
* @return void
*/
public function testSetData($data)
{
$configCache = new Cache();
$configCache->load($data, Cache::SOURCE_FILE);
$configCache->set('system', 'test_2','with_data', Cache::SOURCE_DATA);
$this->assertEquals(['system' => ['test_2' => 'with_data']], $configCache->getDataBySource(Cache::SOURCE_DATA));
$this->assertEquals($data, $configCache->getDataBySource(Cache::SOURCE_FILE));
}
/**
* @dataProvider dataTests
*/
public function testMerge($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);
$configCache->set('old_category', 'test_45','given category', 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);
$newCache->set('new_category', 'test_23','added category', Cache::SOURCE_DATA);
$mergedCache = $configCache->merge($newCache);
self::assertEquals('with_data', $mergedCache->get('system', 'test_2'));
self::assertEquals('override it again', $mergedCache->get('config', 'test_override'));
self::assertEquals('new value', $mergedCache->get('system', 'test_3'));
self::assertEquals('given category', $mergedCache->get('old_category', 'test_45'));
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'));
}
}

View file

@ -21,14 +21,14 @@
namespace Friendica\Test\src\Core\Config\Cache;
use Friendica\Core\Config\Cache;
use Friendica\Core\Config\Factory\Config;
use Friendica\Core\Config\ValueObject\Cache;
use Friendica\Test\MockedTest;
use Friendica\Test\Util\VFSTrait;
use Friendica\Core\Config\Util\ConfigFileLoader;
use Friendica\Core\Config\Util\ConfigFileManager;
use org\bovigo\vfs\vfsStream;
class ConfigFileLoaderTest extends MockedTest
class ConfigFileManagerTest extends MockedTest
{
use VFSTrait;
@ -46,12 +46,12 @@ class ConfigFileLoaderTest extends MockedTest
{
$this->delConfigFile('local.config.php');
$configFileLoader = new ConfigFileLoader(
$configFileLoader = new ConfigFileManager(
$this->root->url(),
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
);
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
$configFileLoader->setupCache($configCache);
@ -72,12 +72,12 @@ class ConfigFileLoaderTest extends MockedTest
->at($this->root->getChild('config'))
->setContent('<?php return true;');
$configFileLoader = new ConfigFileLoader(
$configFileLoader = new ConfigFileManager(
$this->root->url(),
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
);
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
$configFileLoader->setupCache($configCache);
}
@ -101,12 +101,12 @@ class ConfigFileLoaderTest extends MockedTest
->at($this->root->getChild('config'))
->setContent(file_get_contents($file));
$configFileLoader = new ConfigFileLoader(
$configFileLoader = new ConfigFileManager(
$this->root->url(),
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
);
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
$configFileLoader->setupCache($configCache);
@ -138,12 +138,12 @@ class ConfigFileLoaderTest extends MockedTest
->at($this->root->getChild('config'))
->setContent(file_get_contents($file));
$configFileLoader = new ConfigFileLoader(
$configFileLoader = new ConfigFileManager(
$this->root->url(),
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
);
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
$configFileLoader->setupCache($configCache);
@ -174,12 +174,12 @@ class ConfigFileLoaderTest extends MockedTest
->at($this->root)
->setContent(file_get_contents($file));
$configFileLoader = new ConfigFileLoader(
$configFileLoader = new ConfigFileManager(
$this->root->url(),
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
);
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
$configFileLoader->setupCache($configCache);
@ -228,7 +228,7 @@ class ConfigFileLoaderTest extends MockedTest
->at($this->root->getChild('addon')->getChild('test')->getChild('config'))
->setContent(file_get_contents($file));
$configFileLoader = new ConfigFileLoader(
$configFileLoader = new ConfigFileManager(
$this->root->url(),
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
@ -265,12 +265,12 @@ class ConfigFileLoaderTest extends MockedTest
->at($this->root->getChild('config'))
->setContent(file_get_contents($fileDir . 'B.config.php'));
$configFileLoader = new ConfigFileLoader(
$configFileLoader = new ConfigFileManager(
$this->root->url(),
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
);
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
$configFileLoader->setupCache($configCache);
@ -299,12 +299,12 @@ class ConfigFileLoaderTest extends MockedTest
->at($this->root->getChild('config'))
->setContent(file_get_contents($fileDir . 'B.ini.php'));
$configFileLoader = new ConfigFileLoader(
$configFileLoader = new ConfigFileManager(
$this->root->url(),
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
);
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
$configFileLoader->setupCache($configCache);
@ -333,12 +333,12 @@ class ConfigFileLoaderTest extends MockedTest
->at($this->root->getChild('config'))
->setContent(file_get_contents($fileDir . 'B.ini.php'));
$configFileLoader = new ConfigFileLoader(
$configFileLoader = new ConfigFileManager(
$this->root->url(),
$this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
$this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
);
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
$configFileLoader->setupCache($configCache);
@ -354,7 +354,7 @@ class ConfigFileLoaderTest extends MockedTest
$this->delConfigFile('local.config.php');
$configFileLoader = (new Config())->createConfigFileLoader($this->root->url(), ['FRIENDICA_CONFIG_DIR' => '/a/wrong/dir/']);
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
$configFileLoader->setupCache($configCache);
@ -380,10 +380,57 @@ class ConfigFileLoaderTest extends MockedTest
->setContent(file_get_contents($fileDir . 'B.config.php'));
$configFileLoader = (new Config())->createConfigFileLoader($this->root->url(), ['FRIENDICA_CONFIG_DIR' => $this->root->getChild('config2')->url()]);
$configCache = new \Friendica\Core\Config\ValueObject\Cache();
$configCache = new Cache();
$configFileLoader->setupCache($configCache);
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'));
$configFileLoader = (new Config())->createConfigFileLoader($this->root->url(), ['FRIENDICA_CONFIG_DIR' => $this->root->getChild('config2')->url()]);
$configCache = new Cache();
$configFileLoader->setupCache($configCache);
$specialChars = '!"§$%&/()(/&%$\'><?$a,;:[]}{}\\';
// overwrite some data and save it back to the config file
$configCache->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);
$configFileLoader->saveData($configCache);
// Reload the configCache with the new values
$configCache2 = new Cache();
$configFileLoader->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));
}
}

View file

@ -23,22 +23,25 @@ namespace Friendica\Test\src\Core\Config;
use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Config\Repository\Config as ConfigModel;
use Friendica\Core\Config\Model\Config;
use Friendica\Core\Config\Util\ConfigFileManager;
use Friendica\Core\Config\Util\ConfigFileTransformer;
use Friendica\Core\Config\ValueObject\Cache;
use Friendica\Test\MockedTest;
use Mockery\MockInterface;
use Mockery;
use Friendica\Test\Util\VFSTrait;
use org\bovigo\vfs\vfsStream;
abstract class ConfigTest extends MockedTest
class ConfigTest extends MockedTest
{
use ArraySubsetAsserts;
/** @var ConfigModel|MockInterface */
protected $configModel;
use VFSTrait;
/** @var Cache */
protected $configCache;
/** @var ConfigFileManager */
protected $configFileManager;
/** @var IManageConfigValues */
protected $testedConfig;
@ -60,17 +63,22 @@ abstract class ConfigTest extends MockedTest
protected function setUp(): void
{
$this->setUpVfsDir();
parent::setUp();
// Create the config model
$this->configModel = Mockery::mock(ConfigModel::class);
$this->configCache = new Cache();
$this->configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/');
}
/**
* @return IManageConfigValues
*/
abstract public function getInstance();
public function getInstance()
{
$this->configFileManager->setupCache($this->configCache, []);
return new Config($this->configFileManager, $this->configCache);
}
public function dataTests()
{
@ -156,12 +164,13 @@ abstract class ConfigTest extends MockedTest
/**
* Test the configuration initialization
* @dataProvider dataConfigLoad
*/
public function testSetUp(array $data)
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true)
->once();
vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE)
->at($this->root->getChild('config'))
->setContent(ConfigFileTransformer::encode($data));
$this->testedConfig = $this->getInstance();
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
@ -171,19 +180,23 @@ abstract class ConfigTest extends MockedTest
}
/**
* Test the configuration load() method
* Test the configuration reload() method
*
* @param array $data
* @param array $load
*
* @dataProvider dataConfigLoad
*/
public function testLoad(array $data, array $load)
public function testReload(array $data, array $load)
{
vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE)
->at($this->root->getChild('config'))
->setContent(ConfigFileTransformer::encode($data));
$this->testedConfig = $this->getInstance();
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
foreach ($load as $loadedCats) {
$this->testedConfig->load($loadedCats);
}
$this->testedConfig->reload();
// Assert at least loaded cats are loaded
foreach ($load as $loadedCats) {
@ -256,23 +269,31 @@ abstract class ConfigTest extends MockedTest
/**
* Test the configuration load() method with overwrite
*
* @dataProvider dataDoubleLoad
*/
public function testCacheLoadDouble(array $data1, array $data2, array $expect = [])
{
vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE)
->at($this->root->getChild('config'))
->setContent(ConfigFileTransformer::encode($data1));
$this->testedConfig = $this->getInstance();
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
foreach ($data1 as $cat => $data) {
$this->testedConfig->load($cat);
}
// Assert at least loaded cats are loaded
foreach ($data1 as $cat => $data) {
self::assertConfig($cat, $data);
}
vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE)
->at($this->root->getChild('config'))
->setContent(ConfigFileTransformer::encode($data2));
$this->testedConfig->reload();
foreach ($data2 as $cat => $data) {
$this->testedConfig->load($cat);
self::assertConfig($cat, $data);
}
}
@ -281,44 +302,19 @@ abstract class ConfigTest extends MockedTest
*/
public function testLoadWrong()
{
$this->configModel->shouldReceive('isConnected')->andReturn(true)->once();
$this->configModel->shouldReceive('load')->withAnyArgs()->andReturn([])->once();
$this->testedConfig = $this->getInstance();
$this->testedConfig = new Config($this->configFileManager, new Cache());
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
self::assertEmpty($this->testedConfig->getCache()->getAll());
}
/**
* Test the configuration get() and set() methods without adapter
* Test the configuration get() and set() methods
*
* @dataProvider dataTests
*/
public function testSetGetWithoutDB($data)
public function testSetGet($data)
{
$this->configModel->shouldReceive('isConnected')
->andReturn(false)
->times(3);
$this->testedConfig = $this->getInstance();
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
self::assertTrue($this->testedConfig->set('test', 'it', $data));
self::assertEquals($data, $this->testedConfig->get('test', 'it'));
self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
}
/**
* Test the configuration get() and set() methods with a model/db
*
* @dataProvider dataTests
*/
public function testSetGetWithDB($data)
{
$this->configModel->shouldReceive('set')->with('test', 'it', $data)->andReturn(true)->once();
$this->testedConfig = $this->getInstance();
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
@ -349,41 +345,16 @@ abstract class ConfigTest extends MockedTest
self::assertEquals('default', $this->testedConfig->get('test', 'it', 'default', true));
}
/**
* Test the configuration get() method with refresh
*
* @dataProvider dataTests
*/
public function testGetWithRefresh($data)
{
$this->configCache->load(['test' => ['it' => 'now']], Cache::SOURCE_FILE);
$this->testedConfig = $this->getInstance();
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
// without refresh
self::assertEquals('now', $this->testedConfig->get('test', 'it'));
self::assertEquals('now', $this->testedConfig->getCache()->get('test', 'it'));
// with refresh
self::assertEquals($data, $this->testedConfig->get('test', 'it', null, true));
self::assertEquals($data, $this->testedConfig->getCache()->get('test', 'it'));
// without refresh and wrong value and default
self::assertEquals('default', $this->testedConfig->get('test', 'not', 'default'));
self::assertNull($this->testedConfig->getCache()->get('test', 'not'));
}
/**
* Test the configuration delete() method without a model/db
*
* @dataProvider dataTests
*/
public function testDeleteWithoutDB($data)
public function testDelete($data)
{
$this->configCache->load(['test' => ['it' => $data]], Cache::SOURCE_FILE);
$this->testedConfig = $this->getInstance();
$this->testedConfig = new Config($this->configFileManager, $this->configCache);
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
self::assertEquals($data, $this->testedConfig->get('test', 'it'));
@ -396,51 +367,6 @@ abstract class ConfigTest extends MockedTest
self::assertEmpty($this->testedConfig->getCache()->getAll());
}
/**
* Test the configuration delete() method with a model/db
*/
public function testDeleteWithDB()
{
$this->configCache->load(['test' => ['it' => 'now', 'quarter' => 'true']], Cache::SOURCE_FILE);
$this->configModel->shouldReceive('delete')
->with('test', 'it')
->andReturn(false)
->once();
$this->configModel->shouldReceive('delete')
->with('test', 'second')
->andReturn(true)
->once();
$this->configModel->shouldReceive('delete')
->with('test', 'third')
->andReturn(false)
->once();
$this->configModel->shouldReceive('delete')
->with('test', 'quarter')
->andReturn(true)
->once();
$this->testedConfig = $this->getInstance();
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
// directly set the value to the cache
$this->testedConfig->getCache()->set('test', 'it', 'now');
self::assertEquals('now', $this->testedConfig->get('test', 'it'));
self::assertEquals('now', $this->testedConfig->getCache()->get('test', 'it'));
// delete from cache only
self::assertTrue($this->testedConfig->delete('test', 'it'));
// delete from db only
self::assertTrue($this->testedConfig->delete('test', 'second'));
// no delete
self::assertFalse($this->testedConfig->delete('test', 'third'));
// delete both
self::assertTrue($this->testedConfig->delete('test', 'quarter'));
self::assertEmpty($this->testedConfig->getCache()->getAll());
}
/**
* Test the configuration get() and set() method where the db value has a higher prio than the config file
*/
@ -462,6 +388,12 @@ abstract class ConfigTest extends MockedTest
*/
public function testSetGetLowPrio()
{
vfsStream::newFile(ConfigFileManager::CONFIG_DATA_FILE)
->at($this->root->getChild('config'))
->setContent(ConfigFileTransformer::encode([
'config' => ['test' => 'it'],
]));
$this->testedConfig = $this->getInstance();
self::assertInstanceOf(Cache::class, $this->testedConfig->getCache());
self::assertEquals('it', $this->testedConfig->get('config', 'test'));

View file

@ -0,0 +1,111 @@
<?php
namespace Friendica\Test\src\Core\Config;
use Friendica\Core\Config\Capability\ISetConfigValuesTransactionally;
use Friendica\Core\Config\Model\Config;
use Friendica\Core\Config\Model\ConfigTransaction;
use Friendica\Core\Config\Util\ConfigFileManager;
use Friendica\Core\Config\ValueObject\Cache;
use Friendica\Test\MockedTest;
use Friendica\Test\Util\VFSTrait;
class ConfigTransactionTest extends MockedTest
{
use VFSTrait;
/** @var ConfigFileManager */
protected $configFileManager;
protected function setUp(): void
{
parent::setUp();
$this->setUpVfsDir();
$this->configFileManager = new ConfigFileManager($this->root->url(), $this->root->url() . '/config/', $this->root->url() . '/static/');
}
public function dataTests(): array
{
return [
'default' => [
'data' => include dirname(__FILE__, 4) . '/datasets/B.node.config.php',
]
];
}
public function testInstance()
{
$config = new Config($this->configFileManager, new Cache());
$configTransaction = new ConfigTransaction($config);
self::assertInstanceOf(ISetConfigValuesTransactionally::class, $configTransaction);
self::assertInstanceOf(ConfigTransaction::class, $configTransaction);
}
public function testConfigTransaction()
{
$config = new Config($this->configFileManager, 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);
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
$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');
// overwrite key-value
$configTransaction->set('config', 'key1', 'changedValue1');
// delete key-value
$configTransaction->delete('system', 'keyDel');
// delete last key of category - so the category is gone
$configTransaction->delete('delete', 'keyDel');
// The main config still doesn't know about the change
self::assertNull($config->get('transaction', 'key3'));
self::assertEquals('value1', $config->get('config', 'key1'));
self::assertEquals('valueDel', $config->get('system', '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
$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();
// Now every config and file knows the change
self::assertEquals('changedValue1', $config->get('config', 'key1'));
self::assertEquals('value3', $config->get('transaction', 'key3'));
self::assertNull($config->get('system', '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;
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);
}
}

View file

@ -1,255 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Test\src\Core\Config;
use Friendica\Core\Config\Type\JitConfig;
class JitConfigTest extends ConfigTest
{
public function getInstance()
{
return new JitConfig($this->configCache, $this->configModel);
}
/**
* @dataProvider dataConfigLoad
*/
public function testSetUp(array $data)
{
$this->configModel->shouldReceive('load')
->with('config')
->andReturn(['config' => $data['config']])
->once();
parent::testSetUp($data);
}
/**
* @dataProvider dataConfigLoad
*
* @param array $data
* @param array $load
*/
public function testLoad(array $data, array $load)
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true)
->times(count($load) + 1);
$this->configModel->shouldReceive('load')
->with('config')
->andReturn(['config' => $data['config']])
->once();
foreach ($load as $loadCat) {
$this->configModel->shouldReceive('load')
->with($loadCat)
->andReturn([$loadCat => $data[$loadCat]])
->once();
}
parent::testLoad($data, $load);
}
/**
* @dataProvider dataDoubleLoad
*/
public function testCacheLoadDouble(array $data1, array $data2, array $expect = [])
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true)
->times(count($data1) + count($data2) + 1);
$this->configModel->shouldReceive('load')
->with('config')
->andReturn(['config' => $data1['config']])
->once();
foreach ($data1 as $cat => $data) {
$this->configModel->shouldReceive('load')
->with($cat)
->andReturn([$cat => $data])
->once();
}
foreach ($data2 as $cat => $data) {
$this->configModel->shouldReceive('load')
->with($cat)
->andReturn([$cat => $data])
->once();
}
parent::testCacheLoadDouble($data1, $data2);
// Assert the expected categories
foreach ($data2 as $cat => $data) {
self::assertConfig($cat, $expect[$cat]);
}
}
/**
* @dataProvider dataTests
*/
public function testSetGetWithDB($data)
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true)
->times(3);
$this->configModel->shouldReceive('load')->with('config')->andReturn(['config' => []])->once();
parent::testSetGetWithDB($data);
}
/**
* @dataProvider dataTests
*/
public function testGetWithRefresh($data)
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true)
->times(4);
// constructor loading
$this->configModel->shouldReceive('load')
->with('config')
->andReturn(['config' => []])
->once();
// mocking one get without result
$this->configModel->shouldReceive('get')
->with('test', 'it')
->andReturn(null)
->once();
// mocking the data get
$this->configModel->shouldReceive('get')
->with('test', 'it')
->andReturn($data)
->once();
// mocking second get
$this->configModel->shouldReceive('get')
->with('test', 'not')
->andReturn(null)
->once();
parent::testGetWithRefresh($data);
}
public function testGetWrongWithoutDB()
{
$this->configModel->shouldReceive('isConnected')
->andReturn(false)
->times(4);
parent::testGetWrongWithoutDB();
}
/**
* @dataProvider dataTests
*/
public function testDeleteWithoutDB($data)
{
$this->configModel->shouldReceive('isConnected')
->andReturn(false)
->times(4);
parent::testDeleteWithoutDB($data);
}
public function testDeleteWithDB()
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true)
->times(6);
// constructor loading
$this->configModel->shouldReceive('load')
->with('config')
->andReturn(['config' => []])
->once();
// mocking one get without result
$this->configModel->shouldReceive('get')
->with('test', 'it')
->andReturn(null)
->once();
parent::testDeleteWithDB();
}
public function testSetGetHighPrio()
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true);
// constructor loading
$this->configModel->shouldReceive('load')
->with('config')
->andReturn(['config' => []])
->once();
$this->configModel->shouldReceive('get')
->with('config', 'test')
->andReturn('prio')
->once();
$this->configModel->shouldReceive('set')
->with('config', 'test', '123')
->andReturn(true)
->once();
$this->configModel->shouldReceive('get')
->with('config', 'test')
->andReturn('123')
->once();
parent::testSetGetHighPrio();
}
public function testSetGetLowPrio()
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true);
// constructor loading
$this->configModel->shouldReceive('load')
->with('config')
->andReturn(['config' => ['test' => 'it']])
->once();
$this->configModel->shouldReceive('set')
->with('config', 'test', '123')
->andReturn(true)
->once();
// mocking one get without result
$this->configModel->shouldReceive('get')
->with('config', 'test')
->andReturn('it')
->once();
parent::testSetGetLowPrio();
}
}

View file

@ -1,213 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Test\src\Core\Config;
use Friendica\Core\Config\Type\PreloadConfig;
class PreloadConfigTest extends ConfigTest
{
public function getInstance()
{
return new PreloadConfig($this->configCache, $this->configModel);
}
/**
* @dataProvider dataConfigLoad
*/
public function testSetUp(array $data)
{
$this->configModel->shouldReceive('load')
->andReturn($data)
->once();
parent::testSetUp($data);
}
/**
* @dataProvider dataConfigLoad
*
* @param array $data
* @param array $load
*/
public function testLoad(array $data, array $load)
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true)
->once();
$this->configModel->shouldReceive('load')
->andReturn($data)
->once();
parent::testLoad($data, $load);
// Assert that every category is loaded everytime
foreach ($data as $cat => $values) {
self::assertConfig($cat, $values);
}
}
/**
* @dataProvider dataDoubleLoad
*
* @param array $data1
* @param array $data2
*/
public function testCacheLoadDouble(array $data1, array $data2, array $expect = [])
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true)
->once();
$this->configModel->shouldReceive('load')
->andReturn($data1)
->once();
parent::testCacheLoadDouble($data1, $data2);
// Assert that every category is loaded everytime and is NOT overwritten
foreach ($data1 as $cat => $values) {
self::assertConfig($cat, $values);
}
}
/**
* @dataProvider dataTests
*/
public function testSetGetWithDB($data)
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true)
->times(2);
$this->configModel->shouldReceive('load')->andReturn(['config' => []])->once();
parent::testSetGetWithDB($data);
}
/**
* @dataProvider dataTests
*/
public function testGetWithRefresh($data)
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true)
->times(2);
// constructor loading
$this->configModel->shouldReceive('load')
->andReturn(['config' => []])
->once();
// mocking one get
$this->configModel->shouldReceive('get')
->with('test', 'it')
->andReturn($data)
->once();
parent::testGetWithRefresh($data);
}
public function testGetWrongWithoutDB()
{
$this->configModel->shouldReceive('isConnected')
->andReturn(false)
->times(2);
parent::testGetWrongWithoutDB();
}
/**
* @dataProvider dataTests
*/
public function testDeleteWithoutDB($data)
{
$this->configModel->shouldReceive('isConnected')
->andReturn(false)
->times(2);
parent::testDeleteWithoutDB($data);
}
public function testDeleteWithDB()
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true)
->times(5);
// constructor loading
$this->configModel->shouldReceive('load')
->andReturn(['config' => []])
->once();
parent::testDeleteWithDB();
}
public function testSetGetHighPrio()
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true);
// constructor loading
$this->configModel->shouldReceive('load')
->andReturn(['config' => []])
->once();
$this->configModel->shouldReceive('set')
->with('config', 'test', '123')
->andReturn(true)
->once();
$this->configModel->shouldReceive('get')
->with('config', 'test')
->andReturn('123')
->once();
parent::testSetGetHighPrio();
}
public function testSetGetLowPrio()
{
$this->configModel->shouldReceive('isConnected')
->andReturn(true);
// constructor loading
$this->configModel->shouldReceive('load')
->andReturn(['config' => ['test' => 'it']])
->once();
$this->configModel->shouldReceive('set')
->with('config', 'test', '123')
->andReturn(true)
->once();
// mocking one get without result
$this->configModel->shouldReceive('get')
->with('config', 'test')
->andReturn('it')
->once();
parent::testSetGetLowPrio();
}
}

View file

@ -0,0 +1,57 @@
<?php
/**
* @copyright Copyright (C) 2010-2023, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Test\src\Core\Config\Util;
use Friendica\Core\Config\Util\ConfigFileTransformer;
use Friendica\Test\MockedTest;
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/C.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)
{
$dataArray = include $configFile;
$newConfig = ConfigFileTransformer::encode($dataArray);
self::assertEquals(file_get_contents($configFile), $newConfig);
}
}

View file

@ -24,7 +24,10 @@ 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\ValueObject\Cache;
use Friendica\Core\Lock\Type\SemaphoreLock;
use Friendica\Core\System;
use Friendica\DI;
@ -42,11 +45,8 @@ class SemaphoreLockTest extends LockTest
$app->shouldReceive('getHostname')->andReturn('friendica.local');
$dice->shouldReceive('create')->with(App::class)->andReturn($app);
$configMock = Mockery::mock(JitConfig::class);
$configMock
->shouldReceive('get')
->with('system', 'temppath')
->andReturn('/tmp/');
$configCache = new Cache(['system' => ['temppath' => '/tmp']]);
$configMock = new Config(Mockery::mock(ConfigFileManager::class), $configCache);
$dice->shouldReceive('create')->with(IManageConfigValues::class)->andReturn($configMock);
// @todo Because "get_temppath()" is using static methods, we have to initialize the BaseObject

View file

@ -22,9 +22,7 @@
namespace Friendica\Test\src\Core\Storage\Repository;
use Dice\Dice;
use Friendica\App\Mode;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Config\Type\PreloadConfig;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Session\Capability\IHandleSessions;
@ -41,7 +39,6 @@ use Friendica\Database\Definition\DbaDefinition;
use Friendica\Database\Definition\ViewDefinition;
use Friendica\DI;
use Friendica\Core\Config\Factory\Config;
use Friendica\Core\Config\Repository;
use Friendica\Core\Storage\Type;
use Friendica\Test\DatabaseTest;
use Friendica\Test\Util\Database\StaticDatabase;
@ -89,8 +86,7 @@ class StorageManagerTest extends DatabaseTest
$this->dba = new StaticDatabase($configCache, $profiler, $dbaDefinition, $viewDefinition);
$configModel = new Repository\Config($this->dba, new Mode(Mode::DBCONFIGAVAILABLE));
$this->config = new PreloadConfig($configCache, $configModel);
$this->config = new \Friendica\Core\Config\Model\Config($loader, $configCache);
$this->config->set('storage', 'name', 'Database');
$this->config->set('storage', 'filesystem_path', $this->root->getChild(Type\FilesystemConfig::DEFAULT_BASE_FOLDER)->url());

View file

@ -52,10 +52,7 @@ class DBATest extends DatabaseTest
*/
public function testExists() {
self::assertTrue(DBA::exists('config', []));
self::assertTrue(DBA::exists('user', []));
self::assertFalse(DBA::exists('notable', []));
self::assertTrue(DBA::exists('config', ['k' => 'hostname']));
self::assertFalse(DBA::exists('config', ['k' => 'nonsense']));
}
}

View file

@ -44,30 +44,30 @@ class DBStructureTest extends DatabaseTest
* @small
*/
public function testExists() {
self::assertTrue(DBStructure::existsTable('config'));
self::assertTrue(DBStructure::existsTable('user'));
self::assertFalse(DBStructure::existsTable('notatable'));
self::assertTrue(DBStructure::existsColumn('config', ['k']));
self::assertFalse(DBStructure::existsColumn('config', ['nonsense']));
self::assertFalse(DBStructure::existsColumn('config', ['k', 'nonsense']));
self::assertTrue(DBStructure::existsColumn('user', ['uid']));
self::assertFalse(DBStructure::existsColumn('user', ['nonsense']));
self::assertFalse(DBStructure::existsColumn('user', ['uid', 'nonsense']));
}
/**
* @small
*/
public function testRename() {
$fromColumn = 'k';
$toColumn = 'key';
$fromType = 'varbinary(255) not null';
$toType = 'varbinary(255) not null comment \'Test To Type\'';
$fromColumn = 'email';
$toColumn = 'email_key';
$fromType = 'varchar(255) NOT NULL DEFAULT \'\' COMMENT \'the users email address\'';
$toType = 'varchar(255) NOT NULL DEFAULT \'\' COMMENT \'Adapted column\'';
self::assertTrue(DBStructure::rename('config', [ $fromColumn => [ $toColumn, $toType ]]));
self::assertTrue(DBStructure::existsColumn('config', [ $toColumn ]));
self::assertFalse(DBStructure::existsColumn('config', [ $fromColumn ]));
self::assertTrue(DBStructure::rename('user', [ $fromColumn => [ $toColumn, $toType ]]));
self::assertTrue(DBStructure::existsColumn('user', [ $toColumn ]));
self::assertFalse(DBStructure::existsColumn('user', [ $fromColumn ]));
self::assertTrue(DBStructure::rename('config', [ $toColumn => [ $fromColumn, $fromType ]]));
self::assertTrue(DBStructure::existsColumn('config', [ $fromColumn ]));
self::assertFalse(DBStructure::existsColumn('config', [ $toColumn ]));
self::assertTrue(DBStructure::rename('user', [ $toColumn => [ $fromColumn, $fromType ]]));
self::assertTrue(DBStructure::existsColumn('user', [ $fromColumn ]));
self::assertFalse(DBStructure::existsColumn('user', [ $toColumn ]));
}
/**

View file

@ -26,6 +26,7 @@ use Friendica\App\Router;
use Friendica\DI;
use Friendica\Module\Api\GNUSocial\GNUSocial\Config;
use Friendica\Test\src\Module\Api\ApiTest;
use Friendica\Test\Util\VFSTrait;
class ConfigTest extends ApiTest
{

View file

@ -1148,6 +1148,10 @@ function update_1502()
function update_1505()
{
if (!DBStructure::existsTable('config')) {
return Update::SUCCESS;
}
$conditions = [
"((`cat` = ?) AND ((`k` LIKE ?) OR (`k` = ?) OR (`k` LIKE ?) OR (`k` = ?))) OR " .
"((`cat` != ?) AND (`k` LIKE ?)) OR " .
@ -1175,3 +1179,18 @@ function update_1505()
return DBA::delete('config', $conditions) ? Update::SUCCESS : Update::FAILED;
}
function update_1508()
{
$config = DBA::selectToArray('config');
$newConfig = DI::config()->beginTransaction();
foreach ($config as $entry) {
$newConfig->set($entry['cat'], $entry['k'], $entry['v']);
}
$newConfig->commit();
DBA::e("TRUNCATE TABLE `config`");
}

View file

@ -49,7 +49,7 @@ $login_bg_color = '';
$modified = time();
if (DI::mode()->has(\Friendica\App\Mode::MAINTENANCEDISABLED)) {
DI::config()->load('frio');
DI::config()->reload();
// Default to hard-coded values for empty settings
$scheme = DI::config()->get('frio', 'scheme', DI::config()->get('frio', 'schema'));