Commit 8127b564 authored by Carsten  Rose's avatar Carsten Rose
Browse files

Merge branch 'F6481-custom-primary-key' into 'master'

Feature #6481 - Add custom primary key option to Forms. Closes #6481

See merge request !90
parents 4eaba5d1 3d95371c
Pipeline #895 passed with stage
in 1 minute and 40 seconds
......@@ -2040,6 +2040,8 @@ Definition
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Table | Primary table of the form. _`form-tablename` |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Primary Key | Primary key of the indicated table. Only needed if != 'id'. _`form-primary-key` |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Required Parameter NEW | Name of required SIP parameter to create a new record (r=0), separated by comma. '#' as comment delimiter. See `form-requiredParameter`_ |
+-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
|Required Parameter EDIT | Name of required SIP parameter to edit an existing record (r>0), separated by comma. '#' as comment delimiter. See `form-requiredParameter`_ |
......
......@@ -268,7 +268,7 @@ abstract class AbstractBuildForm {
// element-update: with 'value'
$recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_ZERO);
$md5 = $this->buildRecordHashMd5($this->formSpec[F_TABLE_NAME], $recordId);
$md5 = $this->buildRecordHashMd5($this->formSpec[F_TABLE_NAME], $recordId, $this->formSpec[F_PRIMARY_KEY]);
// Via 'element-update'
$json[][API_ELEMENT_UPDATE][DIRTY_RECORD_HASH_MD5][API_ELEMENT_ATTRIBUTE]['value'] = $md5;
......@@ -399,7 +399,7 @@ abstract class AbstractBuildForm {
public function buildInputRecordHashMd5() {
$recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_ZERO);
$md5 = $this->buildRecordHashMd5($this->formSpec[F_TABLE_NAME], $recordId);
$md5 = $this->buildRecordHashMd5($this->formSpec[F_TABLE_NAME], $recordId, $this->formSpec[F_PRIMARY_KEY]);
$data = "<input id='" . DIRTY_RECORD_HASH_MD5 . "' name='" . DIRTY_RECORD_HASH_MD5 . "' type='hidden' value='$md5'>";
......@@ -412,17 +412,18 @@ abstract class AbstractBuildForm {
/**
* @param $tableName
* @param $recordId
* @param string $primaryKey
*
* @return string
* @throws CodeException
* @throws DbException
* @throws UserFormException
*/
public function buildRecordHashMd5($tableName, $recordId) {
public function buildRecordHashMd5($tableName, $recordId, $primaryKey = F_PRIMARY_KEY_DEFAULT) {
$record = array();
if ($recordId != 0) {
$record = $this->dbArray[$this->dbIndexData]->sql("SELECT * FROM $tableName WHERE id=?", ROW_EXPECT_1, [$recordId], "Record to load not found.");
$record = $this->dbArray[$this->dbIndexData]->sql("SELECT * FROM $tableName WHERE $primaryKey=?", ROW_EXPECT_1, [$recordId], "Record to load not found.");
}
return OnArray::getMd5($record);
......@@ -597,10 +598,11 @@ abstract class AbstractBuildForm {
$skip = [FE_SQL_UPDATE, FE_SQL_INSERT, FE_SQL_DELETE, FE_SQL_AFTER, FE_SQL_BEFORE, FE_PARAMETER, FE_FILL_STORE_VAR, FE_FILE_DOWNLOAD_BUTTON];
// get current data record
if ($recordId > 0 && $this->store->getVar('id', STORE_RECORD) === false) {
$primaryKey = $this->formSpec[F_PRIMARY_KEY];
if ($recordId > 0 && $this->store->getVar($primaryKey, STORE_RECORD) === false) {
$tableName = $this->formSpec[F_TABLE_NAME];
$row = $this->dbArray[$this->dbIndexData]->sql("SELECT * FROM $tableName WHERE id = ?", ROW_EXPECT_1,
array($recordId), "Form '" . $this->formSpec[F_NAME] . "' failed to load record '$recordId' from table '" .
$row = $this->dbArray[$this->dbIndexData]->sql("SELECT * FROM $tableName WHERE $primaryKey = ?", ROW_EXPECT_1,
array($recordId), "Form '" . $this->formSpec[F_NAME] . "' failed to load record '$primaryKey'='$recordId' from table '" .
$this->formSpec[F_TABLE_NAME] . "'.");
$this->store->setStore($row, STORE_RECORD);
}
......
......@@ -816,6 +816,8 @@ const F_ID = 'id';
const F_NAME = 'name';
const F_TITLE = 'title';
const F_TABLE_NAME = 'tableName';
const F_PRIMARY_KEY = 'primaryKey';
const F_PRIMARY_KEY_DEFAULT = 'id';
const F_REQUIRED_PARAMETER_NEW = 'requiredParameterNew';
const F_REQUIRED_PARAMETER_EDIT = 'requiredParameterEdit';
const F_EXTRA_DELETE_FORM = 'extraDeleteForm';
......@@ -1517,6 +1519,7 @@ const DIRTY_QFQ_USER_SESSION_COOKIE = 'qfqUserSessionCookie';
const DIRTY_FE_USER = 'feUser';
const DIRTY_EXPIRE = 'expire';
const DIRTY_TABLE_NAME = 'tableName';
const DIRTY_PRIMARY_KEY = 'primaryKey';
const DIRTY_RECORD_ID = 'recordId';
const DIRTY_RECORD_HASH_MD5 = 'recordHashMd5';
const DIRTY_RECORD_HASH_MD5_SPAN = 'recordHashMd5Span';
......
......@@ -43,7 +43,7 @@ class Delete {
}
/**
* Deletes the record id=$recordId from table $form[F_TABLE_NAME].
* Deletes the record id=$recordId from table $tableName.
* If the table has a column named COLUMN_PATH_FILE_NAME and the value of that specific record column points
* to a file: delete such a file if their are no other records in the same table which also have a reference to
* that file.
......@@ -55,7 +55,7 @@ class Delete {
* @throws DbException
* @throws UserFormException
*/
public function process($tableName, $recordId) {
public function process($tableName, $recordId, $primaryKey = F_PRIMARY_KEY_DEFAULT) {
$msg = array();
if ($tableName === false || $tableName === '') {
......@@ -74,12 +74,12 @@ class Delete {
}
// Read record first.
$row = $this->db->sql("SELECT * FROM $tableName WHERE id=?", ROW_EXPECT_0_1, [$recordId]);
$row = $this->db->sql("SELECT * FROM $tableName WHERE $primaryKey=?", ROW_EXPECT_0_1, [$recordId]);
if (count($row) > 0) {
$this->deleteReferencedFiles($row, $tableName);
$this->deleteReferencedFiles($row, $tableName, $primaryKey);
$this->db->sql("DELETE FROM $tableName WHERE id =? LIMIT 1", ROW_REGULAR, [$recordId]);
$this->db->sql("DELETE FROM $tableName WHERE $primaryKey =? LIMIT 1", ROW_REGULAR, [$recordId]);
} else {
throw new UserFormException("Record $recordId not found in table '$tableName'.", ERROR_RECORD_NOT_FOUND);
}
......@@ -102,7 +102,7 @@ class Delete {
* @throws DbException
* @throws UserFormException
*/
private function deleteReferencedFiles(array $row, $tableName) {
private function deleteReferencedFiles(array $row, $tableName, $primaryKey) {
foreach ($row AS $key => $file) {
if (false === strpos($key, COLUMN_PATH_FILE_NAME)) {
......@@ -114,7 +114,7 @@ class Delete {
// check if there are other records referencing the same file: do not delete the file now.
// This check won't find duplicates, if they are spread over different columns or tables.
$samePathFileName = $this->db->sql("SELECT COUNT(id) AS cnt FROM $tableName WHERE $key LIKE ?", ROW_EXPECT_1, [$file]);
$samePathFileName = $this->db->sql("SELECT COUNT($primaryKey) AS cnt FROM $tableName WHERE $key LIKE ?", ROW_EXPECT_1, [$file]);
if ($samePathFileName['cnt'] === 1) {
if (!unlink($file)) {
throw new UserFormException("Error deleting file: $file", ERROR_IO_UNLINK);
......
......@@ -388,9 +388,9 @@ class QuickFormQuery {
$this->store->createSipAfterFormLoad($formName);
}
if ($this->store->getVar('id', STORE_BEFORE) === false) {
if ($this->store->getVar($this->formSpec[F_PRIMARY_KEY], STORE_BEFORE) === false) {
$this->store->fillStoreWithRecord($this->formSpec[F_TABLE_NAME], $recordId,
$this->dbArray[$this->dbIndexData], STORE_BEFORE);
$this->dbArray[$this->dbIndexData], $this->formSpec[F_PRIMARY_KEY],STORE_BEFORE);
}
// Check (and release) dirtyRecord.
......@@ -398,7 +398,7 @@ class QuickFormQuery {
$dirty = new Dirty(false, $this->dbIndexData, $this->dbIndexQfq);
$answer = $dirty->checkDirtyAndRelease($formMode, $this->formSpec[F_RECORD_LOCK_TIMEOUT_SECONDS],
$this->formSpec[F_DIRTY_MODE], $this->formSpec[F_TABLE_NAME], $recordId, true);
$this->formSpec[F_DIRTY_MODE], $this->formSpec[F_TABLE_NAME], $this->formSpec[F_PRIMARY_KEY], $recordId, true);
// In case of a conflict, return immediately
if ($answer[API_STATUS] != API_ANSWER_STATUS_SUCCESS) {
......@@ -461,7 +461,7 @@ class QuickFormQuery {
case FORM_DELETE:
$formAction->elements($recordId, $this->feSpecAction, FE_TYPE_BEFORE_DELETE);
$build->process($this->formSpec[F_TABLE_NAME], $recordId);
$build->process($this->formSpec[F_TABLE_NAME], $recordId, $this->formSpec[F_PRIMARY_KEY]);
$formAction->elements($recordId, $this->feSpecAction, FE_TYPE_AFTER_DELETE);
break;
......@@ -476,7 +476,7 @@ class QuickFormQuery {
// If an old record exist: load it. Necessary to delete uploaded files which should be overwritten.
$this->store->fillStoreWithRecord($this->formSpec[F_TABLE_NAME], $recordId,
$this->dbArray[$this->dbIndexData]);
$this->dbArray[$this->dbIndexData], $this->formSpec[F_PRIMARY_KEY]);
// SAVE
$save = new Save($this->formSpec, $this->feSpecAction, $this->feSpecNative, $this->feSpecNativeRaw);
......@@ -487,7 +487,7 @@ class QuickFormQuery {
$rc = $save->process();
// Reload fresh saved record and fill STORE_RECORD with it.
$this->store->fillStoreWithRecord($this->formSpec[F_TABLE_NAME], $rc, $this->dbArray[$this->dbIndexData]);
$this->store->fillStoreWithRecord($this->formSpec[F_TABLE_NAME], $rc, $this->dbArray[$this->dbIndexData], $this->formSpec[F_PRIMARY_KEY]);
$save->processAllUploads($rc);
......@@ -495,7 +495,7 @@ class QuickFormQuery {
$status = $formAction->elements($rc, $this->feSpecAction, FE_TYPE_AFTER_INSERT . ',' . FE_TYPE_AFTER_UPDATE . ',' . FE_TYPE_AFTER_SAVE);
if ($status != ACTION_ELEMENT_NO_CHANGE) {
// Reload fresh saved record and fill STORE_RECORD with it.
$this->store->fillStoreWithRecord($this->formSpec[F_TABLE_NAME], $rc, $this->dbArray[$this->dbIndexData]);
$this->store->fillStoreWithRecord($this->formSpec[F_TABLE_NAME], $rc, $this->dbArray[$this->dbIndexData], $this->formSpec[F_PRIMARY_KEY]);
}
// Action: Paste
......@@ -844,6 +844,9 @@ class QuickFormQuery {
} else {
$form[F_DB_INDEX] = $this->eval->parse($form[F_DB_INDEX]);
}
if (empty($form[F_PRIMARY_KEY])) {
$form[F_PRIMARY_KEY] = F_PRIMARY_KEY_DEFAULT;
}
// Some forms load/save the form data on extra defined databases.
if ($this->dbIndexData != $form[F_DB_INDEX]) {
......@@ -858,7 +861,7 @@ class QuickFormQuery {
// This is needed for filling templateGroup records with their default values
// and for evaluating variables in the Form title
$this->store->fillStoreWithRecord($form[F_TABLE_NAME], $recordId, $this->dbArray[$this->dbIndexData]);
$this->store->fillStoreWithRecord($form[F_TABLE_NAME], $recordId, $this->dbArray[$this->dbIndexData], $form[F_PRIMARY_KEY]);
$formSpec = $this->eval->parseArray($form);
......
......@@ -230,7 +230,7 @@ class Save {
$rc = $this->insertRecord($this->formSpec[F_TABLE_NAME], $newValues);
} else {
$this->updateRecord($this->formSpec[F_TABLE_NAME], $newValues, $recordId);
$this->updateRecord($this->formSpec[F_TABLE_NAME], $newValues, $recordId, $this->formSpec[F_PRIMARY_KEY]);
$rc = $recordId;
}
......@@ -288,13 +288,14 @@ class Save {
* @param string $tableName
* @param array $values
* @param int $recordId
* @param string $primaryKey
*
* @return bool|int false if $values is empty, else affectedrows
* @throws CodeException
* @throws DbException
* @throws UserFormException
*/
public function updateRecord($tableName, array $values, $recordId) {
public function updateRecord($tableName, array $values, $recordId, $primaryKey = F_PRIMARY_KEY_DEFAULT) {
if (count($values) === 0)
return 0; // nothing to write, 0 rows affected
......@@ -310,7 +311,7 @@ class Save {
$sql .= '`' . $column . '` = ?, ';
}
$sql = substr($sql, 0, strlen($sql) - 2) . " WHERE id = ?";
$sql = substr($sql, 0, strlen($sql) - 2) . " WHERE $primaryKey = ?";
$values[] = $recordId;
$rc = $this->db->sql($sql, ROW_REGULAR, array_values($values));
......@@ -387,7 +388,7 @@ class Save {
// Only used in 'Simple Upload'
if (count($newValues) > 0) {
$this->updateRecord($this->formSpec[F_TABLE_NAME], $newValues, $recordId);
$this->updateRecord($this->formSpec[F_TABLE_NAME], $newValues, $recordId, $this->formSpec[F_PRIMARY_KEY]);
}
}
......
......@@ -124,6 +124,10 @@ $UPDATE_ARRAY = array(
"ALTER TABLE `Form` CHANGE `title` `title` VARCHAR(511) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT ''",
],
'18.9.1' => [
"ALTER TABLE `Form` ADD `primaryKey` VARCHAR(255) NOT NULL DEFAULT '' AFTER `tableName`",
],
);
......
......@@ -126,7 +126,10 @@ class Dirty {
$this->dbIndexData = empty($sipVars[PARAM_DB_INDEX_DATA]) ? $this->store->getVar(SYSTEM_DB_INDEX_DATA, STORE_SYSTEM) : $sipVars[PARAM_DB_INDEX_DATA];
$this->doDbArray($this->dbIndexData, $this->dbIndexQfq);
$tableVars = $this->dbArray[$this->dbIndexQfq]->sql("SELECT tableName, dirtyMode, recordLockTimeoutSeconds FROM Form AS f WHERE f.name=?", ROW_EXPECT_1, [$sipVars[SIP_FORM]], "Form not found: '" . $sipVars[SIP_FORM] . "'");
$tableVars = $this->dbArray[$this->dbIndexQfq]->sql("SELECT tableName, primaryKey, dirtyMode, recordLockTimeoutSeconds FROM Form WHERE name=?", ROW_EXPECT_1, [$sipVars[SIP_FORM]], "Form not found: '" . $sipVars[SIP_FORM] . "'");
if (empty($tableVars[F_PRIMARY_KEY])) {
$tableVars[F_PRIMARY_KEY] = F_PRIMARY_KEY_DEFAULT;
}
switch ($this->client[API_LOCK_ACTION]) {
case API_LOCK_ACTION_LOCK:
......@@ -134,7 +137,7 @@ class Dirty {
$answer = $this->acquireDirty($recordId, $tableVars, $this->client[DIRTY_RECORD_HASH_MD5]);
break;
case API_LOCK_ACTION_RELEASE:
$answer = $this->checkDirtyAndRelease(FORM_SAVE, $tableVars[F_RECORD_LOCK_TIMEOUT_SECONDS], $tableVars[F_DIRTY_MODE], $tableVars[F_TABLE_NAME], $recordId);
$answer = $this->checkDirtyAndRelease(FORM_SAVE, $tableVars[F_RECORD_LOCK_TIMEOUT_SECONDS], $tableVars[F_DIRTY_MODE], $tableVars[F_TABLE_NAME], $tableVars[F_PRIMARY_KEY], $recordId);
break;
default;
throw new CodeException("Unknown action: " . $this->client[API_LOCK_ACTION], ERROR_DIRTY_UNKNOWN_ACTION);
......@@ -156,6 +159,7 @@ class Dirty {
private function acquireDirty($recordId, array $tableVars, $recordHashMd5) {
$tableName = $tableVars[F_TABLE_NAME];
$primaryKey = $tableVars[F_PRIMARY_KEY];
$formDirtyMode = $tableVars[F_DIRTY_MODE];
$rcMd5 = '';
......@@ -163,7 +167,7 @@ class Dirty {
$answer = [API_STATUS => 'success', API_MESSAGE => ''];
} else {
// Check for changed record. Compute $rcMd5
$flagModified = $this->isRecordModified($tableName, $recordId, $recordHashMd5, $rcMd5);
$flagModified = $this->isRecordModified($tableName, $primaryKey, $recordId, $recordHashMd5, $rcMd5);
if (($recordHashMd5 != '') && $flagModified) {
return [API_STATUS => API_ANSWER_STATUS_CONFLICT, API_MESSAGE => 'The record has been modified in the meantime. Please reload the form, edit and save again.'];
}
......@@ -176,7 +180,7 @@ class Dirty {
$feUser = $this->session->get(SESSION_FE_USER);
$answer = $this->writeDirty($this->client[SIP_SIP], $recordId, $tableVars, $feUser, $rcMd5);
} else {
$answer = $this->conflict($recordDirty, $formDirtyMode);
$answer = $this->conflict($recordDirty, $formDirtyMode, $primaryKey);
}
}
......@@ -213,12 +217,12 @@ class Dirty {
*
* @return array
*/
private function conflict(array $recordDirty, $currentFormDirtyMode) {
private function conflict(array $recordDirty, $currentFormDirtyMode, $primaryKey) {
$status = API_ANSWER_STATUS_CONFLICT;
$at = "at " . $recordDirty[COLUMN_CREATED] . " from " . $recordDirty[DIRTY_REMOTE_ADDRESS];
// Compare modified timestamp
if ($this->isRecordModified($recordDirty[DIRTY_TABLE_NAME], $recordDirty[DIRTY_RECORD_ID], $recordDirty[DIRTY_RECORD_HASH_MD5], $dummy)) {
if ($this->isRecordModified($recordDirty[DIRTY_TABLE_NAME], $primaryKey, $recordDirty[DIRTY_RECORD_ID], $recordDirty[DIRTY_RECORD_HASH_MD5], $dummy)) {
return [API_STATUS => API_ANSWER_STATUS_CONFLICT, API_MESSAGE => 'The record has been modified in the meantime. Please reload the form, edit and save again.'];
}
......@@ -261,9 +265,10 @@ class Dirty {
private function writeDirty($s, $recordId, array $tableVars, $feUser, $recordHashMd5) {
$tableName = $tableVars[F_TABLE_NAME];
$primaryKey = $tableVars[F_PRIMARY_KEY];
$formDirtyMode = $tableVars[F_DIRTY_MODE];
$record = $this->dbArray[$this->dbIndexData]->sql("SELECT * FROM $tableName WHERE id=?", ROW_EXPECT_1, [$recordId], "Record to lock not found.");
$record = $this->dbArray[$this->dbIndexData]->sql("SELECT * FROM $tableName WHERE $primaryKey=?", ROW_EXPECT_1, [$recordId], "Record to lock not found.");
$expire = date('Y-m-d H:i:s', strtotime("+" . $tableVars[F_RECORD_LOCK_TIMEOUT_SECONDS] . " seconds"));
// Write 'dirty' record
......@@ -281,18 +286,19 @@ class Dirty {
* Get MD5 from tableName/recordId and compare with $recordHashMd5.
*
* @param string $tableName
* @param string $primaryKey
* @param int $recordId
* @param string $recordHashMd5 - timestamp e.g. '2017-07-27 14:06:56'
* @param $rcMd5
* @return bool true if $recordHashMd5 is different from current record md5 hash.
*/
private function isRecordModified($tableName, $recordId, $recordHashMd5, &$rcMd5) {
private function isRecordModified($tableName, $primaryKey, $recordId, $recordHashMd5, &$rcMd5) {
if ($recordHashMd5 == '') {
return false; // If there is no recordHashMd5, the check is not possible. Always return 'not modified' (=ok)
}
$record = $this->dbArray[$this->dbIndexData]->sql("SELECT * FROM $tableName WHERE id=?", ROW_EXPECT_1, [$recordId], "Record to lock not found.");
$record = $this->dbArray[$this->dbIndexData]->sql("SELECT * FROM $tableName WHERE $primaryKey=?", ROW_EXPECT_1, [$recordId], "Record to lock not found.");
$rcMd5 = OnArray::getMd5($record);
......@@ -355,7 +361,7 @@ class Dirty {
* @throws CodeException
* @throws UserFormException
*/
public function checkDirtyAndRelease($formMode, $lockTimeout, $dirtyMode, $tableName, $recordId, $flagCheckModifiedFirst = false) {
public function checkDirtyAndRelease($formMode, $lockTimeout, $dirtyMode, $tableName, $primaryKey, $recordId, $flagCheckModifiedFirst = false) {
$rcRecordDirty = array();
$rcMsg = '';
......@@ -368,7 +374,7 @@ class Dirty {
}
// Check if the record has changed in the meantime.
if ($flagCheckModifiedFirst && $this->isRecordModified($tableName, $recordId, $this->client[DIRTY_RECORD_HASH_MD5], $dummy)) {
if ($flagCheckModifiedFirst && $this->isRecordModified($tableName, $primaryKey, $recordId, $this->client[DIRTY_RECORD_HASH_MD5], $dummy)) {
throw new UserFormException ('The record has been modified in the meantime. Please reload the form, edit and save again.', ERROR_DIRTY_RECORD_MODIFIED);
}
......@@ -402,7 +408,7 @@ class Dirty {
// Is the dirtyRecord mine?
if ($lockStatus == LOCK_FOUND_OWNER) {
// Check if the record has changed in the meantime.
if ($this->isRecordModified($tableName, $recordId, $rcRecordDirty[DIRTY_RECORD_HASH_MD5], $dummy)) {
if ($this->isRecordModified($tableName, $primaryKey, $recordId, $rcRecordDirty[DIRTY_RECORD_HASH_MD5], $dummy)) {
return [API_STATUS => API_ANSWER_STATUS_CONFLICT, API_MESSAGE => 'The record has been modified in the meantime. Please reload the form, edit and save again.'];
}
......
......@@ -149,7 +149,7 @@ class FormAction {
break;
default:
// Always work on recent data: previous actions might have modified the data.
$this->store->fillStoreWithRecord($this->primaryTableName, $recordId, $this->db);
$this->store->fillStoreWithRecord($this->primaryTableName, $recordId, $this->db, $this->formSpec[F_PRIMARY_KEY]);
}
if (!$this->checkRequiredList($fe)) {
......
......@@ -70,9 +70,12 @@ class FillStoreForm {
$form = $this->store->getVar(SIP_FORM, STORE_SIP, SANITIZE_ALLOW_ALNUMX);
$recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP, SANITIZE_ALLOW_DIGIT);
$tableFromFormSql = "SELECT f.tableName FROM Form AS f WHERE f.name=?";
$tableVars = $this->dbArray[$this->dbIndexQfq]->sql($tableFromFormSql,ROW_EXPECT_1, [$form]);
$this->store->fillStoreWithRecord($tableVars[F_TABLE_NAME], $recordId, $this->dbArray[$this->dbIndexData]);
$tableFromFormSql = "SELECT tableName, primaryKey FROM Form WHERE name=?";
$form = $this->dbArray[$this->dbIndexQfq]->sql($tableFromFormSql,ROW_EXPECT_1, [$form]);
if (empty($form[F_PRIMARY_KEY])) {
$form[F_PRIMARY_KEY] = F_PRIMARY_KEY_DEFAULT;
}
$this->store->fillStoreWithRecord($form[F_TABLE_NAME], $recordId, $this->dbArray[$this->dbIndexData], $form[F_PRIMARY_KEY]);
$this->evaluate = new Evaluate($this->store, $this->dbArray[$this->dbIndexData]);
......
......@@ -856,15 +856,20 @@ class Store {
* @param $tableName
* @param $recordId
* @param $db
* @param $primaryKey
* @param string $store
* @throws CodeException
* @throws UserFormException
*/
public static function fillStoreWithRecord($tableName, $recordId, $db, $store = STORE_RECORD) {
public static function fillStoreWithRecord($tableName, $recordId, $db,
$primaryKey = F_PRIMARY_KEY_DEFAULT, $store = STORE_RECORD) {
if ($recordId !== false && $recordId > 0 &&
is_string($tableName) && $tableName !== '') {
if (!$primaryKey) {
$primaryKey = F_PRIMARY_KEY_DEFAULT;
}
$record = $db->sql("SELECT * FROM $tableName WHERE id = ?", ROW_EXPECT_1, [$recordId]);
$record = $db->sql("SELECT * FROM $tableName WHERE $primaryKey = ?", ROW_EXPECT_1, [$recordId]);
self::setStore($record, $store, true);
}
}
......
......@@ -4,7 +4,7 @@ CREATE TABLE IF NOT EXISTS `Form` (
`title` VARCHAR(511) NOT NULL DEFAULT '',
`noteInternal` TEXT NOT NULL,
`tableName` VARCHAR(255) NOT NULL DEFAULT '',
`primaryKey` VARCHAR(255) NOT NULL DEFAULT '',
`permitNew` ENUM ('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip',
`permitEdit` ENUM ('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip',
......@@ -190,8 +190,9 @@ VALUES
1, '', '', '', 'specialchar', 'no', '[a-zA-Z0-9._+-]+'),
(1, 'title', 'Title', 'show', 'text', 'all', 'native', 130, 0, 0, '<a href="{{documentation:Y}}#form-title">Info</a>', '', '', '', '', 1, '', '', '', 'none', 'no', ''),
(1, 'noteInternal', 'Note', 'show', 'text', 'all', 'native', 140, '40,3', 0, '<a href="{{documentation:Y}}#form-note">Info</a>', '', '', '', '', 1, '', '', '', 'specialchar', 'no', ''),
(1, 'tableName', 'Table', 'required', 'select', 'all', 'native', 150, 0, 0, '<a href="{{documentation:Y}}#form-tablename">Info</a>', '', '', '{{[{{indexData:Y}}]!SHOW tables}}',
'emptyItemAtStart', 1, '', '', '', 'specialchar', 'no', ''),
(1, 'tableName', 'Table', 'required', 'select', 'all', 'native', 150, 0, 0, '<a href="{{documentation:Y}}#form-tablename">Info</a>', '', '', '{{[{{indexData:Y}}]!SHOW tables}}', 'emptyItemAtStart', 1, '', '', '', 'specialchar', 'no', ''),
(1, 'primaryKey', 'Primary Key', 'show', 'text', 'all', 'native', 155, 0, 0, '<a href="{{documentation:Y}}#form-primary-key">Info</a>', '', '', '', '', 1, '', '', 'id', 'specialchar', 'no', ''),
(1, 'parameterLanguageA', 'Language: {{formLanguageALabel:YE}}', 'show', 'text', 'all', 'native', 160, '60,2', 0,
'<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 1, '', '{{SELECT IF("{{formLanguageAId:YE}}"="","hidden","show" ) }}', '', 'none', 'no', ''),
(1, 'parameterLanguageB', 'Language: {{formLanguageBLabel:YE}}', 'show', 'text', 'all', 'native', 160, '60,2', 0,
......
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