Commit 7118bca2 authored by Marc Egger's avatar Marc Egger Committed by Carsten Rose
Browse files

update SQL functions error

parent cd24d20d
......@@ -41,7 +41,7 @@ try {
case REQUEST_METHOD_POST:
if ($id != 0) {
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => "Forbidden: id>0 with HTTP method $method",
ERROR_MESSAGE_SUPPORT => '',
ERROR_MESSAGE_TO_DEVELOPER => '',
ERROR_MESSAGE_HTTP_STATUS => HTTP_400_BAD_REQUEST
]), ERROR_REST_INVALID_ID);
}
......@@ -53,7 +53,7 @@ try {
case REQUEST_METHOD_PUT:
if ($id == 0) {
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => "Forbidden: id==0 with HTTP method $method",
ERROR_MESSAGE_SUPPORT => '',
ERROR_MESSAGE_TO_DEVELOPER => '',
ERROR_MESSAGE_HTTP_STATUS => HTTP_400_BAD_REQUEST
]), ERROR_REST_INVALID_ID);
}
......@@ -64,7 +64,7 @@ try {
case REQUEST_METHOD_DELETE:
if ($id == 0) {
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => "Forbidden: id==0 with HTTP method $method",
ERROR_MESSAGE_SUPPORT => '',
ERROR_MESSAGE_TO_DEVELOPER => '',
ERROR_MESSAGE_HTTP_STATUS => HTTP_400_BAD_REQUEST
]), ERROR_REST_INVALID_ID);
}
......@@ -73,7 +73,7 @@ try {
default:
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'Unsupported/unknown HTTP request method',
ERROR_MESSAGE_SUPPORT => 'HTTP Code: ' . $method,
ERROR_MESSAGE_TO_DEVELOPER => 'HTTP Code: ' . $method,
ERROR_MESSAGE_HTTP_STATUS => HTTP_403_METHOD_NOT_ALLOWED
]), ERROR_UNKNOWN_MODE);
break;
......@@ -81,7 +81,7 @@ try {
if ($data === null) {
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => "Missing or broken JSON",
ERROR_MESSAGE_SUPPORT => json_last_error_msg(),
ERROR_MESSAGE_TO_DEVELOPER => json_last_error_msg(),
ERROR_MESSAGE_HTTP_STATUS => HTTP_400_BAD_REQUEST
]), ERROR_BROKEN_PARAMETER);
}
......
......@@ -264,7 +264,7 @@ abstract class AbstractBuildForm {
$recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP);
if (!($recordId == '' || is_numeric($recordId))) {
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'Invalid record ID', ERROR_MESSAGE_SUPPORT => 'Invalid record ID: r="' . $recordId]),
json_encode([ERROR_MESSAGE_TO_USER => 'Invalid record ID', ERROR_MESSAGE_TO_DEVELOPER => 'Invalid record ID: r="' . $recordId]),
ERROR_INVALID_VALUE);
}
......@@ -1446,7 +1446,7 @@ abstract class AbstractBuildForm {
if (false === stristr(substr($sqlTest, 0, 7), 'SELECT ')) {
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => '"Expect a SELECT statement', ERROR_MESSAGE_SUPPORT => "Expect a SELECT statement in " . FE_TYPEAHEAD_SQL . " - got: " . $sqlTest]),
json_encode([ERROR_MESSAGE_TO_USER => '"Expect a SELECT statement', ERROR_MESSAGE_TO_DEVELOPER => "Expect a SELECT statement in " . FE_TYPEAHEAD_SQL . " - got: " . $sqlTest]),
ERROR_BROKEN_PARAMETER);
}
......@@ -2566,7 +2566,7 @@ abstract class AbstractBuildForm {
} else {
throw new UserFormException(json_encode(
[ERROR_MESSAGE_TO_USER => 'Missing Parameter',
ERROR_MESSAGE_SUPPORT => FE_DND_TABLE . ' or ' . SUBRECORD_PARAMETER_FORM]),
ERROR_MESSAGE_TO_DEVELOPER => FE_DND_TABLE . ' or ' . SUBRECORD_PARAMETER_FORM]),
ERROR_MISSING_TABLE_NAME);
}
......
......@@ -43,7 +43,7 @@ class BodytextParser {
if (strpos($bodyText, NESTING_TOKEN_OPEN) !== false) {
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'Report: Missing close delimiter', ERROR_MESSAGE_SUPPORT => $bodyText]), ERROR_MISSING_CLOSE_DELIMITER);
json_encode([ERROR_MESSAGE_TO_USER => 'Report: Missing close delimiter', ERROR_MESSAGE_TO_DEVELOPER => $bodyText]), ERROR_MISSING_CLOSE_DELIMITER);
}
return $bodyText;
......@@ -280,7 +280,7 @@ class BodytextParser {
if ($posMatchOpen === false) {
$result = $this->decryptNestingDelimeter($result, $nestingOpen, $nestingClose);
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'Missing open delimiter', ERROR_MESSAGE_SUPPORT => "Missing open delimiter: $result"]),
json_encode([ERROR_MESSAGE_TO_USER => 'Missing open delimiter', ERROR_MESSAGE_TO_DEVELOPER => "Missing open delimiter: $result"]),
ERROR_MISSING_OPEN_DELIMITER);
}
......
......@@ -139,7 +139,7 @@ const KVP_VALUE_GIVEN = 'value_given';
// https://lib2.colostate.edu/wildlife/atoz.php?letter=ALL
// JSON encoded messages thrown through an exception:
const ERROR_MESSAGE_TO_USER = 'toUser'; // always shown to the user.
const ERROR_MESSAGE_SUPPORT = 'support'; // Message to help the developer to understand the problem.
const ERROR_MESSAGE_TO_DEVELOPER = 'support'; // Message to help the developer to understand the problem.
const ERROR_MESSAGE_OS = 'os'; // Error message from the OS - like 'file not found' or specific SQL problem
const ERROR_MESSAGE_HTTP_STATUS = 'httpStatus'; // HTTP Status Code to report
......@@ -228,6 +228,7 @@ const ERROR_SMALLER_THAN_MIN = 1083;
const ERROR_LARGER_THAN_MAX = 1084;
const ERROR_INVALID_DECIMAL_FORMAT = 1085;
const ERROR_INVALID_DATE = 1086;
const ERROR_PLAY_SQL_MULTIQUERY = 1087;
// Subrecord
const ERROR_SUBRECORD_MISSING_COLUMN_ID = 1100;
......
......@@ -71,7 +71,7 @@ class Delete {
$sitePath = $this->store->getVar(SYSTEM_SITE_PATH, STORE_SYSTEM);
if ($cwd === false || $sitePath === false || !HelperFile::chdir($sitePath)) {
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'getcwd() failed or SITE_PATH undefined or chdir() failed', ERROR_MESSAGE_SUPPORT => "getcwd() failed or SITE_PATH undefined or chdir('$sitePath') failed."]),
json_encode([ERROR_MESSAGE_TO_USER => 'getcwd() failed or SITE_PATH undefined or chdir() failed', ERROR_MESSAGE_TO_DEVELOPER => "getcwd() failed or SITE_PATH undefined or chdir('$sitePath') failed."]),
ERROR_IO_CHDIR);
}
......@@ -85,7 +85,7 @@ class Delete {
$this->db->sql("DELETE FROM $tableName WHERE $primaryKey =? LIMIT 1", ROW_REGULAR, [$recordId]);
} else {
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'Record not found in table', ERROR_MESSAGE_SUPPORT => "Record $recordId not found in table '$tableName'."]),
json_encode([ERROR_MESSAGE_TO_USER => 'Record not found in table', ERROR_MESSAGE_TO_DEVELOPER => "Record $recordId not found in table '$tableName'."]),
ERROR_RECORD_NOT_FOUND);
}
......
......@@ -143,7 +143,7 @@ class Evaluate {
if ($recursion > 4) {
throw new qfq\UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'Recursion too deep', ERROR_MESSAGE_SUPPORT => "Level: $recursion, Line: $line"]),
json_encode([ERROR_MESSAGE_TO_USER => 'Recursion too deep', ERROR_MESSAGE_TO_DEVELOPER => "Level: $recursion, Line: $line"]),
ERROR_RECURSION_TOO_DEEP);
}
......@@ -162,7 +162,7 @@ class Evaluate {
$posMatchOpen = strrpos(substr($result, 0, $posFirstClose), $this->startDelimiter);
if ($posMatchOpen === false) {
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'Missing open delimiter', ERROR_MESSAGE_SUPPORT => "Text: $result"]),
json_encode([ERROR_MESSAGE_TO_USER => 'Missing open delimiter', ERROR_MESSAGE_TO_DEVELOPER => "Text: $result"]),
ERROR_MISSING_OPEN_DELIMITER);
}
......@@ -305,7 +305,7 @@ class Evaluate {
if ($token[2] !== ']') {
throw new UserFormException(json_encode(
[ERROR_MESSAGE_TO_USER => "Missing token ']' on position 3",
ERROR_MESSAGE_SUPPORT => "In string '$token'"]), ERROR_TOKEN_MISSING);
ERROR_MESSAGE_TO_DEVELOPER => "In string '$token'"]), ERROR_TOKEN_MISSING);
}
$dbIndex = $token[1];
$token = trim(substr($token, 3));
......
......@@ -129,7 +129,7 @@ class File {
if ($statusUpload[FILES_ERROR] !== UPLOAD_ERR_OK) {
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'Upload: Error', ERROR_MESSAGE_SUPPORT => $this->uploadErrMsg[$newArr[FILES_ERROR]]]),
json_encode([ERROR_MESSAGE_TO_USER => 'Upload: Error', ERROR_MESSAGE_TO_DEVELOPER => $this->uploadErrMsg[$newArr[FILES_ERROR]]]),
ERROR_UPLOAD);
}
......@@ -149,7 +149,7 @@ class File {
if (!move_uploaded_file($newArr[FILES_TMP_NAME], $filenameCached)) {
$msg = error_get_last();
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'Upload: Error', ERROR_MESSAGE_SUPPORT => $msg]),
json_encode([ERROR_MESSAGE_TO_USER => 'Upload: Error', ERROR_MESSAGE_TO_DEVELOPER => $msg]),
ERROR_UPLOAD_FILE_TYPE);
}
......
......@@ -661,13 +661,13 @@ class QuickFormQuery {
if ($clientToken == false) {
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'Missing authorization token',
ERROR_MESSAGE_SUPPORT => "Missing HTTP Header: " . HTTP_HEADER_AUTHORIZATION,
ERROR_MESSAGE_TO_DEVELOPER => "Missing HTTP Header: " . HTTP_HEADER_AUTHORIZATION,
ERROR_MESSAGE_HTTP_STATUS => HTTP_401_UNAUTHORIZED
]), ERROR_REST_AUTHORIZATION);
}
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'Authorization token not accepted',
ERROR_MESSAGE_SUPPORT => "Missing HTTP Header: " . HTTP_HEADER_AUTHORIZATION,
ERROR_MESSAGE_TO_DEVELOPER => "Missing HTTP Header: " . HTTP_HEADER_AUTHORIZATION,
ERROR_MESSAGE_HTTP_STATUS => HTTP_401_UNAUTHORIZED
]), ERROR_REST_AUTHORIZATION);
}
......@@ -1483,7 +1483,7 @@ class QuickFormQuery {
if (false === Support::findInSet(strtolower($method), $this->formSpec[F_REST_METHOD])) {
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'Invalid HTTP method',
ERROR_MESSAGE_SUPPORT => "Endpoint '" . $this->formSpec[F_NAME] . "' is not allowed with HTTP method '$method'",
ERROR_MESSAGE_TO_DEVELOPER => "Endpoint '" . $this->formSpec[F_NAME] . "' is not allowed with HTTP method '$method'",
ERROR_MESSAGE_HTTP_STATUS => HTTP_401_UNAUTHORIZED
]), ERROR_FORM_REST);
......
......@@ -512,7 +512,7 @@ class Save {
$sitePath = $this->store->getVar(SYSTEM_SITE_PATH, STORE_SYSTEM);
if ($cwd === false || $sitePath === false || !HelperFile::chdir($sitePath)) {
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'getcwd() failed or SITE_PATH undefined or chdir() failed', ERROR_MESSAGE_SUPPORT => "getcwd() failed or SITE_PATH undefined or chdir('$sitePath') failed."]),
json_encode([ERROR_MESSAGE_TO_USER => 'getcwd() failed or SITE_PATH undefined or chdir() failed', ERROR_MESSAGE_TO_DEVELOPER => "getcwd() failed or SITE_PATH undefined or chdir('$sitePath') failed."]),
ERROR_IO_CHDIR);
}
......@@ -521,7 +521,7 @@ class Save {
$pathFileName = $this->store->getVar($field, STORE_SIP);
if ($pathFileName == '' || !file_exists($pathFileName)) {
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'Empty file or file not found', ERROR_MESSAGE_SUPPORT => 'Empty file or file not found: ' . $pathFileName]),
json_encode([ERROR_MESSAGE_TO_USER => 'Empty file or file not found', ERROR_MESSAGE_TO_DEVELOPER => 'Empty file or file not found: ' . $pathFileName]),
ERROR_IO_FILE_NOT_FOUND);
}
......@@ -568,7 +568,7 @@ class Save {
if (false === file_put_contents($pathFileName, base64_decode($imageData))) {
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'Write new image failed', ERROR_MESSAGE_SUPPORT => "Write new image failed: $pathFileName"]),
json_encode([ERROR_MESSAGE_TO_USER => 'Write new image failed', ERROR_MESSAGE_TO_DEVELOPER => "Write new image failed: $pathFileName"]),
ERROR_IO_WRITE);
}
......@@ -617,7 +617,7 @@ class Save {
$sitePath = $this->store->getVar(SYSTEM_SITE_PATH, STORE_SYSTEM);
if ($cwd === false || $sitePath === false || !HelperFile::chdir($sitePath)) {
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'getcwd() failed or SITE_PATH undefined or chdir() failed', ERROR_MESSAGE_SUPPORT => "getcwd() failed or SITE_PATH undefined or chdir('$sitePath') failed."]),
json_encode([ERROR_MESSAGE_TO_USER => 'getcwd() failed or SITE_PATH undefined or chdir() failed', ERROR_MESSAGE_TO_DEVELOPER => "getcwd() failed or SITE_PATH undefined or chdir('$sitePath') failed."]),
ERROR_IO_CHDIR);
}
......@@ -913,7 +913,7 @@ class Save {
// Do 'autoOrient' command
$output = Support::qfqExec($cmd, $rc);
if ($rc != 0) {
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'copy failed', ERROR_MESSAGE_SUPPORT => "[cmd=$cmd]$output"]), ERROR_IO_COPY);
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'copy failed', ERROR_MESSAGE_TO_DEVELOPER => "[cmd=$cmd]$output"]), ERROR_IO_COPY);
}
}
......@@ -1003,7 +1003,7 @@ class Save {
if ($rc != 0) {
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'pdf2svg failed', ERROR_MESSAGE_SUPPORT => "[$cwd][cmd=$cmd]$output"]),
json_encode([ERROR_MESSAGE_TO_USER => 'pdf2svg failed', ERROR_MESSAGE_TO_DEVELOPER => "[$cwd][cmd=$cmd]$output"]),
ERROR_PDF2SVG);
}
......
......@@ -147,7 +147,7 @@ class Database {
if ($mysqli->connect_error) {
throw new UserFormException (
json_encode([ERROR_MESSAGE_TO_USER => 'Error open Database',
ERROR_MESSAGE_SUPPORT => "Error open Database 'mysql:host=" . $config[SYSTEM_DB_SERVER] .
ERROR_MESSAGE_TO_DEVELOPER => "Error open Database 'mysql:host=" . $config[SYSTEM_DB_SERVER] .
";dbname=" . $config[SYSTEM_DB_NAME] .
";dbuser=" . $config[SYSTEM_DB_USER] .
"'': " . $mysqli->connect_errno . PHP_EOL . $mysqli->connect_error]),
......@@ -159,7 +159,7 @@ class Database {
if (!$mysqli->set_charset('utf8')) {
throw new UserFormException (
json_encode([ERROR_MESSAGE_TO_USER => "Error set_charset('utf8')",
ERROR_MESSAGE_SUPPORT => "Error set_charset('utf8') Database: " . $mysqli->connect_errno . PHP_EOL . $mysqli->connect_error]),
ERROR_MESSAGE_TO_DEVELOPER => "Error set_charset('utf8') Database: " . $mysqli->connect_errno . PHP_EOL . $mysqli->connect_error]),
ERROR_DB_SET_CHARSET);
}
......@@ -375,7 +375,7 @@ class Database {
if (false === ($this->mysqli_stmt = $this->mysqli->prepare($sql))) {
$this->dbLog(SQL_LOG_MODE_ERROR, $sql, $parameterArray);
$errorMsg[ERROR_MESSAGE_SUPPORT] = $this->getSqlHint($sql, $this->mysqli->error);
$errorMsg[ERROR_MESSAGE_TO_DEVELOPER] = $this->getSqlHint($sql, $this->mysqli->error);
$errorMsg[ERROR_MESSAGE_OS] = '[ mysqli: ' . $this->mysqli->errno . ' ] ' . $this->mysqli->error;
throw new DbException(json_encode($errorMsg), ERROR_DB_PREPARE);
......@@ -384,7 +384,7 @@ class Database {
if (count($parameterArray) > 0) {
if (false === $this->prepareBindParam($parameterArray)) {
$this->dbLog(SQL_LOG_MODE_ERROR, $sql, $parameterArray);
$errorMsg[ERROR_MESSAGE_SUPPORT] = $this->getSqlHint($sql, $this->mysqli->error);
$errorMsg[ERROR_MESSAGE_TO_DEVELOPER] = $this->getSqlHint($sql, $this->mysqli->error);
$errorMsg[ERROR_MESSAGE_OS] = '[ mysqli: ' . $this->mysqli_stmt->errno . ' ] ' . $this->mysqli_stmt->error;
throw new DbException(json_encode($errorMsg), ERROR_DB_BIND);
......@@ -393,7 +393,7 @@ class Database {
if (false === $this->mysqli_stmt->execute()) {
$this->dbLog(SQL_LOG_MODE_ERROR, $sql, $parameterArray);
$errorMsg[ERROR_MESSAGE_SUPPORT] = $this->getSqlHint($sql, $this->mysqli->error);
$errorMsg[ERROR_MESSAGE_TO_DEVELOPER] = $this->getSqlHint($sql, $this->mysqli->error);
$errorMsg[ERROR_MESSAGE_OS] = '[ mysqli: ' . $this->mysqli_stmt->errno . ' ] ' . $this->mysqli_stmt->error;
throw new DbException(json_encode($errorMsg), ERROR_DB_EXECUTE);
......@@ -409,7 +409,7 @@ class Database {
case 'EXPLAIN':
if (false === ($result = $this->mysqli_stmt->get_result())) {
throw new DbException(
json_encode([ERROR_MESSAGE_TO_USER => 'Error DB execute', ERROR_MESSAGE_SUPPORT => '[ mysqli: ' . $this->mysqli_stmt->errno . ' ] ' . $this->mysqli_stmt->error . $specificMessage]),
json_encode([ERROR_MESSAGE_TO_USER => 'Error DB execute', ERROR_MESSAGE_TO_DEVELOPER => '[ mysqli: ' . $this->mysqli_stmt->errno . ' ] ' . $this->mysqli_stmt->error . $specificMessage]),
ERROR_DB_EXECUTE);
}
......@@ -730,7 +730,7 @@ class Database {
}
throw new DbException(
json_encode([ERROR_MESSAGE_TO_USER => 'Column name not found', ERROR_MESSAGE_SUPPORT => "Column name '$columnName' not found in table '$table'."]),
json_encode([ERROR_MESSAGE_TO_USER => 'Column name not found', ERROR_MESSAGE_TO_DEVELOPER => "Column name '$columnName' not found in table '$table'."]),
ERROR_DB_COLUMN_NOT_FOUND_IN_TABLE);
}
......@@ -966,16 +966,17 @@ class Database {
}
/**
* @param $filename
* @param $sqlStatements
*
* @throws \qfq\CodeException
*/
public function playSqlFile($filename) {
$sqlStatements = file_get_contents($filename);
public function playMultiQuery($sqlStatements) {
if (false === $this->mysqli->multi_query($sqlStatements)) {
throw new CodeException("Error playing $filename", ERROR_PLAY_SQL_FILE);
$executed = $this->mysqli->multi_query($sqlStatements);
if (false === $executed) {
$errorMsg[ERROR_MESSAGE_TO_USER] = 'SQL Error.';
$errorMsg[ERROR_MESSAGE_TO_DEVELOPER] = "Error playing multi query: " . $sqlStatements;
throw new CodeException($errorMsg, ERROR_PLAY_SQL_MULTIQUERY);
}
// discard all results: this is important - if missed, following calls on $mysqli will fail.
......@@ -987,6 +988,24 @@ class Database {
}
/**
* @param $filename
*
* @throws \qfq\CodeException
*/
public function playSqlFile($filename) {
$query = file_get_contents($filename);
try {
$this->playMultiQuery($query);
}
catch (CodeException $e) {
throw new CodeException("Error playing $filename", ERROR_PLAY_SQL_FILE);
}
}
/**
* @return string
* @throws CodeException
......
......@@ -80,16 +80,16 @@ class DatabaseUpdate {
//
foreach ($arr as $row) {
if (isset($row['Comment'])) {
$arr = explode('=', $row['Comment']);
if (count($arr) == 2 && $arr[0] == 'Version' && $arr[1] != '' AND (version_compare($arr[1], $found) == 1)) {
$found = $arr[1];
parse_str($row['Comment'], $arr);
if (($arr['Version'] ?? '') !== '' AND (version_compare($arr['Version'], $found) == 1)) {
$found = $arr;
}
} else {
continue;
}
}
return $found === '' ? false : $found;
return ($found === '') ? false : $found;
}
/**
......@@ -101,7 +101,14 @@ class DatabaseUpdate {
*/
private function setDatabaseVersion($version) {
$this->db->sql("ALTER TABLE `Form` COMMENT = 'Version=$version'");
if (is_array($version)) {
$versionInfo = $version;
} else {
$versionInfo = $this->getDatabaseVersion();
$versionInfo['Version'] = $version;
}
$this->db->sql("ALTER TABLE `Form` COMMENT = '" . http_build_query($versionInfo) . "'");
}
......@@ -118,20 +125,28 @@ class DatabaseUpdate {
if ($dbUpdate === SYSTEM_DB_UPDATE_NEVER) {
return;
}
$old = false;
$new = $this->getExtensionVersion();
$old = $this->getDatabaseVersion();
$versionInfo = $this->getDatabaseVersion();
$old = $versionInfo['Version'];
if ($dbUpdate === SYSTEM_DB_UPDATE_ALWAYS || ($dbUpdate === SYSTEM_DB_UPDATE_AUTO && $new != $old)) {
$newFunctionsHash = $this->updateSqlFunctions($versionInfo['functionsHash']);
if (null !== $newFunctionsHash) {
$versionInfo['functionsHash'] = $newFunctionsHash;
$versionInfo['functionsVersion'] = $new;
}
$this->dbUpdateStatements($old, $new);
$this->db->playSqlFile(__DIR__ . '/../../sql/formEditor.sql');
$this->db->playSqlFile(__DIR__ . '/../../sql/functions.sql');
$qfqLog = $this->db->getQfqLogFile();
Logger::logMessage(date('Y.m.d H:i:s ') . ": Updated from QFQ version '$old' to '$new'", $qfqLog);
// Finally write the latest version number.
$this->setDatabaseVersion($new);
$versionInfo['Version'] = $new;
$this->setDatabaseVersion($versionInfo);
}
if ($old === false) {
......@@ -140,6 +155,53 @@ class DatabaseUpdate {
}
}
/**
* @param $oldFunctionsHash
*
* @return string
*
* @throws CodeException
* @throws DbException
* @throws UserFormException
*/
private function updateSqlFunctions($oldFunctionsHash) {
if ('no' === $oldFunctionsHash) {
return null;
}
$functionsSql = file_get_contents(__DIR__ . '/../../sql/functions.sql');
$functionsHash = hash('md5', $functionsSql);
if ($functionsHash === $oldFunctionsHash) {
return null;
}
$query = str_replace('%%FUNCTIONSHASH%%', $functionsHash, $functionsSql);
if (stripos($query, 'delimiter')) {
$errorMsg[ERROR_MESSAGE_TO_USER] = 'Error while updating qfq.';
$errorMsg[ERROR_MESSAGE_TO_DEVELOPER] = "Error in file functions.sql: The keyword DELIMITER is present " .
"in functions.sql, this usually leads to errors when trying to execute it on the database.";
throw new DbException(json_encode($errorMsg), ERROR_PLAY_SQL_FILE);
}
$this->db->playMultiQuery($query);
try {
$functionsHashTest = $this->db->sql('SELECT GETFUNCTIONSHASH() AS res;', ROW_EXPECT_1)['res'];
} catch (DbException $e) {
$functionsHashTest = null;
}
if ($functionsHash !== null AND $functionsHashTest === $functionsHash) {
return $functionsHash;
} else {
$errorMsg[ERROR_MESSAGE_TO_USER] = 'Error while updating qfq.';
$errorMsg[ERROR_MESSAGE_TO_DEVELOPER] = "Error while updating qfq: " .
"Could not properly execute the file 'functions.sql' on the QFQ MYSQL database. " .
"Please do so manually or set the parameter 'functionsHash' in the table comments of the table" .
" 'Form' to 'no' i.e. 'Version=x.y.z&functionHash=no' to disable updating of the qfq mysql functions." .
" You may also try giving the mysql user the 'SUPER' privilege temporarily.";
throw new DbException(json_encode($errorMsg), ERROR_PLAY_SQL_FILE);
}
}
/**
* @param $path
*
......@@ -170,7 +232,7 @@ class DatabaseUpdate {
* @throws UserFormException
*/
private function dbUpdateStatements($old, $new) {
if ($new == '' || $old === false) {
if ($new == '' || $old === false || $old === null) {
return;
}
$updateArray = $this->readUpdateData(__DIR__ . '/DatabaseUpdateData.php');
......
......@@ -41,7 +41,7 @@ class ErrorHandler {
// file and line number. Often the filename is part of the message >> don't show the message to the user.
throw new CodeException(json_encode(
[ERROR_MESSAGE_TO_USER => 'General error - please report.',
ERROR_MESSAGE_SUPPORT => "File: $file / Line: $line / $message"]), $severity, null);
ERROR_MESSAGE_TO_DEVELOPER => "File: $file / Line: $line / $message"]), $severity, null);
}
......
......@@ -153,7 +153,7 @@ class DragAndDrop {
break;
default:
throw new CodeException(json_encode([ERROR_MESSAGE_TO_USER => 'Unknown "setTo" string', ERROR_MESSAGE_SUPPORT => "Token found: " . $setTo]), ERROR_UNKNOWN_TOKEN);
throw new CodeException(json_encode([ERROR_MESSAGE_TO_USER => 'Unknown "setTo" string', ERROR_MESSAGE_TO_DEVELOPER => "Token found: " . $setTo]), ERROR_UNKNOWN_TOKEN);
}
} else {
$data = $this->setNewOrder($tableName, $orderColumn, $row[DND_COLUMN_ID], $row[DND_COLUMN_ORD], $ord, $data);
......
......@@ -109,7 +109,7 @@ class FormAction {
if (!empty($rows)) {
throw new UserFormException(json_encode(
[ERROR_MESSAGE_TO_USER => "Invalid statement for 'fillStoreVar'.",
ERROR_MESSAGE_SUPPORT => $fe[FE_FILL_STORE_VAR]]), ERROR_INVALID_OR_MISSING_PARAMETER);
ERROR_MESSAGE_TO_DEVELOPER => $fe[FE_FILL_STORE_VAR]]), ERROR_INVALID_OR_MISSING_PARAMETER);
}
}
$fe[FE_FILL_STORE_VAR] = ''; // do not process the same later on.
......@@ -321,7 +321,7 @@ class FormAction {
$msg = $this->evaluate->parse($fe[FE_MESSAGE_FAIL]); // Replace possible dynamic parts
// Throw user error message
throw new UserFormException( json_encode([ERROR_MESSAGE_TO_USER => $msg, ERROR_MESSAGE_SUPPORT => 'validate() failed']), ERROR_REPORT_FAILED_ACTION);
throw new UserFormException( json_encode([ERROR_MESSAGE_TO_USER => $msg, ERROR_MESSAGE_TO_DEVELOPER => 'validate() failed']), ERROR_REPORT_FAILED_ACTION);
}
......
......@@ -248,7 +248,7 @@ class HelperFile {
if ($mode !== false) {
if (false === chmod($pathFileName, $mode)) {
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'Failed: chmod', ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'"]),
json_encode([ERROR_MESSAGE_TO_USER => 'Failed: chmod', ERROR_MESSAGE_TO_DEVELOPER => "Failed: chmod $mode '$pathFileName'"]),
ERROR_IO_CHMOD);
}
}
......@@ -278,7 +278,7 @@ class HelperFile {
if (false === chdir($cwd)) {
$msg = self::errorGetLastAsString() . " - chdir($cwd)";
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'chdir failed', ERROR_MESSAGE_SUPPORT => $msg]), ERROR_IO_CHDIR);
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'chdir failed', ERROR_MESSAGE_TO_DEVELOPER => $msg]), ERROR_IO_CHDIR);
}
return true;
......@@ -301,7 +301,7 @@ class HelperFile {
if (false === unlink($filename)) {
$msg = self::errorGetLastAsString() . " - unlink($filename)";
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'unlink failed', ERROR_MESSAGE_SUPPORT => $msg]), ERROR_IO_UNLINK);
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'unlink failed', ERROR_MESSAGE_TO_DEVELOPER => $msg]), ERROR_IO_UNLINK);
}
return true;
......@@ -318,7 +318,7 @@ class HelperFile {
if (false === rmdir($tempDir)) {
$msg = self::errorGetLastAsString() . " - rmdir($tempDir)";
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'rmdir failed', ERROR_MESSAGE_SUPPORT => $msg]), ERROR_IO_RMDIR);
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'rmdir failed', ERROR_MESSAGE_TO_DEVELOPER => $msg]), ERROR_IO_RMDIR);
}
return true;
......@@ -336,7 +336,7 @@ class HelperFile {
if (false === rename($oldname, $newname)) {
$msg = self::errorGetLastAsString() . " - rename($oldname ,$newname)";
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'unlink failed', ERROR_MESSAGE_SUPPORT => $msg]), ERROR_IO_RENAME);
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'unlink failed', ERROR_MESSAGE_TO_DEVELOPER => $msg]), ERROR_IO_RENAME);
}
return true;
......@@ -360,16 +360,16 @@ class HelperFile {
if (false === copy($source, $dest)) {
if (!is_readable($source)) {
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'copy failed', ERROR_MESSAGE_SUPPORT => "Can't read file '$source'"]), ERROR_IO_READ_FILE);
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'copy failed', ERROR_MESSAGE_TO_DEVELOPER => "Can't read file '$source'"]), ERROR_IO_READ_FILE);
}
if (!is_writeable($dest)) {
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'copy failed', ERROR_MESSAGE_SUPPORT => "Can't write to file '$dest'"]), ERROR_IO_WRITE_FILE);
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'copy failed', ERROR_MESSAGE_TO_DEVELOPER => "Can't write to file '$dest'"]), ERROR_IO_WRITE_FILE);
}
$msg = self::errorGetLastAsString(); // Often, there is no specific error string.
$msg .= " - copy($source, $dest)";
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'copy failed', ERROR_MESSAGE_SUPPORT => $msg]), ERROR_IO_COPY);