Commit 446e7e7f authored by Carsten  Rose's avatar Carsten Rose
Browse files

Refactor to use form.restMethod instead of form.permNew|edit=rest. Next step...

Refactor to use form.restMethod instead of form.permNew|edit=rest. Next step will be to eliminate formMode=FORM_REST
parent 3e2d2805
...@@ -24,11 +24,38 @@ try { ...@@ -24,11 +24,38 @@ try {
try { try {
$form = OnString::splitPathInfoToIdForm($_SERVER['PATH_INFO'], $restId, $restForm); $form = OnString::splitPathInfoToIdForm($_SERVER['PATH_INFO'], $restId, $restForm);
// get latest `ìd`
$id=end($restId); $id=end($restId);
// Fake Bodytext setup // Fake Bodytext setup
$bodytext = TYPO3_RECORD_ID . '=' . $id . PHP_EOL; $bodytext = TYPO3_RECORD_ID . '=' . $id . PHP_EOL;
$bodytext .= TYPO3_FORM . '=' . $form . PHP_EOL; $bodytext .= TYPO3_FORM . '=' . $form . PHP_EOL;
$method=$_SERVER['REQUEST_METHOD'];
switch($method){
case REQUEST_METHOD_GET:
break;
case REQUEST_METHOD_POST:
if($id!=0){
throw new UserFormException('Method POST needs no id or id=0', ERROR_REST_INVALID_ID);
}
$_POST = json_decode(file_get_contents('php://input'), true);
break;
case REQUEST_METHOD_PUT:
if($id==0){
throw new UserFormException('Method PUT needs an id>0', ERROR_REST_INVALID_ID);
}
$_POST = json_decode(file_get_contents('php://input'), true);
break;
case REQUEST_METHOD_DELETE:
if($id==0){
throw new UserFormException('Method DELETE needs an id>0', ERROR_REST_INVALID_ID);
}
break;
default:
break;
}
$qfq = new QuickFormQuery(['bodytext' => $bodytext]); $qfq = new QuickFormQuery(['bodytext' => $bodytext]);
$answer = $qfq->rest($restId, $restForm); $answer = $qfq->rest($restId, $restForm);
$status='HTTP/1.0 200 OK'; $status='HTTP/1.0 200 OK';
...@@ -50,4 +77,3 @@ try { ...@@ -50,4 +77,3 @@ try {
header($status); header($status);
header("Content-Type: application/json"); header("Content-Type: application/json");
echo json_encode($answer); echo json_encode($answer);
...@@ -365,6 +365,7 @@ const ERROR_IMPORT_LIST_SHEET_NAMES = 2901; ...@@ -365,6 +365,7 @@ const ERROR_IMPORT_LIST_SHEET_NAMES = 2901;
// REST // REST
const ERROR_FORM_REST = 3000; const ERROR_FORM_REST = 3000;
const ERROR_REST_AUTHORIZATION = 3001; const ERROR_REST_AUTHORIZATION = 3001;
const ERROR_REST_INVALID_ID = 3002;
// //
// Store Names: Identifier // Store Names: Identifier
// //
...@@ -420,12 +421,18 @@ const CLIENT_SERVER_ADDRESS = 'SERVER_ADDR'; ...@@ -420,12 +421,18 @@ const CLIENT_SERVER_ADDRESS = 'SERVER_ADDR';
const CLIENT_SERVER_PORT = 'SERVER_PORT'; const CLIENT_SERVER_PORT = 'SERVER_PORT';
const CLIENT_REMOTE_ADDRESS = 'REMOTE_ADDR'; const CLIENT_REMOTE_ADDRESS = 'REMOTE_ADDR';
const CLIENT_REQUEST_SCHEME = 'REQUEST_SCHEME'; const CLIENT_REQUEST_SCHEME = 'REQUEST_SCHEME';
const CLIENT_REQUEST_METHOD = 'REQUEST_METHOD';
const CLIENT_SCRIPT_FILENAME = 'SCRIPT_FILENAME'; const CLIENT_SCRIPT_FILENAME = 'SCRIPT_FILENAME';
const CLIENT_QUERY_STRING = 'QUERY_STRING'; const CLIENT_QUERY_STRING = 'QUERY_STRING';
const CLIENT_REQUEST_URI = 'REQUEST_URI'; const CLIENT_REQUEST_URI = 'REQUEST_URI';
const CLIENT_SCRIPT_NAME = 'SCRIPT_NAME'; const CLIENT_SCRIPT_NAME = 'SCRIPT_NAME';
const CLIENT_PHP_SELF = 'PHP_SELF'; const CLIENT_PHP_SELF = 'PHP_SELF';
const REQUEST_METHOD_GET = 'GET';
const REQUEST_METHOD_POST = 'POST';
const REQUEST_METHOD_PUT = 'PUT';
const REQUEST_METHOD_DELETE = 'DELETE';
// _COOKIE // _COOKIE
const CLIENT_COOKIE_QFQ = 'cookieQfq'; const CLIENT_COOKIE_QFQ = 'cookieQfq';
...@@ -879,6 +886,7 @@ const F_TITLE = 'title'; ...@@ -879,6 +886,7 @@ const F_TITLE = 'title';
const F_TABLE_NAME = 'tableName'; const F_TABLE_NAME = 'tableName';
const F_PRIMARY_KEY = 'primaryKey'; const F_PRIMARY_KEY = 'primaryKey';
const F_PRIMARY_KEY_DEFAULT = 'id'; const F_PRIMARY_KEY_DEFAULT = 'id';
const F_REST_METHOD = 'restMethod';
const F_REQUIRED_PARAMETER_NEW = 'requiredParameterNew'; const F_REQUIRED_PARAMETER_NEW = 'requiredParameterNew';
const F_REQUIRED_PARAMETER_EDIT = 'requiredParameterEdit'; const F_REQUIRED_PARAMETER_EDIT = 'requiredParameterEdit';
const F_EXTRA_DELETE_FORM = 'extraDeleteForm'; const F_EXTRA_DELETE_FORM = 'extraDeleteForm';
......
...@@ -172,7 +172,7 @@ class QuickFormQuery { ...@@ -172,7 +172,7 @@ class QuickFormQuery {
Session::checkSessionExpired($timeout); Session::checkSessionExpired($timeout);
// If an FE user logs out and a different user logs in (same browser session) - the old values has to be destroyed! // If an FE user logs out and a different user logs in (same browser session) - the old values has to be destroyed!
if (Session::getAndDestroyFlagFeUserHasChanged() ) { if (Session::getAndDestroyFlagFeUserHasChanged()) {
$this->store->unsetStore(STORE_USER); $this->store->unsetStore(STORE_USER);
} }
...@@ -371,7 +371,6 @@ class QuickFormQuery { ...@@ -371,7 +371,6 @@ class QuickFormQuery {
// Check 'session expire' happens quite late, cause it can be configured per form. // Check 'session expire' happens quite late, cause it can be configured per form.
Session::checkSessionExpired($this->formSpec[F_SESSION_TIMEOUT_SECONDS]); Session::checkSessionExpired($this->formSpec[F_SESSION_TIMEOUT_SECONDS]);
if ($formName !== false) { if ($formName !== false) {
// Validate only if there is a 'real' form (not a FORM_DELETE with only a tablename). // Validate only if there is a 'real' form (not a FORM_DELETE with only a tablename).
$sipFound = $this->validateForm($foundInStore, $formMode); $sipFound = $this->validateForm($foundInStore, $formMode);
...@@ -984,13 +983,10 @@ class QuickFormQuery { ...@@ -984,13 +983,10 @@ class QuickFormQuery {
HelperFormElement::explodeParameter($form, F_PARAMETER); HelperFormElement::explodeParameter($form, F_PARAMETER);
unset($form[F_PARAMETER]); unset($form[F_PARAMETER]);
if (isset($form[FE_FILL_STORE_VAR])) {
$fillStoreVar = $form[FE_FILL_STORE_VAR];
unset($form[FE_FILL_STORE_VAR]);
}
// Save specific elements to be expanded later. // Save specific elements to be expanded later.
$parseLater = OnArray::getArrayItems($form, [F_FORWARD_PAGE, F_REST_SQL_LIST, F_REST_SQL_DATA]); $parseLater = OnArray::getArrayItems($form, [F_FORWARD_PAGE, FE_FILL_STORE_VAR, F_REST_SQL_LIST, F_REST_SQL_DATA]);
$form[FE_FILL_STORE_VAR] = '';
$form[F_FORWARD_PAGE] = ''; $form[F_FORWARD_PAGE] = '';
$form[F_REST_SQL_LIST] = ''; $form[F_REST_SQL_LIST] = '';
$form[F_REST_SQL_DATA] = ''; $form[F_REST_SQL_DATA] = '';
...@@ -1054,8 +1050,11 @@ class QuickFormQuery { ...@@ -1054,8 +1050,11 @@ class QuickFormQuery {
!empty($form[FORM_LOG_ACTIVE]) && Logger::logFormLine($form, "F:$mode:evaluated:" . date('Y-m-d H:i:s'), $form, true); !empty($form[FORM_LOG_ACTIVE]) && Logger::logFormLine($form, "F:$mode:evaluated:" . date('Y-m-d H:i:s'), $form, true);
// Fire FE_FILL_STORE_VAR after the primary form record has been loaded // Fire FE_FILL_STORE_VAR after the primary form record has been loaded
if (!empty($fillStoreVar)) { if (!empty($formSpec[FE_FILL_STORE_VAR])) {
$rows = $this->evaluate->parse($fillStoreVar, ROW_EXPECT_0_1);
$rows = $this->evaluate->parse($formSpec[FE_FILL_STORE_VAR], ROW_EXPECT_0_1);
unset($formSpec[FE_FILL_STORE_VAR]);
if (is_array($rows)) { if (is_array($rows)) {
$this->store->appendToStore($rows, STORE_VAR); $this->store->appendToStore($rows, STORE_VAR);
// LOG // LOG
...@@ -1422,10 +1421,10 @@ class QuickFormQuery { ...@@ -1422,10 +1421,10 @@ class QuickFormQuery {
*/ */
private function validateForm($formNameFoundInStore, $formMode) { private function validateForm($formNameFoundInStore, $formMode) {
// Retrieve record_id either from SIP (prefered) or via URL // Retrieve record_id either from SIP (preferred) or via URL
$r = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3 . STORE_CLIENT, '', $recordIdFoundInStore); $r = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3 . STORE_CLIENT, '', $recordIdFoundInStore);
// If not found: Fake a definition in STORE_TYPO3. // no record id: Fake a definition in STORE_TYPO3.
if ($r === false) { if ($r === false) {
$r = 0; $r = 0;
$this->store->setVar(TYPO3_RECORD_ID, $r, STORE_TYPO3); $this->store->setVar(TYPO3_RECORD_ID, $r, STORE_TYPO3);
...@@ -1466,22 +1465,23 @@ class QuickFormQuery { ...@@ -1466,22 +1465,23 @@ class QuickFormQuery {
case FORM_PERMISSION_NEVER: case FORM_PERMISSION_NEVER:
throw new UserFormException("Loading form forbidden.", ERROR_FORM_FORBIDDEN); throw new UserFormException("Loading form forbidden.", ERROR_FORM_FORBIDDEN);
break; break;
case FORM_PERMISSION_REST: // case FORM_PERMISSION_REST:
if ($formMode != FORM_REST) { // if ($formMode != FORM_REST) {
throw new UserFormException("Try to load a REST form", ERROR_FORM_REST); // throw new UserFormException("Try to load a REST form", ERROR_FORM_REST);
} // }
break; // break;
default: default:
throw new CodeException("Unknown permission mode: '" . $permitMode . "'", ERROR_FORM_UNKNOWN_PERMISSION_MODE); throw new CodeException("Unknown permission mode: '" . $permitMode . "'", ERROR_FORM_UNKNOWN_PERMISSION_MODE);
} }
if ($formMode == FORM_REST) { if ($formMode == FORM_REST) {
$this->restCheckAuthToken($this->formSpec[F_REST_TOKEN] ?? ''); $method = strtolower($this->store::getVar(CLIENT_REQUEST_METHOD, STORE_CLIENT));
if (false === Support::findInSet($method, $this->formSpec[F_REST_METHOD])) {
if ($permitMode != FORM_PERMISSION_REST) { throw new UserFormException("Form '". $this->formSpec[F_NAME]. "' is not allowed with method '$method'", ERROR_FORM_REST);
throw new UserFormException("Try to load a non-REST form in REST mode", ERROR_FORM_REST);
} }
$this->restCheckAuthToken($this->formSpec[F_REST_TOKEN] ?? '');
} }
// Form Definition valid? // Form Definition valid?
...@@ -1871,7 +1871,7 @@ EOF; ...@@ -1871,7 +1871,7 @@ EOF;
/** /**
* @param array $restId * @param array $restId
* @param array $restForm * @param string $method
* @return array|string * @return array|string
* @throws CodeException * @throws CodeException
* @throws DbException * @throws DbException
......
...@@ -137,6 +137,10 @@ $UPDATE_ARRAY = array( ...@@ -137,6 +137,10 @@ $UPDATE_ARRAY = array(
"ALTER TABLE `FormElement` ADD `labelAlign` ENUM('default','left','center','right') NOT NULL DEFAULT 'default' AFTER `maxLength`;", "ALTER TABLE `FormElement` ADD `labelAlign` ENUM('default','left','center','right') NOT NULL DEFAULT 'default' AFTER `maxLength`;",
], ],
'19.2.3' => [
"ALTER TABLE `Form` ADD `restMethod` SET('get','post','put','delete') NOT NULL DEFAULT '' AFTER `permitEdit`; ",
],
); );
......
...@@ -319,7 +319,7 @@ class Support { ...@@ -319,7 +319,7 @@ class Support {
/** /**
* Search for the parameter $needle in $haystack. The arguments has to be separated by ','. * Search for the parameter $needle in $haystack. The arguments has to be separated by ','.
* *
* Returns false if not found or index of found place. Be careful: use unary operator to compare for 'false' * Returns false if not found, or index (starting with 0) of found place. Be careful: use unary operator to compare for 'false'
* *
* @param string $needle * @param string $needle
* @param string $haystack * @param string $haystack
......
...@@ -42,14 +42,12 @@ class Client { ...@@ -42,14 +42,12 @@ class Client {
if (isset($_POST)) { if (isset($_POST)) {
$post = $_POST; $post = $_POST;
// Logger::logMessage(var_export($post, true) . PHP_EOL . PHP_EOL,'post.txt');
} }
if (isset($_COOKIE[SESSION_NAME])) { if (isset($_COOKIE[SESSION_NAME])) {
$cookie[CLIENT_COOKIE_QFQ] = $_COOKIE[SESSION_NAME]; $cookie[CLIENT_COOKIE_QFQ] = $_COOKIE[SESSION_NAME];
} }
// It's important to merge the SERVER array last: those entries shall overwrite client values.
if (isset($_SERVER)) { if (isset($_SERVER)) {
$server = Sanitize::htmlentitiesArr($_SERVER); // $_SERVER values might be compromised. $server = Sanitize::htmlentitiesArr($_SERVER); // $_SERVER values might be compromised.
} }
...@@ -59,6 +57,7 @@ class Client { ...@@ -59,6 +57,7 @@ class Client {
$server[CLIENT_REMOTE_ADDRESS] = '0.0.0.0'; $server[CLIENT_REMOTE_ADDRESS] = '0.0.0.0';
} }
// It's important to merge the SERVER array last: those entries shall overwrite client values.
$arr = array_merge($header, $get, $post, $cookie, $server); $arr = array_merge($header, $get, $post, $cookie, $server);
return Sanitize::normalize($arr); return Sanitize::normalize($arr);
......
...@@ -124,6 +124,7 @@ class Store { ...@@ -124,6 +124,7 @@ class Store {
CLIENT_SERVER_PORT => SANITIZE_ALLOW_DIGIT, CLIENT_SERVER_PORT => SANITIZE_ALLOW_DIGIT,
CLIENT_REMOTE_ADDRESS => SANITIZE_ALLOW_ALNUMX, CLIENT_REMOTE_ADDRESS => SANITIZE_ALLOW_ALNUMX,
CLIENT_REQUEST_SCHEME => SANITIZE_ALLOW_ALNUMX, CLIENT_REQUEST_SCHEME => SANITIZE_ALLOW_ALNUMX,
CLIENT_REQUEST_METHOD => SANITIZE_ALLOW_ALNUMX,
CLIENT_SCRIPT_FILENAME => SANITIZE_ALLOW_ALNUMX, CLIENT_SCRIPT_FILENAME => SANITIZE_ALLOW_ALNUMX,
CLIENT_QUERY_STRING => SANITIZE_ALLOW_ALL, CLIENT_QUERY_STRING => SANITIZE_ALLOW_ALL,
CLIENT_REQUEST_URI => SANITIZE_ALLOW_ALL, CLIENT_REQUEST_URI => SANITIZE_ALLOW_ALL,
......
...@@ -13,6 +13,7 @@ CREATE TABLE IF NOT EXISTS `Form` ...@@ -13,6 +13,7 @@ CREATE TABLE IF NOT EXISTS `Form`
`permitNew` ENUM ('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip', `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', `permitEdit` ENUM ('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip',
`restMethod` SET ('get','post','put','delete') NOT NULL DEFAULT '',
`escapeTypeDefault` VARCHAR(32) NOT NULL DEFAULT 'c', `escapeTypeDefault` VARCHAR(32) NOT NULL DEFAULT 'c',
`render` ENUM ('bootstrap', 'table', 'plain') NOT NULL DEFAULT 'bootstrap', `render` ENUM ('bootstrap', 'table', 'plain') NOT NULL DEFAULT 'bootstrap',
`requiredParameterNew` VARCHAR(255) NOT NULL DEFAULT '', `requiredParameterNew` VARCHAR(255) NOT NULL DEFAULT '',
...@@ -164,20 +165,19 @@ WHERE FIND_IN_SET(Form.name, 'form,formElement,copyForm,cron') > 0; ...@@ -164,20 +165,19 @@ WHERE FIND_IN_SET(Form.name, 'form,formElement,copyForm,cron') > 0;
# #
# FormEditor: Form # FormEditor: Form
INSERT INTO Form (id, name, title, noteInternal, tableName, permitNew, permitEdit, render, multiSql, parameter) INSERT INTO Form (id, name, title, noteInternal, tableName, permitNew, permitEdit, render, multiSql, parameter)
VALUES VALUES (1, 'form', 'Form Editor: {{SELECT id, " / ", name FROM Form WHERE id = {{r:S0}}}} (DB: {{dbNameQfq:Y}})',
(1, 'form', 'Form Editor: {{SELECT id, " / ", name FROM Form WHERE id = {{r:S0}}}} (DB: {{dbNameQfq:Y}})',
'FormElement Editor', 'FormElement Editor',
'Form', 'sip', 'sip', 'bootstrap', '', 'maxVisiblePill=5\nclass=container-fluid\ndbIndex={{indexQfq:Y}}'); 'Form', 'sip', 'sip', 'bootstrap', '', 'maxVisiblePill=5\nclass=container-fluid\ndbIndex={{indexQfq:Y}}');
# FormEditor: FormElements for 'form' # FormEditor: FormElements for 'form'
INSERT INTO FormElement (id, formId, name, label, mode, type, checkType, class, ord, size, note, clientJs, value, INSERT INTO FormElement (id, formId, name, label, mode, type, checkType, class, ord, size, note, clientJs, value,
sql1, parameter, feIdContainer, subrecordOption, modeSql, placeholder) sql1, parameter, feIdContainer, subrecordOption, modeSql, placeholder)
VALUES VALUES (1, 1, 'basic', 'Basic', 'show', 'pill', 'all', 'container', 100, 0, '', '', '', '', '', 0, '', '', ''),
(1, 1, 'basic', 'Basic', 'show', 'pill', 'all', 'container', 100, 0, '', '', '', '', '', 0, '', '', ''), (2, 1, 'formelement', 'Formelement', 'show', 'pill', 'all', 'container', 200, 0, '', '', '', '', '', 0, '', '',
(2, 1, 'formelement', 'Formelement', 'show', 'pill', 'all', 'container', 200, 0, '', '', '', '', '', 0, '', '', ''), ''),
(3, 1, 'layout', 'Layout', 'show', 'pill', 'all', 'container', 300, 0, '', '', '', '', '', 0, '', '', ''), (3, 1, 'layout', 'Layout', 'show', 'pill', 'all', 'container', 300, 0, '', '', '', '', '', 0, '', '', ''),
(4, 1, 'access', 'Access', 'show', 'pill', 'all', 'container', 400, 0, '', '', '', '', '', 0, '', '', ''), (4, 1, 'access', 'Access', 'show', 'pill', 'all', 'container', 400, 0, '', '', '', '', '', 0, '', '', ''),
(5, 1, 'multi', 'Multi', 'hidden', 'pill', 'all', 'container', 500, 0, '', '', '', '', '', 0, '', '', ''); (5, 1, 'multi', 'Multi', 'hidden', 'pill', 'all', 'container', 500, 0, '', '', '', '', '', 0, '', '', '');
# FormEditor: FormElements for 'form' # FormEditor: FormElements for 'form'
INSERT INTO FormElement (formId, name, label, mode, type, checkType, class, ord, size, maxLength, note, clientJs, value, INSERT INTO FormElement (formId, name, label, mode, type, checkType, class, ord, size, maxLength, note, clientJs, value,
...@@ -293,8 +293,7 @@ VALUES ...@@ -293,8 +293,7 @@ VALUES
# FormEditor: FormElement # FormEditor: FormElement
INSERT INTO Form (id, name, title, noteInternal, tableName, permitNew, permitEdit, render, multiSql, parameter, INSERT INTO Form (id, name, title, noteInternal, tableName, permitNew, permitEdit, render, multiSql, parameter,
requiredParameterNew) requiredParameterNew)
VALUES VALUES (2, 'formElement',
(2, 'formElement',
'Form Element Editor. Form : {{SELECT f.id, " / ", f.name FROM Form AS f WHERE f.id = {{formId:S0}} }} (DB: {{dbNameQfq:Y}})', 'Form Element Editor. Form : {{SELECT f.id, " / ", f.name FROM Form AS f WHERE f.id = {{formId:S0}} }} (DB: {{dbNameQfq:Y}})',
'Please secure the form', 'Please secure the form',
'FormElement', 'sip', 'sip', 'bootstrap', '', 'FormElement', 'sip', 'sip', 'bootstrap', '',
...@@ -303,124 +302,140 @@ VALUES ...@@ -303,124 +302,140 @@ VALUES
# FormEditor: FormElements for 'formElement' # FormEditor: FormElements for 'formElement'
INSERT INTO FormElement (id, formId, name, label, mode, type, checkType, class, ord, size, note, clientJs, value, INSERT INTO FormElement (id, formId, name, label, mode, type, checkType, class, ord, size, note, clientJs, value,
sql1, parameter, feIdContainer, subrecordOption, modeSql) sql1, parameter, feIdContainer, subrecordOption, modeSql)
VALUES VALUES (100, 2, 'basic', 'Basic', 'show', 'pill', 'all', 'container', 10, 0, '', '', '', '', '', 0, '', ''),
(100, 2, 'basic', 'Basic', 'show', 'pill', 'all', 'container', 10, 0, '', '', '', '', '', 0, '', ''), (101, 2, 'check_order', 'Check & Order', 'show', 'pill', 'all', 'container', 290, 0, '', '', '', '', '', 0, '',
(101, 2, 'check_order', 'Check & Order', 'show', 'pill', 'all', 'container', 290, 0, '', '', '', '', '', 0, '',
''), ''),
(102, 2, 'layout', 'Layout', 'show', 'pill', 'all', 'container', 390, 0, '', '', '', '', '', 0, '', ''), (102, 2, 'layout', 'Layout', 'show', 'pill', 'all', 'container', 390, 0, '', '', '', '', '', 0, '', ''),
(103, 2, 'value', 'Value', 'show', 'pill', 'all', 'container', 490, 0, '', '', '', '', '', 0, '', ''); (103, 2, 'value', 'Value', 'show', 'pill', 'all', 'container', 490, 0, '', '', '', '', '', 0, '', '');
INSERT INTO FormElement (formId, name, label, mode, type, checkType, class, ord, size, maxLength, note, clientJs, value, INSERT INTO FormElement (formId, name, label, mode, type, checkType, class, ord, size, maxLength, note, clientJs, value,
sql1, parameter, feIdContainer, subrecordOption, dynamicUpdate, bsLabelColumns, bsInputColumns, sql1, parameter, feIdContainer, subrecordOption, dynamicUpdate, bsLabelColumns, bsInputColumns,
bsNoteColumns, modeSql, placeholder, encode) bsNoteColumns, modeSql, placeholder, encode)
VALUES VALUES (2, 'feIdContainer', 'Container', 'show', 'select', 'all', 'native', 120, 0, 0,
(2, 'feIdContainer', 'Container', 'show', 'select', 'all', 'native', 120, 0, 0,
'<a href="{{documentation:Y}}#class-container">Info</a>', '', '', '<a href="{{documentation:Y}}#class-container">Info</a>', '', '',
'{{!SELECT fe.id, CONCAT(fe.type, " / ", fe.name, " (", COUNT(feSub.id), ")" ) FROM FormElement As fe LEFT JOIN FormElement As feSub ON feSub.feIdContainer=fe.id WHERE fe.formId={{formId:SR0}} AND fe.class="container" GROUP BY fe.id ORDER BY fe.type, fe.ord, fe.name }}', '{{!SELECT fe.id, CONCAT(fe.type, " / ", fe.name, " (", COUNT(feSub.id), ")" ) FROM FormElement As fe LEFT JOIN FormElement As feSub ON feSub.feIdContainer=fe.id WHERE fe.formId={{formId:SR0}} AND fe.class="container" GROUP BY fe.id ORDER BY fe.type, fe.ord, fe.name }}',
'emptyItemAtStart', 100, '', 'no', '', '', '', 'emptyItemAtStart', 100, '', 'no', '', '', '',
'{{SELECT IF(COUNT(fe.id)>0, "show", "hidden") FROM Form AS f LEFT JOIN FormElement AS fe ON f.id=fe.formId AND fe.class="container" WHERE f.id={{formId:S0}} GROUP BY f.id}}', '{{SELECT IF(COUNT(fe.id)>0, "show", "hidden") FROM Form AS f LEFT JOIN FormElement AS fe ON f.id=fe.formId AND fe.class="container" WHERE f.id={{formId:S0}} GROUP BY f.id}}',
'', 'specialchar'), '', 'specialchar'),
(2, 'enabled', 'Enabled', 'show', 'checkbox', 'all', 'native', 130, 0, 0, (2, 'enabled', 'Enabled', 'show', 'checkbox', 'all', 'native', 130, 0, 0,
'<a href="{{documentation:Y}}#class-native">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '', '', '<a href="{{documentation:Y}}#class-native">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '', '',
'specialchar'), 'specialchar'),
(2, 'dynamicUpdate', 'Dynamic Update', 'show', 'checkbox', 'all', 'native', 135, 0, 0, (2, 'dynamicUpdate', 'Dynamic Update', 'show', 'checkbox', 'all', 'native', 135, 0, 0,
'<a href="{{documentation:Y}}#dynamic-update">Info</a>', '<a href="{{documentation:Y}}#dynamic-update">Info</a>',
'', '', '', '', 100, '', 'no', '', '', '', '', '', 'specialchar'), '', '', '', '', 100, '', 'no', '', '', '', '', '', 'specialchar'),
(2, 'name', 'Name', 'show', 'text', 'all', 'native', 140, 0, 0, '<a href="{{documentation:Y}}#class-native">Info</a>', (2, 'name', 'Name', 'show', 'text', 'all', 'native', 140, 0, 0,
'<a href="{{documentation:Y}}#class-native">Info</a>',
'', '', '', '', '', '',
'typeAheadSql = [{{indexData:Y}}]SELECT COLUMN_NAME FROM information_schema.columns WHERE table_schema = "{{DB_1_NAME:Y}}" AND table_name = "{{SELECT f.tableName FROM Form AS f WHERE f.id={{formId:S0}}}}" AND COLUMN_NAME LIKE ? ORDER BY COLUMN_NAME\ntypeAheadMinLength = 1\ntypeAheadLimit = 100\ntypeAheadPedantic = 0\n', 'typeAheadSql = [{{indexData:Y}}]SELECT COLUMN_NAME FROM information_schema.columns WHERE table_schema = "{{DB_1_NAME:Y}}" AND table_name = "{{SELECT f.tableName FROM Form AS f WHERE f.id={{formId:S0}}}}" AND COLUMN_NAME LIKE ? ORDER BY COLUMN_NAME\ntypeAheadMinLength = 1\ntypeAheadLimit = 100\ntypeAheadPedantic = 0\n',
100, '<a href="{{documentation:Y}}#class-native">Info</a>', 'no', '', '', '', '', '', 'specialchar'), 100, '<a href="{{documentation:Y}}#class-native">Info</a>', 'no', '', '', '', '', '', 'specialchar'),
(2, 'label', 'Label', 'show', 'text', 'all', 'native', 150, 0, 0, '<a href="{{documentation:Y}}#class-native">Info</a>', (2, 'label', 'Label', 'show', 'text', 'all', 'native', 150, 0, 0,
'<a href="{{documentation:Y}}#class-native">Info</a>',
'', '', '', '', 100, '', 'no', '', '', '', '', '', 'none'), '', '', '', '', 100, '', 'no', '', '', '', '', '', 'none'),
(2, 'mode', 'Mode', 'show', 'radio', 'all', 'native', 160, 0, 0, '<a href="{{documentation:Y}}#class-native">Info</a>', (2, 'mode', 'Mode', 'show', 'radio', 'all', 'native', 160, 0, 0,
'<a href="{{documentation:Y}}#class-native">Info</a>',
'', '', '', 'buttonClass=btn-default', 100, '', 'no', '', '', '', '', '', 'specialchar'), '', '', '', 'buttonClass=btn-default', 100, '', 'no', '', '', '', '', '', 'specialchar'),
(2, 'modeSql', 'Mode sql', 'show', 'text', 'all', 'native', 170, '70,2', 0, (2, 'modeSql', 'Mode sql', 'show', 'text', 'all', 'native', 170, '70,2', 0,
'<a href="{{documentation:Y}}#dynamic-update">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '', '', 'none'), '<a href="{{documentation:Y}}#dynamic-update">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '', '',
(2, 'class', 'Class', 'show', 'select', 'all', 'native', 180, 0, 0, 'none'),
'<a href="{{documentation:Y}}#class-container">Info</a>', '', '{{class:FSRD0:alnumx}}', '', '', 100, '', 'yes', '', '', (2, 'class', 'Class', 'show', 'select', 'all', 'native', 180, 0, 0,
'<a href="{{documentation:Y}}#class-container">Info</a>', '', '{{class:FSRD0:alnumx}}', '', '', 100, '', 'yes',
'', '',
'', '', '', 'none'), '', '', '', 'none'),
(2, 'type', 'Type', 'show', 'select', 'all', 'native', 190, 0, 0, (2, 'type', 'Type', 'show', 'select', 'all', 'native', 190, 0, 0,
'<a href="{{documentation:Y}}#class-native">Native</a>, <a href="{{documentation:Y}}#class-action">Action</a>, <a href="{{documentation:Y}}#class-container">Container</a>', '<a href="{{documentation:Y}}#class-native">Native</a>, <a href="{{documentation:Y}}#class-action">Action</a>, <a href="{{documentation:Y}}#class-container">Container</a>',
'', '', '', '', '', '',
'itemList={{SELECT IF( "{{class:FRD0:alnumx}}"="native","checkbox,date,time,datetime,dateJQW,datetimeJQW,extra,gridJQW,text,editor,annotate,imageCut,note,password,radio,select,subrecord,upload", IF("{{class:FRD0:alnumx}}"="action","beforeLoad,beforeSave,beforeInsert,beforeUpdate,beforeDelete,afterLoad,afterSave,afterInsert,afterUpdate,afterDelete,sendMail,paste", "fieldset,pill,templateGroup") ) }}', 'itemList={{SELECT IF( "{{class:FRD0:alnumx}}"="native","checkbox,date,time,datetime,dateJQW,datetimeJQW,extra,gridJQW,text,editor,annotate,imageCut,note,password,radio,select,subrecord,upload", IF("{{class:FRD0:alnumx}}"="action","beforeLoad,beforeSave,beforeInsert,beforeUpdate,beforeDelete,afterLoad,afterSave,afterInsert,afterUpdate,afterDelete,sendMail,paste", "fieldset,pill,templateGroup") ) }}',
100, '', 'yes', '', '', '', '', '', 'specialchar'), 100, '', 'yes', '', '', '', '', '', 'specialchar'),
(2, 'subrecordOption', 'Subrecord Option', 'show', 'checkbox', 'all', 'native', 200, 0, 0, (2, 'subrecordOption', 'Subrecord Option', 'show', 'checkbox', 'all', 'native', 200, 0, 0,
'<a href="{{documentation:Y}}#subrecord-option">Info</a>', '', '', '', '<a href="{{documentation:Y}}#subrecord-option">Info</a>', '', '', '',
'', 100, '', 'yes', '', '', '', '', 100, '', 'yes', '', '', '',
'{{ SELECT IF("{{type:FRE:alnumx}}"="subrecord" AND "{{class:FRE:alnumx}}"="native", "show", "hidden") }}', '', '{{ SELECT IF("{{type:FRE:alnumx}}"="subrecord" AND "{{class:FRE:alnumx}}"="native", "show", "hidden") }}', '',
'specialchar'), 'specialchar'),
(2, 'parameterLanguageA', 'Language: {{formLanguageALabel:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0, (2, 'parameterLanguageA', 'Language: {{formLanguageALabel:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0,
'<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '',
'{{SELECT IF("{{formLanguageAId:YE}}"="","hidden","show" ) }}', '', 'none'), '{{SELECT IF("{{formLanguageAId:YE}}"="","hidden","show" ) }}', '', 'none'),
(2, 'parameterLanguageB', 'Language: {{formLanguageBLabel:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0, (2, 'parameterLanguageB', 'Language: {{formLanguageBLabel:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0,
'<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '',
'{{SELECT IF("{{formLanguageBId:YE}}"="","hidden","show" ) }}', '', 'none'), '{{SELECT IF("{{formLanguageBId:YE}}"="","hidden","show" ) }}', '', 'none'),
(2, 'parameterLanguageC', 'Language: {{formLanguageCLabel:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0, (2, 'parameterLanguageC', 'Language: {{formLanguageCLabel:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0,
'<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '',
'{{SELECT IF("{{formLanguageCId:YE}}"="","hidden","show" ) }}', '', 'none'), '{{SELECT IF("{{formLanguageCId:YE}}"="","hidden","show" ) }}', '', 'none'),
(2, 'parameterLanguageD', 'Language: {{formLanguageDLabel:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0, (2, 'parameterLanguageD', 'Language: {{formLanguageDLabel:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0,
'<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '',
'{{SELECT IF("{{formLanguageDId:YE}}"="","hidden","show" ) }}', '', 'none'), '{{SELECT IF("{{formLanguageDId:YE}}"="","hidden","show" ) }}', '', 'none'),
(2, 'encode', 'Encode', 'show', 'radio', 'all', 'native', 300, 0, 0, (2, 'encode', 'Encode', 'show', 'radio', 'all', 'native', 300, 0, 0,
'<a href="{{documentation:Y}}#field-encode">Info</a>', '', '', '', 'buttonClass=btn-default', 101, '', 'no', '', '', '<a href="{{documentation:Y}}#field-encode">Info</a>', '', '', '', 'buttonClass=btn-default', 101, '', 'no', '',
'',
'', '', '', 'specialchar'), '', '', '', 'specialchar'),
(2, 'checkType', 'Check Type', 'show', 'radio', 'all', 'native', 310, 0, 0, (2, 'checkType', 'Check Type', 'show', 'radio', 'all', 'native', 310, 0, 0,
'<a href="{{documentation:Y}}#field-checktype">Info</a>', '', '', '', 'buttonClass=btn-default', 101, '', 'yes', '', '<a href="{{documentation:Y}}#field-checktype">Info</a>', '', '', '', 'buttonClass=btn-default', 101, '', 'yes',
'',
'', '', '', '', 'specialchar'), '', '', '', '', 'specialchar'),
(2, 'checkPattern', 'Check Pattern', 'show', 'text', 'all', 'native', 320, 0, 0, (2, 'checkPattern', 'Check Pattern', 'show', 'text', 'all', 'native', 320, 0, 0,
'<a href="{{documentation:Y}}#field-checkpattern">Info</a>, <a href="https://regex101.com/">Regex101</a>', '', '', '', '<a href="{{documentation:Y}}#field-checkpattern">Info</a>, <a href="https://regex101.com/">Regex101</a>', '',
'', '',
'', 101, '', 'yes', '', '', '', '', 101, '', 'yes', '', '', '',
'{{ SELECT IF("{{checkType:FRE:alnumx}}"="pattern" OR "{{checkType:FRE:allbut}}" LIKE "min%", "show", "hidden") }}', '{{ SELECT IF("{{checkType:FRE:alnumx}}"="pattern" OR "{{checkType:FRE:allbut}}" LIKE "min%", "show", "hidden") }}',
'', 'none'), '', 'none'),
#(2, 'onChange', 'JS onChange', 'show', 'text', 'all', 'native', 330, 0, 0, '', '', '', '', '', 101, '', 'no', '', '', '', '', '', 'none'), #(2, 'onChange', 'JS onChange', 'show', 'text', 'all', 'native', 330, 0, 0, '', '', '', '', '', 101, '', 'no', '', '', '', '', '', 'none'),
(2, 'ord', 'Order', 'show', 'text', 'all', 'native', 340, 0, 0, '<a href="{{documentation:Y}}#field-ord">Info</a>', '', (2, 'ord', 'Order', 'show', 'text', 'all', 'native', 340, 0, 0,
'<a href="{{documentation:Y}}#field-ord">Info</a>', '',
'{{SELECT IF({{ord:R0}}=0, MAX(IFNULL(fe.ord,0))+10,{{ord:R0}}) FROM (SELECT 1) AS a LEFT JOIN FormElement AS fe ON fe.formId={{formId:S0}} GROUP BY fe.formId}}', '{{SELECT IF({{ord:R0}}=0, MAX(IFNULL(fe.ord,0))+10,{{ord:R0}}) FROM (SELECT 1) AS a LEFT JOIN FormElement AS fe ON fe.formId={{formId:S0}} GROUP BY fe.formId}}',
'', '', 101, '', 'no', '', '', '', '', '', 'specialchar'), '', '', 101, '', 'no', '', '', '', '', '', 'specialchar'),
(2, 'tabindex', 'tabindex', 'show', 'text', 'all', 'native', 350, 0, 0, (2, 'tabindex', 'tabindex', 'show', 'text', 'all', 'native', 350, 0, 0,
'<a href="{{documentation:Y}}#field-tabindex">Info</a>', '', '', '', '', 101, '', 'no', '', '', '', '', '', '<a href="{{documentation:Y}}#field-tabindex">Info</a>', '', '', '', '', 101, '', 'no', '', '', '', '', '',
'specialchar'), 'specialchar'),
(2, 'adminNote', 'Internal Note', 'show', 'text', 'all', 'native', 360, '60,4', 0, '', '', '', '', '', 101, '', 'no', (2, 'adminNote', 'Internal Note', 'show', 'text', 'all', 'native', 360, '60,4', 0, '', '', '', '', '', 101, '',
'no',
'', '', '', '',
'', '', '', 'specialchar'), '', '', '', 'specialchar'),