Commit a32a7d3d authored by Marc Egger's avatar Marc Egger
Browse files

Refs #10120 finetune export and import forms on Database update

parent 802ef88d
Pipeline #3619 failed with stages
in 43 seconds
......@@ -144,7 +144,10 @@ class DatabaseUpdate {
if ($dbUpdate === SYSTEM_DB_UPDATE_ALWAYS || ($dbUpdate === SYSTEM_DB_UPDATE_AUTO && $new != $old)) {
FormAsFile::importAllForms($this->db, true);
if ($old !== false) {
// Import files from form path. (Creates path and exports all forms to it, if it doesn't exist)
FormAsFile::importAllForms($this->db, true, true);
}
$newFunctionHash = $this->updateSqlFunctions($versionInfo[QFQ_VERSION_KEY_FUNCTION_HASH] ?? '');
if (null !== $newFunctionHash) {
......@@ -162,7 +165,14 @@ class DatabaseUpdate {
$versionInfo[QFQ_VERSION_KEY] = $new;
$this->setDatabaseVersion($versionInfo);
FormAsFIle::exportAllForms($this->db);
if ($old === false) {
// new installation: export native forms + import existing user forms
FormAsFIle::exportAllForms($this->db, false);
FormAsFile::importAllForms($this->db);
} else {
// Export forms + delete files which were removed since the import above
FormAsFIle::exportAllForms($this->db, true);
}
}
if ($old === false) {
......
......@@ -8,6 +8,7 @@ use IMATHUZH\Qfq\Core\Helper\HelperFile;
use IMATHUZH\Qfq\Core\Helper\OnString;
use IMATHUZH\Qfq\Core\Helper\SqlQuery;
// TODO: exportAllForms() mit deleteFiles true testen
// TODO: queryFormNames is executed before Form table exists. Add error to sql and make sure this does not happen in DatabaseUpdate.php
// TODO: gibt es UPDATE/INSERT/DELETE statements die an Form/FormElement arbeiten koennen, die nicht nur durch doForm aufgerufen werden?
//
......@@ -430,63 +431,60 @@ class FormAsFile
}
/**
* Import all form files and DELETE forms in the DB for which there are not form files.
* Import all form files into the database.
* If the file folder does not exist, it is created and all forms from the DB are exported.
*
* @param Database $database
* @param bool $enforceWritable
* @param bool $enforceWritable Throw exception if one of the form files is not writable by current user.
* @param bool $deleteFromDB Delete forms from DB if there are no corresponding form files.
* @throws \CodeException
* @throws \DbException
* @throws \UserFormException
*/
public static function importAllForms(Database $database, bool $enforceWritable = false): void
public static function importAllForms(Database $database, bool $enforceWritable = false, bool $deleteFromDB = false): void
{
// Import all form files
$formPath = self::formPath($database);
$files = scandir($formPath);
if ($files === false) {
throw new \UserFormException(json_encode([
ERROR_MESSAGE_TO_USER => "Reading directory failed.",
ERROR_MESSAGE_TO_DEVELOPER => "Can't read directory: " . $formPath]),
ERROR_IO_READ_FILE);
}
$formFileNames = [];
foreach ($files as $file) {
$fileInfo = pathinfo($file);
if ($fileInfo['extension'] === 'json') {
$fileName = $fileInfo['filename'];
$formFileNames[] = $fileName;
self::importForm($fileName, $database);
$formFileNames = self::formFileNames($database);
foreach ($formFileNames as $formFileName) {
self::importForm($formFileName, $database);
if ($enforceWritable) {
self::enforceFormFileWritable($fileName, $database);
}
self::enforceFormFileWritable($formFileName, $database);
}
}
// Delete all forms which are in DB but not in files
if ($deleteFromDB) {
$formNamesDB = self::queryAllFormNames($database);
$formsToDelete = array_diff($formNamesDB, $formFileNames);
foreach ($formsToDelete as $formToDelete) {
self::deleteFormDB($formToDelete, $database);
}
}
}
/**
* Export all forms in database to form files.
* Warning: This overwrites form files without any checks or warning. Use cautiously.
*
* Note: Does not delete form files if the corresponding forms are not present in the database.
*
* @param Database $database
* @param bool $deleteFiles Delete form files without a corresponding form record in the DB.
* @throws \CodeException
* @throws \DbException
* @throws \UserFormException
*/
public static function exportAllForms(Database $database): void
public static function exportAllForms(Database $database, bool $deleteFiles = false): void
{
$formNamesDB = self::queryAllFormNames($database);
foreach ($formNamesDB as $formNameDB) {
self::exportForm($formNameDB, $database);
}
if ($deleteFiles) {
$formFileNames = self::formFileNames($database);
$filesToDelete = array_diff($formFileNames, $formNamesDB);
foreach ($filesToDelete as $fileToDelete) {
self::deleteFormFile($fileToDelete, $database);
}
}
}
/**
......@@ -647,4 +645,32 @@ class FormAsFile
$FORM = TABLE_NAME_FORM;
return array_column($database->sql("SELECT `$NAME` FROM `$FORM`", ROW_REGULAR), $NAME);
}
/**
* Return list of form file names contained in the form path (without suffix).
*
* @param Database $database
* @return array|false
* @throws \CodeException
* @throws \DbException
* @throws \UserFormException
*/
private static function formFileNames(Database $database): array
{
$formPath = self::formPath($database);
$files = scandir($formPath);
if ($files === false) {
throw new \UserFormException(json_encode([
ERROR_MESSAGE_TO_USER => "Reading directory failed.",
ERROR_MESSAGE_TO_DEVELOPER => "Can't read directory: " . $formPath]),
ERROR_IO_READ_FILE);
}
return $jsonFileNames = array_reduce($files, function ($result, $file) {
$fileInfo = pathinfo($file);
if ($fileInfo['extension'] === 'json') {
$result[] = $fileInfo['filename'];
}
return $result;
}, []);
}
}
\ No newline at end of file
......@@ -494,7 +494,7 @@ class Report {
// import form files if changed + delete Forms without form file
if (FormAsFile::isFormQuery($sql)) {
FormAsFile::importAllForms($this->db);
FormAsFile::importAllForms($this->db, false, true);
}
//Execute SQL. All errors have been already catched.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment