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

form as file: match form names case sensitive from database

parent d484d323
Pipeline #4095 passed with stages
in 4 minutes and 15 seconds
......@@ -8,12 +8,14 @@
namespace IMATHUZH\Qfq\Core\Database;
use IMATHUZH\Qfq\Core\Exception\Thrower;
use IMATHUZH\Qfq\Core\Helper\BindParam;
use IMATHUZH\Qfq\Core\Helper\HelperFile;
use IMATHUZH\Qfq\Core\Helper\HelperFormElement;
use IMATHUZH\Qfq\Core\Helper\Logger;
use IMATHUZH\Qfq\Core\Helper\OnArray;
use IMATHUZH\Qfq\Core\Helper\Path;
use IMATHUZH\Qfq\Core\Helper\SqlQuery;
use IMATHUZH\Qfq\Core\Store\Store;
/**
......@@ -1062,4 +1064,42 @@ class Database {
$this->sql('DELETE FROM `' . TABLE_NAME_SPLIT . '` WHERE `tableName`=? AND `xId`=?', ROW_REGULAR, [$tableName, $xId]);
}
/**
* Returns either empty array or an array containing the selected columns.
* $formName is matched case sensitively.
* Throws exception if more than one form was found with the exact same name.
*
* @param string $formName
* @param array|null $columnsToSelect
* @return array|bool|int|string
* @throws \CodeException
* @throws \DbException
* @throws \UserFormException
*/
public function selectFormByName(string $formName, array $columnsToSelect = null)
{
// make sure to select column 'name'
if (is_array($columnsToSelect) && !in_array(F_NAME, $columnsToSelect)) {
$columnsToSelect[] = F_NAME;
}
// select
list($sql, $parameterArray) = SqlQuery::selectFormByName($formName, $columnsToSelect);
$forms = $this->sql($sql, ROW_REGULAR, $parameterArray);
$forms = array_filter($forms, function ($f) use ($formName) {
return $formName === $f[F_NAME];
});
// Check for case sensitive matches
$count = count($forms);
if ($count > 1) {
Thrower::userFormException("Multiple forms with the exact same name: '$formName' (case sensitive). Expected one or zero rows, got $count rows");
} else if ($count === 1) {
return reset($forms); // returns first element
} else {
return [];
}
}
}
\ No newline at end of file
......@@ -36,29 +36,30 @@ class FormAsFile
public static function importForm(string $formName, Database $database, bool $keepIfNeverExported = true): bool
{
// Get file stats from database form
list($sql, $parameterArray) = SqlQuery::selectFormByName($formName, [F_ID, F_FILE_STATS]);
$formFromDb = $database->sql($sql, ROW_EXPECT_0_1,
$parameterArray, "Multiple forms with the same name: '$formName'");
$formFromDb = $database->selectFormByName($formName, [F_ID, F_FILE_STATS]);
// Get file stats from file system
$cwdToFormFile = self::formPathFileName($formName, $database);
$fileReadException = new \UserFormException(json_encode([
ERROR_MESSAGE_TO_USER => "Form file not found or missing permission: " . baseName($cwdToFormFile),
ERROR_MESSAGE_TO_DEVELOPER => "Form definition file not found or no permission to read file: '$cwdToFormFile'"]),
ERROR_FORM_NOT_FOUND);
$fileReadException = function () use ($cwdToFormFile, $database, $formName) {
Thrower::userFormException(
"Form file not found or missing permission: '" . baseName($cwdToFormFile) . "'. Form names are case sensitive. Similar forms: "
. implode(', ', array_filter(self::formFileNames($database), function ($f) use ($formName) {return strtolower($f) === strtolower($formName);})),
"Form definition file not found or no permission to read file: '$cwdToFormFile'"
);
};
if(!file_exists($cwdToFormFile)) {
if ($keepIfNeverExported && (!isset($formFromDb[F_FILE_STATS]) || !self::isValidFileStats($formFromDb[F_FILE_STATS]))) {
if ($keepIfNeverExported && isset($formFromDb[F_ID]) && (!isset($formFromDb[F_FILE_STATS]) || !self::isValidFileStats($formFromDb[F_FILE_STATS]))) {
// if file not exists and form was never exported, then export
self::exportForm($formName, $database);
} else {
self::deleteFormDB($formName, $database, "No corresponding form file found.");
throw $fileReadException;
$fileReadException();
}
}
$fileStatsNew = self::formFileStatsJson($cwdToFormFile);
if ($fileStatsNew === false) {
self::deleteFormDB($formName, $database, "Failed to read form file stats.");
throw $fileReadException;
$fileReadException();
}
// if fileStats from DB and file are equal: do nothing
......@@ -70,7 +71,7 @@ class FormAsFile
$fileContents = file_get_contents($cwdToFormFile);
if ($fileContents === false) {
self::deleteFormDB($formName, $database, "Failed to read form file.");
throw $fileReadException;
$fileReadException();
}
$formFromFile = json_decode($fileContents, true);
......@@ -468,9 +469,7 @@ class FormAsFile
*/
private static function deleteFormDB(string $formName, Database $database, string $logMessageReason = '', bool $keepIfNeverExported = false) // : void
{
list($sql, $parameterArray) = SqlQuery::selectFormByName($formName, [F_ID, F_FILE_STATS]);
$formFromDb = $database->sql($sql, ROW_EXPECT_0_1,
$parameterArray, "Multiple forms with the same name: '$formName'");
$formFromDb = $database->selectFormByName($formName, [F_ID, F_FILE_STATS]);
if ($keepIfNeverExported && (isset($formFromDb[F_ID]) && !isset($formFromDb[F_FILE_STATS])) || (isset($formFromDb[F_FILE_STATS]) && !self::isValidFileStats($formFromDb[F_FILE_STATS]))) {
// export form instead of deleting since it was never exported before
......@@ -693,9 +692,10 @@ class FormAsFile
$form = $database->sql($sql, ROW_EXPECT_1,
$parameterArray, "Form with id $formId not found."); // array(column name => value)
} else {
list($sql, $parameterArray) = SqlQuery::selectFormByName($formName);
$form = $database->sql($sql, ROW_EXPECT_1,
$parameterArray, "Form $formName not found or multiple forms with the same name."); // array(column name => value)
$form = $database->selectFormByName($formName); // array(column name => value)
if (!isset($form[F_ID])) {
Thrower::userFormException("Error during form export.", "Form $formName not found in database. Note: Form names are case sensitive.");
}
}
// Remove columns: id, name, fileStats
......
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