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 { ...@@ -144,7 +144,10 @@ class DatabaseUpdate {
if ($dbUpdate === SYSTEM_DB_UPDATE_ALWAYS || ($dbUpdate === SYSTEM_DB_UPDATE_AUTO && $new != $old)) { 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] ?? ''); $newFunctionHash = $this->updateSqlFunctions($versionInfo[QFQ_VERSION_KEY_FUNCTION_HASH] ?? '');
if (null !== $newFunctionHash) { if (null !== $newFunctionHash) {
...@@ -162,7 +165,14 @@ class DatabaseUpdate { ...@@ -162,7 +165,14 @@ class DatabaseUpdate {
$versionInfo[QFQ_VERSION_KEY] = $new; $versionInfo[QFQ_VERSION_KEY] = $new;
$this->setDatabaseVersion($versionInfo); $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) { if ($old === false) {
......
...@@ -8,6 +8,7 @@ use IMATHUZH\Qfq\Core\Helper\HelperFile; ...@@ -8,6 +8,7 @@ use IMATHUZH\Qfq\Core\Helper\HelperFile;
use IMATHUZH\Qfq\Core\Helper\OnString; use IMATHUZH\Qfq\Core\Helper\OnString;
use IMATHUZH\Qfq\Core\Helper\SqlQuery; 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: 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? // TODO: gibt es UPDATE/INSERT/DELETE statements die an Form/FormElement arbeiten koennen, die nicht nur durch doForm aufgerufen werden?
// //
...@@ -430,43 +431,34 @@ class FormAsFile ...@@ -430,43 +431,34 @@ 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 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 \CodeException
* @throws \DbException * @throws \DbException
* @throws \UserFormException * @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 // Import all form files
$formPath = self::formPath($database); $formFileNames = self::formFileNames($database);
$files = scandir($formPath); foreach ($formFileNames as $formFileName) {
if ($files === false) { self::importForm($formFileName, $database);
throw new \UserFormException(json_encode([ if ($enforceWritable) {
ERROR_MESSAGE_TO_USER => "Reading directory failed.", self::enforceFormFileWritable($formFileName, $database);
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);
if ($enforceWritable) {
self::enforceFormFileWritable($fileName, $database);
}
} }
} }
// Delete all forms which are in DB but not in files // Delete all forms which are in DB but not in files
$formNamesDB = self::queryAllFormNames($database); if ($deleteFromDB) {
$formsToDelete = array_diff($formNamesDB, $formFileNames); $formNamesDB = self::queryAllFormNames($database);
foreach ($formsToDelete as $formToDelete) { $formsToDelete = array_diff($formNamesDB, $formFileNames);
self::deleteFormDB($formToDelete, $database); foreach ($formsToDelete as $formToDelete) {
self::deleteFormDB($formToDelete, $database);
}
} }
} }
...@@ -474,19 +466,25 @@ class FormAsFile ...@@ -474,19 +466,25 @@ class FormAsFile
* Export all forms in database to form files. * Export all forms in database to form files.
* Warning: This overwrites form files without any checks or warning. Use cautiously. * 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 Database $database
* @param bool $deleteFiles Delete form files without a corresponding form record in the DB.
* @throws \CodeException * @throws \CodeException
* @throws \DbException * @throws \DbException
* @throws \UserFormException * @throws \UserFormException
*/ */
public static function exportAllForms(Database $database): void public static function exportAllForms(Database $database, bool $deleteFiles = false): void
{ {
$formNamesDB = self::queryAllFormNames($database); $formNamesDB = self::queryAllFormNames($database);
foreach ($formNamesDB as $formNameDB) { foreach ($formNamesDB as $formNameDB) {
self::exportForm($formNameDB, $database); 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 ...@@ -647,4 +645,32 @@ class FormAsFile
$FORM = TABLE_NAME_FORM; $FORM = TABLE_NAME_FORM;
return array_column($database->sql("SELECT `$NAME` FROM `$FORM`", ROW_REGULAR), $NAME); 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 { ...@@ -494,7 +494,7 @@ class Report {
// import form files if changed + delete Forms without form file // import form files if changed + delete Forms without form file
if (FormAsFile::isFormQuery($sql)) { if (FormAsFile::isFormQuery($sql)) {
FormAsFile::importAllForms($this->db); FormAsFile::importAllForms($this->db, false, true);
} }
//Execute SQL. All errors have been already catched. //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