Replace setMultiple() by startTransaction() and commitTransaction()

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
This commit is contained in:
Pablo Zmdl 2026-01-23 16:40:45 +01:00
parent 8f123478b0
commit ec9b4b9b38
2 changed files with 70 additions and 66 deletions

View file

@ -123,11 +123,11 @@ readonly class DockerController {
} }
public function StartBackupContainerRestore(Request $request, Response $response, array $args) : Response { public function StartBackupContainerRestore(Request $request, Response $response, array $args) : Response {
$this->configurationManager->setMultiple(function (ConfigurationManager $confManager) use ($request) { $this->configurationManager->startTransaction();
$confManager->backupMode = 'restore'; $this->configurationManager->backupMode = 'restore';
$confManager->selectedRestoreTime = $request->getParsedBody()['selected_restore_time'] ?? ''; $this->configurationManager->selectedRestoreTime = $request->getParsedBody()['selected_restore_time'] ?? '';
$confManager->restoreExcludePreviews = isset($request->getParsedBody()['restore-exclude-previews']); $this->configurationManager->restoreExcludePreviews = isset($request->getParsedBody()['restore-exclude-previews']);
}); $this->configurationManager->commitTransaction();
$id = self::TOP_CONTAINER; $id = self::TOP_CONTAINER;
$forceStopNextcloud = true; $forceStopNextcloud = true;
@ -152,10 +152,10 @@ readonly class DockerController {
} }
public function StartBackupContainerTest(Request $request, Response $response, array $args) : Response { public function StartBackupContainerTest(Request $request, Response $response, array $args) : Response {
$this->configurationManager->setMultiple(function (ConfigurationManager $confManager) { $this->configurationManager->startTransaction();
$confManager->backupMode = 'test'; $this->configurationManager->backupMode = 'test';
$confManager->instance_restore_attempt = false; $this->configurationManager->instance_restore_attempt = false;
}); $this->configurationManager->commitTransaction();
$id = self::TOP_CONTAINER; $id = self::TOP_CONTAINER;
$this->PerformRecursiveContainerStop($id); $this->PerformRecursiveContainerStop($id);
@ -177,13 +177,14 @@ readonly class DockerController {
$port = 443; $port = 443;
} }
$this->configurationManager->setMultiple(function (ConfigurationManager $confManager) use ($request, $host, $port, $path) { $this->configurationManager->startTransaction();
$confManager->install_latest_major = isset($request->getParsedBody()['install_latest_major']); $this->configurationManager->install_latest_major = isset($request->getParsedBody()['install_latest_major']);
// set AIO_URL // set AIO_URL
$confManager->AIO_URL = $host . ':' . (string)$port . $path; $this->configurationManager->AIO_URL = $host . ':' . (string)$port . $path;
// set wasStartButtonClicked // set wasStartButtonClicked
$confManager->wasStartButtonClicked = true; $this->configurationManager->wasStartButtonClicked = true;
}); $this->configurationManager->commitTransaction();
// Do not pull container images in case 'bypass_container_update' is set via url params // Do not pull container images in case 'bypass_container_update' is set via url params
// Needed for local testing // Needed for local testing
$pullImage = !isset($request->getParsedBody()['bypass_container_update']); $pullImage = !isset($request->getParsedBody()['bypass_container_update']);

View file

@ -193,25 +193,27 @@ class ConfigurationManager
private function set(string $key, mixed $value) : void { private function set(string $key, mixed $value) : void {
$this->GetConfig(); $this->GetConfig();
$this->config[$key] = $value; $this->config[$key] = $value;
// Only write if this isn't called via setMultiple(). // Only write if this isn't called in between startTransaction() and commitTransaction().
if ($this->noWrite !== true) { if ($this->noWrite !== true) {
$this->WriteConfig(); $this->WriteConfig();
} }
} }
/** /**
* This allows to assign multiple attributes without saving the config to disk in between (as would * This allows to assign multiple attributes without saving the config to disk in between. It must be
* calling set() do). * followed by a call to commitTransaction(), which then writes all changes to disk.
*/ */
public function setMultiple(\Closure $closure) : void { public function startTransaction() : void {
$this->GetConfig();
$this->noWrite = true; $this->noWrite = true;
try { }
$this->GetConfig();
$closure($this); /**
$this->WriteConfig(); * This allows to assign multiple attributes without saving the config to disk in between.
} finally { */
$this->noWrite = false; public function commitTransaction() : void {
} $this->WriteConfig();
$this->noWrite = false;
} }
public function GetAndGenerateSecret(string $secretId) : string { public function GetAndGenerateSecret(string $secretId) : string {
@ -419,13 +421,14 @@ class ConfigurationManager
} }
} }
$this->setMultiple(function (ConfigurationManager $confManager) use ($domain) { $this->startTransaction();
// Write domain // Write domain
// Don't set the domain via the attribute, or we create a loop. // Don't set the domain via the attribute, or we create a loop.
$confManager->set('domain', $domain); $this->set('domain', $domain);
// Reset the borg restore password when setting the domain // Reset the borg restore password when setting the domain
$confManager->borg_restore_password = ''; $this->borg_restore_password = '';
}); $this->startTransaction();
$this->commitTransaction();
} }
public function GetBaseDN() : string { public function GetBaseDN() : string {
@ -441,10 +444,10 @@ class ConfigurationManager
*/ */
public function SetBorgLocationVars(string $location, string $repo) : void { public function SetBorgLocationVars(string $location, string $repo) : void {
$this->ValidateBorgLocationVars($location, $repo); $this->ValidateBorgLocationVars($location, $repo);
$this->setMultiple(function (ConfigurationManager $confManager) use ($location, $repo) { $this->startTransaction();
$confManager->borg_backup_host_location = $location; $this->borg_backup_host_location = $location;
$confManager->borg_remote_repo = $repo; $this->borg_remote_repo = $repo;
}); $this->commitTransaction();
} }
private function ValidateBorgLocationVars(string $location, string $repo) : void { private function ValidateBorgLocationVars(string $location, string $repo) : void {
@ -490,10 +493,10 @@ class ConfigurationManager
public function DeleteBorgBackupLocationItems() : void { public function DeleteBorgBackupLocationItems() : void {
// Delete the variables // Delete the variables
$this->setMultiple(function (ConfigurationManager $confManager) { $this->startTransaction();
$confManager->borg_backup_host_location = ''; $this->borg_backup_host_location = '';
$confManager->borg_remote_repo = ''; $this->borg_remote_repo = '';
}); $this->commitTransaction();
// Also delete the borg config file to be able to start over // Also delete the borg config file to be able to start over
if (file_exists(DataConst::GetBackupKeyFile())) { if (file_exists(DataConst::GetBackupKeyFile())) {
@ -513,12 +516,12 @@ class ConfigurationManager
throw new InvalidSettingConfigurationException("Please enter the password!"); throw new InvalidSettingConfigurationException("Please enter the password!");
} }
$this->setMultiple(function (ConfigurationManager $confManager) use ($location, $repo, $password) { $this->startTransaction();
$confManager->borg_backup_host_location = $location; $this->borg_backup_host_location = $location;
$confManager->borg_remote_repo = $repo; $this->borg_remote_repo = $repo;
$confManager->borg_restore_password = $password; $this->borg_restore_password = $password;
$confManager->instance_restore_attempt = true; $this->instance_restore_attempt = true;
}); $this->commitTransaction();
} }
/** /**
@ -976,25 +979,25 @@ class ConfigurationManager
if ($input === []) { if ($input === []) {
return; return;
} }
$this->setMultiple(function(ConfigurationManager $confManager) use ($input) { $this->startTransaction();
foreach ($input as $variable) { foreach ($input as $variable) {
if (!is_string($variable) || !str_contains($variable, '=')) { if (!is_string($variable) || !str_contains($variable, '=')) {
error_log("Invalid input: '$variable' is not a string or does not contain an equal sign ('=')"); error_log("Invalid input: '$variable' is not a string or does not contain an equal sign ('=')");
continue; continue;
}
$keyWithValue = $confManager->replaceEnvPlaceholders($variable);
// Pad the result with nulls so psalm is happy (and we don't risk to run into warnings in case
// the check for an equal sign from above gets changed).
[$key, $value] = explode('=', $keyWithValue, 2) + [null, null];
if ($value === null) {
error_log("Invalid input: '$keyWithValue' has no value after the equal sign");
} else if (!property_exists($confManager, $key)) {
error_log("Error: '$key' is not a valid configuration key (in '$keyWithValue')");
} else {
$confManager->$key = $value;
}
} }
}); $keyWithValue = $confManager->replaceEnvPlaceholders($variable);
// Pad the result with nulls so psalm is happy (and we don't risk to run into warnings in case
// the check for an equal sign from above gets changed).
[$key, $value] = explode('=', $keyWithValue, 2) + [null, null];
if ($value === null) {
error_log("Invalid input: '$keyWithValue' has no value after the equal sign");
} else if (!property_exists($confManager, $key)) {
error_log("Error: '$key' is not a valid configuration key (in '$keyWithValue')");
} else {
$confManager->$key = $value;
}
}
$this->commitTransaction();
} }
// //