$enabled = intval($this->getArgument(0));
- $this->config->set('system', 'maintenance', $enabled, false);
+ $transactionConfig = $this->config->transactional();
+
+ $transactionConfig->set('system', 'maintenance', $enabled);
$reason = $this->getArgument(1);
if ($enabled && $this->getArgument(1)) {
- $this->config->set('system', 'maintenance_reason', $this->getArgument(1), false);
+ $transactionConfig->set('system', 'maintenance_reason', $this->getArgument(1));
} else {
- $this->config->set('system', 'maintenance_reason', '', false);
+ $transactionConfig->delete('system', 'maintenance_reason');
}
- $this->config->save();
+ $transactionConfig->save();
if ($enabled) {
$mode_str = "maintenance mode";
return 1;
} finally {
$this->out('Leaving maintenance mode');
- $this->config->set('system', 'maintenance', false, false);
- $this->config->set('system', 'maintenance_reason', '', false);
- $this->config->save();
+ $this->config->transactional()
+ ->set('system', 'maintenance', false)
+ ->delete('system', 'maintenance_reason')
+ ->save();
}
// send relocate
namespace Friendica\Core\Config\Capability;
use Friendica\Core\Config\Exception\ConfigPersistenceException;
+use Friendica\Core\Config\Util\ConfigFileManager;
use Friendica\Core\Config\ValueObject\Cache;
/**
*/
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
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to set
* @param mixed $value The value to store
- * @param bool $autosave If true, implicit save the value
*
* @return bool Operation success
*
* @throws ConfigPersistenceException In case the persistence layer throws errors
*/
- public function set(string $cat, string $key, $value, bool $autosave = true): bool;
+ public function set(string $cat, string $key, $value): bool;
/**
- * Save back the overridden values of the config cache
+ * Creates a transactional config value store, which is used to set a bunch of values at once
*
- * @throws ConfigPersistenceException In case the persistence layer throws errors
+ * It relies on the current instance, so after save(), the values of this config class will get altered at once too.
+ *
+ * @return ISetConfigValuesTransactional
*/
- public function save();
+ public function transactional(): ISetConfigValuesTransactional;
/**
* 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
- * @param bool $autosave If true, implicit save the value
*
* @return bool
*
* @throws ConfigPersistenceException In case the persistence layer throws errors
*
*/
- public function delete(string $cat, string $key, bool $autosave = true): bool;
+ public function delete(string $cat, string $key): bool;
/**
* Returns the Config Cache
--- /dev/null
+<?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 ISetConfigValuesTransactional
+{
+ /**
+ * 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)
+ *
+ * @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);
+
+ /**
+ * 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;
+
+ /**
+ * Saves the node specific config values
+ *
+ * @throws ConfigPersistenceException In case the persistence layer throws errors
+ */
+ public function save(): void;
+}
namespace Friendica\Core\Config\Model;
use Friendica\Core\Config\Capability\IManageConfigValues;
+use Friendica\Core\Config\Capability\ISetConfigValuesTransactional;
use Friendica\Core\Config\Exception\ConfigFileException;
use Friendica\Core\Config\Exception\ConfigPersistenceException;
use Friendica\Core\Config\Util\ConfigFileManager;
return $this->configCache;
}
- /** {@inheritDoc} */
- public function save()
+ /** {@inheritDoc} */
+ public function transactional(): ISetConfigValuesTransactional
+ {
+ return new TransactionalConfig($this);
+ }
+
+ /**
+ * Saves the current Configuration back into the data config.
+ * @see ConfigFileManager::CONFIG_DATA_FILE
+ */
+ protected function save()
{
try {
$this->configFileManager->saveData($this->configCache);
$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)
{
}
/** {@inheritDoc} */
- public function set(string $cat, string $key, $value, bool $autosave = true): bool
+ public function set(string $cat, string $key, $value): bool
{
- $stored = $this->configCache->set($cat, $key, $value, Cache::SOURCE_DATA);
-
- if ($stored && $autosave) {
+ if ($this->configCache->set($cat, $key, $value, Cache::SOURCE_DATA)) {
$this->save();
+ return true;
+ } else {
+ return false;
}
-
- return $stored;
}
/** {@inheritDoc} */
- public function delete(string $cat, string $key, bool $autosave = true): bool
+ public function delete(string $cat, string $key): bool
{
- $removed = $this->configCache->delete($cat, $key);
-
- if ($removed && $autosave) {
+ if ($this->configCache->delete($cat, $key)) {
$this->save();
+ return true;
+ } else {
+ return false;
}
-
- return $removed;
}
}
--- /dev/null
+<?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\ISetConfigValuesTransactional;
+use Friendica\Core\Config\Exception\ConfigPersistenceException;
+use Friendica\Core\Config\ValueObject\Cache;
+
+/**
+ * config class, which sets values into a temporary buffer until "save()" is called
+ */
+class TransactionalConfig implements ISetConfigValuesTransactional
+{
+ /** @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();
+ }
+
+ /** {@inheritDoc} */
+ 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): ISetConfigValuesTransactional
+ {
+ $this->cache->set($cat, $key, $value, Cache::SOURCE_DATA);
+
+ return $this;
+ }
+
+
+ /** {@inheritDoc} */
+ public function delete(string $cat, string $key): ISetConfigValuesTransactional
+ {
+ $this->cache->delete($cat, $key);
+ $this->delCache->set($cat, $key, 'deleted');
+
+ return $this;
+ }
+
+ /** {@inheritDoc} */
+ public function save(): 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);
+ }
+ }
+}
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) {
+ if (!is_null($newConfig[$category][$key] ?? null)) {
+ unset($newConfig[$category][$key]);
+ unset($newSource[$category][$key]);
+ }
+ }
+ }
+ }
+
+ $newCache = new Cache();
+ $newCache->config = $newConfig;
+ $newCache->source = $newSource;
+
+ return $newCache;
+ }
}
Logger::warning('Pre update failed', ['version' => $version]);
DI::config()->set('system', 'update', Update::FAILED);
DI::lock()->release('dbupdate');
- DI::config()->set('system', 'maintenance', false, false);
- DI::config()->delete('system', 'maintenance_reason', false);
- DI::config()->save();
+ DI::config()->transactional()
+ ->set('system', 'maintenance', false)
+ ->delete('system', 'maintenance_reason')
+ ->save();
return $r;
} else {
Logger::notice('Pre update executed.', ['version' => $version]);
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', false, false);
- DI::config()->delete('system', 'maintenance_reason', false);
- DI::config()->save();
+ DI::config()->transactional()
+ ->set('system', 'maintenance', false)
+ ->delete('system', 'maintenance_reason')
+ ->save();
return $retval;
} else {
Logger::notice('Database structure update finished.', ['from' => $stored, 'to' => $current]);
Logger::warning('Post update failed', ['version' => $version]);
DI::config()->set('system', 'update', Update::FAILED);
DI::lock()->release('dbupdate');
- DI::config()->set('system', 'maintenance', false, false);
- DI::config()->delete('system', 'maintenance_reason', false);
- DI::config()->save();
+ DI::config()->transactional()
+ ->set('system', 'maintenance', false)
+ ->delete('system', 'maintenance_reason')
+ ->save();
return $r;
} else {
DI::config()->set('system', 'build', $version);
DI::config()->set('system', 'build', $current);
DI::config()->set('system', 'update', Update::SUCCESS);
DI::lock()->release('dbupdate');
- DI::config()->set('system', 'maintenance', false, false);
- DI::config()->delete('system', 'maintenance_reason', false);
- DI::config()->save();
+ DI::config()->transactional()
+ ->set('system', 'maintenance', false)
+ ->delete('system', 'maintenance_reason')
+ ->save();
Logger::notice('Update success.', ['from' => $stored, 'to' => $current]);
if ($sendMail) {
$status = self::update($verbose, true);
if ($enable_maintenance_mode) {
- DI::config()->set('system', 'maintenance', false, false);
- DI::config()->delete('system', 'maintenance_reason', false);
- DI::config()->save();
+ DI::config()->transactional()
+ ->set('system', 'maintenance', false)
+ ->delete('system', 'maintenance_reason')
+ ->save();
}
return $status;
self::checkFormSecurityTokenRedirectOnError('/admin/site', 'admin_site');
- $a = DI::app();
-
if (!empty($_POST['republish_directory'])) {
Worker::add(Worker::PRIORITY_LOW, 'Directory');
return;
$relay_user_tags = !empty($_POST['relay_user_tags']);
$active_panel = (!empty($_POST['active_panel']) ? "#" . trim($_POST['active_panel']) : '');
+ $transactionConfig = DI::config()->transactional();
+
// 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, false);
+ $transactionConfig->set('system', 'directory', $global_directory);
Worker::add(Worker::PRIORITY_LOW, 'Directory');
}
);
}
}
- DI::config()->set('system', 'ssl_policy' , $ssl_policy, false);
- DI::config()->set('system', 'maxloadavg' , $maxloadavg, false);
- DI::config()->set('system', 'min_memory' , $min_memory, false);
- DI::config()->set('system', 'optimize_tables' , $optimize_tables, false);
- DI::config()->set('system', 'contact_discovery' , $contact_discovery, false);
- DI::config()->set('system', 'synchronize_directory' , $synchronize_directory, false);
- DI::config()->set('system', 'poco_requery_days' , $poco_requery_days, false);
- DI::config()->set('system', 'poco_discovery' , $poco_discovery, false);
- DI::config()->set('system', 'poco_local_search' , $poco_local_search, false);
- DI::config()->set('system', 'nodeinfo' , $nodeinfo, false);
- DI::config()->set('config', 'sitename' , $sitename, false);
- DI::config()->set('config', 'sender_email' , $sender_email, false);
- DI::config()->set('system', 'suppress_tags' , $suppress_tags, false);
- DI::config()->set('system', 'shortcut_icon' , $shortcut_icon, false);
- DI::config()->set('system', 'touch_icon' , $touch_icon, false);
+ $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', false);
+ $transactionConfig->delete('system', 'banner');
} else {
- DI::config()->set('system', 'banner', $banner, false);
+ $transactionConfig->set('system', 'banner', $banner);
}
if (empty($email_banner)) {
- DI::config()->delete('system', 'email_banner', false);
+ $transactionConfig->delete('system', 'email_banner');
} else {
- DI::config()->set('system', 'email_banner', $email_banner, false);
+ $transactionConfig->set('system', 'email_banner', $email_banner);
}
if (empty($additional_info)) {
- DI::config()->delete('config', 'info', false);
+ $transactionConfig->delete('config', 'info');
} else {
- DI::config()->set('config', 'info', $additional_info, false);
+ $transactionConfig->set('config', 'info', $additional_info);
}
- DI::config()->set('system', 'language', $language, false);
- DI::config()->set('system', 'theme', $theme, false);
+ $transactionConfig->set('system', 'language', $language);
+ $transactionConfig->set('system', 'theme', $theme);
Theme::install($theme);
if ($theme_mobile == '---') {
- DI::config()->delete('system', 'mobile-theme', false);
+ $transactionConfig->delete('system', 'mobile-theme');
} else {
- DI::config()->set('system', 'mobile-theme', $theme_mobile, false);
+ $transactionConfig->set('system', 'mobile-theme', $theme_mobile);
}
if ($singleuser == '---') {
- DI::config()->delete('system', 'singleuser', false);
+ $transactionConfig->delete('system', 'singleuser');
} else {
- DI::config()->set('system', 'singleuser', $singleuser, false);
+ $transactionConfig->set('system', 'singleuser', $singleuser);
}
if (preg_match('/\d+(?:\s*[kmg])?/i', $maximagesize)) {
- DI::config()->set('system', 'maximagesize', $maximagesize, false);
+ $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, false);
- DI::config()->set('system', 'jpeg_quality' , $jpegimagequality, false);
-
- DI::config()->set('config', 'register_policy' , $register_policy, false);
- DI::config()->set('system', 'max_daily_registrations', $daily_registrations, false);
- DI::config()->set('system', 'account_abandon_days' , $abandon_days, false);
- DI::config()->set('config', 'register_text' , $register_text, false);
- DI::config()->set('system', 'allowed_sites' , $allowed_sites, false);
- DI::config()->set('system', 'allowed_email' , $allowed_email, false);
- DI::config()->set('system', 'forbidden_nicknames' , $forbidden_nicknames, false);
- DI::config()->set('system', 'system_actor_name' , $system_actor_name, false);
- DI::config()->set('system', 'no_oembed_rich_content' , $no_oembed_rich_content, false);
- DI::config()->set('system', 'allowed_oembed' , $allowed_oembed, false);
- DI::config()->set('system', 'block_public' , $block_public, false);
- DI::config()->set('system', 'publish_all' , $force_publish, false);
- DI::config()->set('system', 'newuser_private' , $newuser_private, false);
- DI::config()->set('system', 'enotify_no_content' , $enotify_no_content, false);
- DI::config()->set('system', 'disable_embedded' , $disable_embedded, false);
- DI::config()->set('system', 'allow_users_remote_self', $allow_users_remote_self, false);
- DI::config()->set('system', 'explicit_content' , $explicit_content, false);
- DI::config()->set('system', 'proxify_content' , $proxify_content, false);
- DI::config()->set('system', 'cache_contact_avatar' , $cache_contact_avatar, false);
- DI::config()->set('system', 'check_new_version_url' , $check_new_version_url, false);
-
- DI::config()->set('system', 'block_extended_register', !$enable_multi_reg, false);
- DI::config()->set('system', 'no_openid' , !$enable_openid, false);
- DI::config()->set('system', 'no_regfullname' , !$enable_regfullname, false);
- DI::config()->set('system', 'register_notification' , $register_notification, false);
- DI::config()->set('system', 'community_page_style' , $community_page_style, false);
- DI::config()->set('system', 'max_author_posts_community_page', $max_author_posts_community_page, false);
- DI::config()->set('system', 'verifyssl' , $verifyssl, false);
- DI::config()->set('system', 'proxyuser' , $proxyuser, false);
- DI::config()->set('system', 'proxy' , $proxy, false);
- DI::config()->set('system', 'curl_timeout' , $timeout, false);
- DI::config()->set('system', 'imap_disabled' , !$mail_enabled && function_exists('imap_open'), false);
- DI::config()->set('system', 'ostatus_disabled' , !$ostatus_enabled, false);
- DI::config()->set('system', 'diaspora_enabled' , $diaspora_enabled, false);
-
- DI::config()->set('config', 'private_addons' , $private_addons, false);
-
- DI::config()->set('system', 'force_ssl' , $force_ssl, false);
- DI::config()->set('system', 'hide_help' , !$show_help, false);
-
- DI::config()->set('system', 'dbclean' , $dbclean, false);
- DI::config()->set('system', 'dbclean-expire-days' , $dbclean_expire_days, false);
- DI::config()->set('system', 'dbclean_expire_conversation', $dbclean_expire_conv, false);
+ $transactionConfig->set('system', 'max_image_length' , $maximagelength);
+ $transactionConfig->set('system', 'jpeg_quality' , $jpegimagequality);
+
+ $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);
+
+ $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);
+
+ $transactionConfig->set('config', 'private_addons' , $private_addons);
+
+ $transactionConfig->set('system', 'force_ssl' , $force_ssl);
+ $transactionConfig->set('system', 'hide_help' , !$show_help);
+
+ $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, false);
+ $transactionConfig->set('system', 'dbclean-expire-unclaimed', $dbclean_unclaimed);
- DI::config()->set('system', 'max_comments', $max_comments, false);
- DI::config()->set('system', 'max_display_comments', $max_display_comments, false);
+ $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, false);
+ $transactionConfig->set('system', 'temppath', $temppath);
- DI::config()->set('system', 'only_tag_search' , $only_tag_search, false);
- DI::config()->set('system', 'compute_group_counts', $compute_group_counts, false);
+ $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, false);
- DI::config()->set('system', 'worker_fastlane' , $worker_fastlane, false);
+ $transactionConfig->set('system', 'worker_queues' , $worker_queues);
+ $transactionConfig->set('system', 'worker_fastlane' , $worker_fastlane);
- DI::config()->set('system', 'relay_directly' , $relay_directly, false);
- DI::config()->set('system', 'relay_scope' , $relay_scope, false);
- DI::config()->set('system', 'relay_server_tags', $relay_server_tags, false);
- DI::config()->set('system', 'relay_deny_tags' , $relay_deny_tags, false);
- DI::config()->set('system', 'relay_user_tags' , $relay_user_tags, false);
+ $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);
- DI::config()->save();
+ $transactionConfig->save();
DI::baseUrl()->redirect('admin/site' . $active_panel);
}
if (DI::config()->get('system', 'directory_submit_url') &&
!DI::config()->get('system', 'directory')) {
- DI::config()->set('system', 'directory', dirname(DI::config()->get('system', 'directory_submit_url')), false);
- DI::config()->delete('system', 'directory_submit_url', false);
+ DI::config()->set('system', 'directory', dirname(DI::config()->get('system', 'directory_submit_url')));
+ DI::config()->delete('system', 'directory_submit_url');
}
/* Installed themes */
$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);
+
+ $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->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'));
+ }
+
+ /**
+ * @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'));
+ }
}
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\ConfigFileManager;
$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);
$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);
}
$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);
$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);
$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);
$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);
$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);
$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);
$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);
->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);
->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);
// overwrite some data and save it back to the config file
- $configCache->set('system', 'test', 'it', \Friendica\Core\Config\ValueObject\Cache::SOURCE_DATA);
- $configCache->set('config', 'test', 'it', \Friendica\Core\Config\ValueObject\Cache::SOURCE_DATA);
- $configCache->set('system', 'test_2', 2, \Friendica\Core\Config\ValueObject\Cache::SOURCE_DATA);
+ $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);
$configFileLoader->saveData($configCache);
// Reload the configCache with the new values
- $configCache2 = new \Friendica\Core\Config\ValueObject\Cache();
+ $configCache2 = new Cache();
$configFileLoader->setupCache($configCache2);
self::assertEquals($configCache, $configCache2);
],
'config' => [
'test' => 'it'
- ]], $configCache2->getDataBySource(\Friendica\Core\Config\ValueObject\Cache::SOURCE_DATA));
+ ]], $configCache2->getDataBySource(Cache::SOURCE_DATA));
}
}
--- /dev/null
+<?php
+
+namespace Friendica\Test\src\Core\Config;
+use Friendica\Core\Config\Capability\ISetConfigValuesTransactional;
+use Friendica\Core\Config\Model\Config;
+use Friendica\Core\Config\Model\TransactionalConfig;
+use Friendica\Core\Config\Util\ConfigFileManager;
+use Friendica\Core\Config\ValueObject\Cache;
+use Friendica\Test\MockedTest;
+use Friendica\Test\Util\VFSTrait;
+
+class TransactionalConfigTest 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());
+ $transactionalConfig = new TransactionalConfig($config);
+
+ self::assertInstanceOf(ISetConfigValuesTransactional::class, $transactionalConfig);
+ self::assertInstanceOf(TransactionalConfig::class, $transactionalConfig);
+ }
+
+ public function testTransactionalConfig()
+ {
+ $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');
+
+ $transactionalConfig = new TransactionalConfig($config);
+ self::assertEquals('value1', $transactionalConfig->get('config', 'key1'));
+ self::assertEquals('value2', $transactionalConfig->get('system', 'key2'));
+ self::assertEquals('valueDel', $transactionalConfig->get('system', 'keyDel'));
+ self::assertEquals('catDel', $transactionalConfig->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
+ $transactionalConfig->set('transaction', 'key3', 'value3');
+ // overwrite key-value
+ $transactionalConfig->set('config', 'key1', 'changedValue1');
+ // delete key-value
+ $transactionalConfig->delete('system', 'keyDel');
+ // delete last key of category - so the category is gone
+ $transactionalConfig->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', $transactionalConfig->get('transaction', 'key3'));
+ self::assertEquals('changedValue1', $transactionalConfig->get('config', 'key1'));
+ self::assertNull($transactionalConfig->get('system', 'keyDel'));
+ self::assertNull($transactionalConfig->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!
+ $transactionalConfig->save();
+
+ // 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', $transactionalConfig->get('transaction', 'key3'));
+ self::assertEquals('changedValue1', $transactionalConfig->get('config', 'key1'));
+ self::assertNull($transactionalConfig->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);
+ }
+}
{
$config = DBA::selectToArray('config');
+ $newConfig = DI::config()->transactional();
+
foreach ($config as $entry) {
- DI::config()->set($entry['cat'], $entry['k'], $entry['v'], false);
+ $newConfig->set($entry['cat'], $entry['k'], $entry['v']);
}
- DI::config()->save();
+ $newConfig->save();
DBA::e("DELETE FROM `config`");
}