]> git.mxchange.org Git - friendica.git/commitdiff
Introduce ISetConfigValuesTransactional for transactional config behaviour
authorPhilipp <admin@philipp.info>
Tue, 3 Jan 2023 13:18:53 +0000 (14:18 +0100)
committerPhilipp <admin@philipp.info>
Tue, 3 Jan 2023 13:22:07 +0000 (14:22 +0100)
14 files changed:
src/Console/Maintenance.php
src/Console/Relocate.php
src/Core/Config/Capability/IManageConfigValues.php
src/Core/Config/Capability/ISetConfigValuesTransactional.php [new file with mode: 0644]
src/Core/Config/Model/Config.php
src/Core/Config/Model/TransactionalConfig.php [new file with mode: 0644]
src/Core/Config/ValueObject/Cache.php
src/Core/Update.php
src/Database/DBStructure.php
src/Module/Admin/Site.php
tests/src/Core/Config/Cache/CacheTest.php
tests/src/Core/Config/Cache/ConfigFileLoaderTest.php
tests/src/Core/Config/TransactionalConfigTest.php [new file with mode: 0644]
update.php

index bd3aef7c290b7ea425727a555ab8d04a709558b1..6a11eb2bb57ba9027a8aef828774b0e56063a57e 100644 (file)
@@ -100,17 +100,19 @@ HELP;
 
                $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";
index 8a76c92070777e62c7c1c090008bd9a2a8d4e395..7a2ef1d0712e02af8e259d1734d593c2aafa199e 100644 (file)
@@ -189,9 +189,10 @@ HELP;
                        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
index 88fa96314ba7056038808ecd48c310d17957ef26..42ebea0004f207693015b7397cfab2d6082c880a 100644 (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;
 
 /**
@@ -57,6 +58,20 @@ interface IManageConfigValues
         */
        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
         *
@@ -67,20 +82,21 @@ interface IManageConfigValues
         * @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.
@@ -89,14 +105,13 @@ interface IManageConfigValues
         *
         * @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
diff --git a/src/Core/Config/Capability/ISetConfigValuesTransactional.php b/src/Core/Config/Capability/ISetConfigValuesTransactional.php
new file mode 100644 (file)
index 0000000..9c58427
--- /dev/null
@@ -0,0 +1,84 @@
+<?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;
+}
index 7829b75ffd905221878b328cd5e32443cd2dc77a..24f5fd3b590a1f105e7be081e342541d42ed3249 100644 (file)
@@ -22,6 +22,7 @@
 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;
@@ -61,8 +62,17 @@ class Config implements IManageConfigValues
                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);
@@ -84,6 +94,13 @@ class Config implements IManageConfigValues
                $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)
        {
@@ -91,26 +108,24 @@ class Config implements IManageConfigValues
        }
 
        /** {@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;
        }
 }
diff --git a/src/Core/Config/Model/TransactionalConfig.php b/src/Core/Config/Model/TransactionalConfig.php
new file mode 100644 (file)
index 0000000..e9aa711
--- /dev/null
@@ -0,0 +1,89 @@
+<?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);
+               }
+       }
+}
index a074414bfc616d9334cec7dfcbecdc71ac25392e..305c00d3305b6abf3ce062f1d874149dc5b317b9 100644 (file)
@@ -279,4 +279,71 @@ 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) {
+                                       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;
+       }
 }
index 9a2ebe1bba8db060cd4f6ac3310e7344ef1d124f..a02645783357b675ab111f764f78005126ed38a3 100644 (file)
@@ -160,9 +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', 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]);
@@ -182,9 +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', 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]);
@@ -200,9 +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', 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);
@@ -213,9 +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', 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) {
index e3af408b9e4f9991e26e4c9e54dbb4f712004408..ed2a5e30e7cb21e4abf618b1fe2f39c103ce503f 100644 (file)
@@ -182,9 +182,10 @@ class DBStructure
                $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;
index f572d3e7256b155cb6fe7337e273f2cf20b4b4bc..50a7ee86866d264314cd76175daba8e7a007182d 100644 (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()->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');
                }
 
@@ -194,133 +194,133 @@ class Site extends BaseAdmin
                                );
                        }
                }
-               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);
        }
@@ -334,8 +334,8 @@ class Site extends BaseAdmin
 
                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 */
index 8b2c24da3ee9179686a4c48754d0d5f2b6aca449..9d72774c40e29170bd2a0ec4eff4945fe8eccc76 100644 (file)
@@ -358,4 +358,52 @@ class CacheTest extends MockedTest
                $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'));
+       }
 }
index e8443611f2bfd0992946736ab6659a014d03d481..aed55f429e599e12108cd804c4ecf2e9f564f4dd 100644 (file)
@@ -21,8 +21,8 @@
 
 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;
@@ -51,7 +51,7 @@ class ConfigFileLoaderTest extends MockedTest
                        $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);
 
@@ -77,7 +77,7 @@ class ConfigFileLoaderTest extends MockedTest
                        $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);
        }
@@ -106,7 +106,7 @@ class ConfigFileLoaderTest extends MockedTest
                        $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);
 
@@ -143,7 +143,7 @@ class ConfigFileLoaderTest extends MockedTest
                        $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);
 
@@ -179,7 +179,7 @@ class ConfigFileLoaderTest extends MockedTest
                        $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);
 
@@ -270,7 +270,7 @@ class ConfigFileLoaderTest extends MockedTest
                        $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);
 
@@ -304,7 +304,7 @@ class ConfigFileLoaderTest extends MockedTest
                        $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);
 
@@ -338,7 +338,7 @@ class ConfigFileLoaderTest extends MockedTest
                        $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,7 +380,7 @@ 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);
 
@@ -403,18 +403,18 @@ 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);
 
                // 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);
@@ -425,6 +425,6 @@ class ConfigFileLoaderTest extends MockedTest
                        ],
                        'config' => [
                                'test' => 'it'
-                       ]], $configCache2->getDataBySource(\Friendica\Core\Config\ValueObject\Cache::SOURCE_DATA));
+                       ]], $configCache2->getDataBySource(Cache::SOURCE_DATA));
        }
 }
diff --git a/tests/src/Core/Config/TransactionalConfigTest.php b/tests/src/Core/Config/TransactionalConfigTest.php
new file mode 100644 (file)
index 0000000..b42fee9
--- /dev/null
@@ -0,0 +1,110 @@
+<?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);
+       }
+}
index ad33dde01206326415817a49749feab505791815..7ad6e432feab92a3f50cb00d7afef6828c4ab95b 100644 (file)
@@ -1184,11 +1184,13 @@ function update_1508()
 {
        $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`");
 }