diff --git a/extension/Classes/Core/Database/DatabaseUpdateData.php b/extension/Classes/Core/Database/DatabaseUpdateData.php index 6710d5d5eb839fd3f60e3cfe0f72150f06c4fac5..8704cd78808e978000d1b87aa92c82e0209885e2 100644 --- a/extension/Classes/Core/Database/DatabaseUpdateData.php +++ b/extension/Classes/Core/Database/DatabaseUpdateData.php @@ -213,6 +213,17 @@ $UPDATE_ARRAY = array( "ALTER TABLE `FormElement` ADD `encryptionMethod` ENUM('Default', 'AES-128','AES-256') NOT NULL DEFAULT 'Default' AFTER `encryption`;", ], + '22.8.1' => [ + "ALTER TABLE `FormElement` CHANGE `formId` `formId` INT(11) NOT NULL DEFAULT '0';", + "ALTER TABLE `Dirty` CHANGE `recordId` `recordId` INT(11) NOT NULL DEFAULT '0';", + "ALTER TABLE `FormSubmitLog` CHANGE `formId` `formId` INT(11) NOT NULL DEFAULT '0';", + "ALTER TABLE `FormSubmitLog` CHANGE `recordId` `recordId` INT(11) NOT NULL DEFAULT '0';", + "ALTER TABLE `Cron` CHANGE `grId` `grId` INT(11) NOT NULL DEFAULT '0';", + "ALTER TABLE `Cron` CHANGE `xId` `xId` INT(11) NOT NULL DEFAULT '0';", + "ALTER TABLE `Split` CHANGE `xId` `xId` INT(11) NOT NULL DEFAULT '0';", + "ALTER TABLE `Setting` CHANGE `public` `public` TINYINT(1) NOT NULL DEFAULT '0';", + ], + ); diff --git a/extension/Classes/Core/Helper/EncryptDecrypt.php b/extension/Classes/Core/Helper/EncryptDecrypt.php index e7bcc257ec9e91daf6d4fcf044043792d9116e43..59c7959c53d2a3af8577fb1fbbf94908a9e96d4c 100644 --- a/extension/Classes/Core/Helper/EncryptDecrypt.php +++ b/extension/Classes/Core/Helper/EncryptDecrypt.php @@ -358,7 +358,11 @@ class EncryptDecrypt { * @param string $value * @return boolean */ - public static function checkForEncryptedValue(string $value): bool { + public static function checkForEncryptedValue($value): bool { + + if (is_null($value)) { + $value = ''; + } // Try to split value and check for first element of array $arrayValues = explode(':', $value, 4); if (isset($arrayValues[0]) && $arrayValues[0] !== '') { diff --git a/extension/Classes/Core/Helper/Support.php b/extension/Classes/Core/Helper/Support.php index 578670711bf9fb19cd0462e5849141730c535598..b61fdcf9e4c8c5595efc5e5458aa82216a513bc5 100644 --- a/extension/Classes/Core/Helper/Support.php +++ b/extension/Classes/Core/Helper/Support.php @@ -1137,7 +1137,7 @@ class Support { * @return bool|int a) 'false' if there is no length definition, b) length definition, c) * date|time|datetime|timestamp use hardcoded length */ - private static function getColumnSize($typeSpec) { + public static function getColumnSize($typeSpec) { $matches = array(); @@ -1149,6 +1149,22 @@ class Support { return 19; case 'time': // hh:mm:ss return 8; + case 'tinytext': + case 'tinyblob': + return 255; + case 'text': + case 'blob': + return 65535; + case 'mediumtext': + case 'mediumblob': + return 16777215; + case 'longtext': + case 'longblob': + return 4294967295; + case 'inet4': + return 4; + case 'inet6': + return 16; default: if (substr($typeSpec, 0, 4) === 'set(' || substr($typeSpec, 0, 5) === 'enum(') { return self::maxLengthSetEnum($typeSpec); @@ -1158,8 +1174,25 @@ class Support { // e.g.: string(64) >> 64, enum('yes','no') >> false if (1 === preg_match('/\((.+)\)/', $typeSpec, $matches)) { - if (is_numeric($matches[1])) - return $matches[1]; + // Check for 'decimal(5,3)' or 'decimal(5,3) unsigned' + if (substr($typeSpec, 0, 8) === 'decimal(') { + $cnt = 0; + // $arr[0]=m, $arr[1]=d + $arr = explode(',', $matches[1]); + $tmp = $arr[1] ?? 0; + if ($tmp > 0) { + $cnt += $tmp + 1; + } + if (strpos('unsigned', $typeSpec) !== false) { + // Without 'unsigned', a '-' (minus) might be given. + $cnt++; + } + return $arr[0] + $cnt; + } else { + + if (is_numeric($matches[1])) + return (int)$matches[1]; + } } return false; diff --git a/extension/Classes/Sql/qfqDefaultTables.sql b/extension/Classes/Sql/qfqDefaultTables.sql index 1416d7112c842e65a8c9383dcbedafddf423fb7b..13ed6b10bd4f73271965064d678cdbe36abc4a30 100644 --- a/extension/Classes/Sql/qfqDefaultTables.sql +++ b/extension/Classes/Sql/qfqDefaultTables.sql @@ -59,7 +59,7 @@ CREATE TABLE IF NOT EXISTS `Form` CREATE TABLE IF NOT EXISTS `FormElement` ( `id` INT(11) NOT NULL AUTO_INCREMENT, - `formId` INT(11) NOT NULL, + `formId` INT(11) NOT NULL DEFAULT '0', `feIdContainer` INT(11) NOT NULL DEFAULT '0', `dynamicUpdate` ENUM ('yes', 'no') NOT NULL DEFAULT 'no', `encryption` ENUM ('yes', 'no') NOT NULL DEFAULT 'no', @@ -132,7 +132,7 @@ CREATE TABLE IF NOT EXISTS `Dirty` `id` INT(11) NOT NULL AUTO_INCREMENT, `sip` VARCHAR(255) NOT NULL, `tableName` VARCHAR(255) NOT NULL, - `recordId` INT(11) NOT NULL, + `recordId` INT(11) NOT NULL DEFAULT '0', `expire` DATETIME NOT NULL, `recordHashMd5` CHAR(32) NOT NULL, `tabUniqId` CHAR(32) NOT NULL, @@ -187,9 +187,9 @@ CREATE TABLE IF NOT EXISTS `FormSubmitLog` `clientIp` VARCHAR(64) NOT NULL, `feUser` VARCHAR(64) NOT NULL, `userAgent` TEXT NOT NULL, - `formId` INT(11) NOT NULL, + `formId` INT(11) NOT NULL DEFAULT '0', `formName` VARCHAR(255) NOT NULL, - `recordId` INT(11) NOT NULL, + `recordId` INT(11) NOT NULL DEFAULT '0', `pageId` INT NOT NULL, `sessionId` VARCHAR(32) NOT NULL, `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -224,8 +224,8 @@ CREATE TABLE IF NOT EXISTS `Clipboard` CREATE TABLE IF NOT EXISTS `Cron` ( `id` INT(11) NOT NULL AUTO_INCREMENT, - `grId` INT(11) NOT NULL, - `xId` INT(11) NOT NULL, + `grId` INT(11) NOT NULL DEFAULT '0', + `xId` INT(11) NOT NULL DEFAULT '0', `type` ENUM ('mail', 'website') NOT NULL DEFAULT 'website', `lastRun` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', `lastStatus` TEXT NOT NULL, @@ -254,7 +254,7 @@ CREATE TABLE IF NOT EXISTS `Split` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `tableName` VARCHAR(255) NOT NULL, - `xId` INT(11) NOT NULL, + `xId` INT(11) NOT NULL DEFAULT '0', `pathFileName` VARCHAR(255) NOT NULL, `modified` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -272,7 +272,7 @@ CREATE TABLE IF NOT EXISTS `Setting` `type` ENUM ('', 'tablesorter') NOT NULL, `readonly` ENUM ('yes', 'no') NOT NULL DEFAULT 'no' COMMENT 'Settings can''t be modified.', `name` VARCHAR(64) NOT NULL, - `public` TINYINT(1) NOT NULL, + `public` TINYINT(1) NOT NULL DEFAULT '0', `feUser` VARCHAR(32) NOT NULL COMMENT 'In case there is no logged in user, take QFQ cookie.', `tableId` VARCHAR(64) NOT NULL, `view` TEXT NOT NULL, diff --git a/extension/Classes/Sql/testtables.sql b/extension/Classes/Sql/testtables.sql index 891eb2c4d897e799387160f0bed697d04c76fd93..1760c1bf51e273b759a930e547c5b8d7f08e118a 100644 --- a/extension/Classes/Sql/testtables.sql +++ b/extension/Classes/Sql/testtables.sql @@ -24,7 +24,7 @@ DROP TABLE IF EXISTS PersFunction; CREATE TABLE PersFunction ( id BIGINT AUTO_INCREMENT PRIMARY KEY, - personId BIGINT, + personId BIGINT DEFAULT '0', type ENUM ('Student', 'Assistant', 'Professor', 'Administration'), start DATE NOT NULL DEFAULT '0000-00-00', end DATE NOT NULL DEFAULT '0000-00-00', diff --git a/extension/Resources/Private/Form/form.json b/extension/Resources/Private/Form/form.json index c107b62bf51780f52197ef07a14dd96f5913fdf0..7981ec3bfcbceed082ab0b8fa43284288cbc537b 100644 --- a/extension/Resources/Private/Form/form.json +++ b/extension/Resources/Private/Form/form.json @@ -1586,7 +1586,7 @@ { "dynamicUpdate": "no", "enabled": "yes", - "name": "Table Definition", + "name": "TableDefinition", "label": "Table Definition", "mode": "show", "modeSql": "", @@ -1662,7 +1662,7 @@ "deleted": "no", "modified": "2022-06-03 15:19:42", "created": "2022-06-03 15:06:55", - "containerName_ff": "Table Definition" + "containerName_ff": "TableDefinition" } ] } \ No newline at end of file diff --git a/extension/Resources/Private/Form/formElement.json b/extension/Resources/Private/Form/formElement.json index 71563812d150f87616ccdf24139b2cead95a6900..7e796a9f0ea9a1b859e4b93aa5aeff4fbd7159d0 100644 --- a/extension/Resources/Private/Form/formElement.json +++ b/extension/Resources/Private/Form/formElement.json @@ -1664,6 +1664,91 @@ "deleted": "no", "modified": "2021-04-06 12:05:41", "created": "2021-04-06 12:05:41" + }, + { + "dynamicUpdate": "no", + "encryption": "no", + "encryptionMethod": "Default", + "enabled": "yes", + "name": "tableDefinition", + "label": "Table Definition", + "mode": "show", + "modeSql": "", + "class": "container", + "type": "pill", + "subrecordOption": "", + "encode": "specialchar", + "checkType": "auto", + "checkPattern": "", + "onChange": "", + "ord": 670, + "tabindex": 0, + "size": "", + "maxLength": "", + "labelAlign": "default", + "bsLabelColumns": "", + "bsInputColumns": "", + "bsNoteColumns": "", + "rowLabelInputNote": "row,label,\/label,input,\/input,note,\/note,\/row", + "note": "", + "adminNote": "", + "tooltip": "", + "placeholder": "", + "value": "", + "sql1": "", + "parameter": "", + "parameterLanguageA": "", + "parameterLanguageB": "", + "parameterLanguageC": "", + "parameterLanguageD": "", + "clientJs": "", + "feGroup": "", + "deleted": "no", + "modified": "2022-08-28 09:41:12", + "created": "2022-08-28 09:37:36" + }, + { + "dynamicUpdate": "no", + "encryption": "no", + "encryptionMethod": "Default", + "enabled": "yes", + "name": "Table Definition", + "label": "", + "mode": "show", + "modeSql": "", + "class": "native", + "type": "note", + "subrecordOption": "", + "encode": "specialchar", + "checkType": "auto", + "checkPattern": "", + "onChange": "", + "ord": 680, + "tabindex": 0, + "size": "", + "maxLength": "", + "labelAlign": "default", + "bsLabelColumns": "", + "bsInputColumns": "col-md-12", + "bsNoteColumns": "", + "rowLabelInputNote": "row,input,\/input,\/row", + "note": "", + "adminNote": "", + "tooltip": "", + "placeholder": "", + "value": "#!report\r\n\r\n10 {\r\n sql = SELECT tableName AS _tableName FROM {{dbNameQfq:Y}}.Form AS f WHERE f.id={{formId:SR0}}\r\n althead = Please save the record.\r\n 20 {\r\n sql = SHOW COLUMNS FROM {{dbNameData:Y}}.{{tableName:RE}}\r\n head = \r\n rend = <\/tr>\r\n fbeg =
Field<\/th>Type<\/th>Null<\/th>Key<\/th>Default<\/th>Extra<\/th><\/tr><\/thead>\r\n tail = <\/table>\r\n rbeg =
\r\n fend = <\/td>\r\n}\r\n}", + "sql1": "", + "parameter": "", + "parameterLanguageA": "", + "parameterLanguageB": "", + "parameterLanguageC": "", + "parameterLanguageD": "", + "clientJs": "", + "feGroup": "", + "deleted": "no", + "modified": "2022-08-28 09:40:13", + "created": "2022-08-28 09:40:13", + "containerName_ff": "tableDefinition" } ] } \ No newline at end of file diff --git a/extension/ext_conf_template.txt b/extension/ext_conf_template.txt index cd38498e0d5076a835036e87dfa63559ab6a500b..1dd6b548b2b0cbb8758fd1ffb878a2922a4e030d 100644 --- a/extension/ext_conf_template.txt +++ b/extension/ext_conf_template.txt @@ -7,7 +7,7 @@ render = single # cat=config/config; type=string; label=Max file size for file uploads:If empty, take minimum of 'post_max_size' and 'upload_max_filesize' (PHP.INI). maxFileSize = -# cat=config/config; type=string; label=Base URL of the current Typo3 installation: Example: https://your.base.url/including/sub/dir. Separate multiple URLs with comma. Final one will dynamically detected. Will be used to convert local pages to PDF. Use {{baseUrl:Y}} whenever the own URL should be displayed. Skip the scheme if the website needs to be accessible with http and https. +# cat=config/config; type=string; label=Base URL of the current Typo3 installation. Use {{baseUrl:Y}} whenever the own URL should be referenced. Important for downloads and PDF conversion too. Example: https://your.base.url/including/sub/dir. Separate multiple URLs with comma. Final one will detected dynamically. Skip the scheme if the website needs to be accessible with http and https. Advanced example: first.base.url/sub1,second.example.url baseUrl = # cat=config/date; type=string; label=Date format:Default is 'dd.mm.yyyy'. Possible options: 'yyyy-mm-dd', 'dd.mm.yyyy' diff --git a/javascript/src/TypeAhead.js b/javascript/src/TypeAhead.js index 800225ba969c2728977e280f3bc9df81972bd3bc..0ea7911ae0c55dd64a44fc8eb4422164162ffb75 100644 --- a/javascript/src/TypeAhead.js +++ b/javascript/src/TypeAhead.js @@ -47,7 +47,8 @@ var QfqNS = QfqNS || {}; var url = n.TypeAhead.makeUrl(typeahead_endpoint, $element); url = url.replace('%QUERY', ''); console.log(url); - $.getJSON(url, {}, console.log); // API by hand + // Seems to trigger an empty query - why? + //$.getJSON(url, {}, console.log); // API by hand // initialize typeahead (either with or without tags) if ($element.data('typeahead-tags')) { @@ -123,6 +124,7 @@ var QfqNS = QfqNS || {}; // when tag is pushed, look up key and add it to existingTags tagApi.bind('tm:pushed', function (e, tag) { + if(tag === "") return; var tagLookup = typeaheadList.filter(function (t) {return t.value.toLowerCase() === tag.toLowerCase();})[0]; if (undefined === tagLookup) { existingTags.push({key: 0, value: tag}); diff --git a/less/qfq-bs.css.less b/less/qfq-bs.css.less index 6f75567dc2074810fde7a15e1065067dccdf41ba..41bdfd177da580224c6682ffabd68b76163d004a 100644 --- a/less/qfq-bs.css.less +++ b/less/qfq-bs.css.less @@ -1346,6 +1346,14 @@ thead.qfq-sticky td { background-color: #1a1a1a; } +.qfq-max-width-1280 { + max-width: 1280px; +} + +.qfq-max-width-1600 { + max-width: 1600px; +} + @font-face { font-family: 'password'; font-style: normal;