diff --git a/Documentation/Report.rst b/Documentation/Report.rst index d47c1e5e865704cf473c3c5b9580474481be4ae5..5d40a5800bb0777faae202f9ba3fbe3b4702e94f 100644 --- a/Documentation/Report.rst +++ b/Documentation/Report.rst @@ -1872,8 +1872,8 @@ JSON answer example:: .. _special-sql-functions: -Special SQL Functions (prepared statements) -------------------------------------------- +Special SQL Functions (stored procedure) +---------------------------------------- .. _qbar-escape-qfq-delimiter: diff --git a/extension/Classes/Core/Constants.php b/extension/Classes/Core/Constants.php index 943a0f48f2642e17a04666750b77bb4c08391b30..ff499bf0cc6e1804abafc20b60e46dcdbaea24f7 100644 --- a/extension/Classes/Core/Constants.php +++ b/extension/Classes/Core/Constants.php @@ -1744,6 +1744,7 @@ const C_TITLE = 'title'; const C_NO_WRAP = 'noWrap'; const C_SPECIAL = 'special'; const C_HIDE = 'hide'; +const C_ENCRYPTION_METHOD = SYSTEM_ENCRYPTION_METHOD; const COLUMN_WRAP_TOKEN = '+'; const COLUMN_STORE_USER = '='; diff --git a/extension/Classes/Core/Database/Database.php b/extension/Classes/Core/Database/Database.php index d1921faff0edb87f01ba83b8a502fd87341c8a86..193af4ed50b8370333b899879c6c0fe009c5fc9d 100644 --- a/extension/Classes/Core/Database/Database.php +++ b/extension/Classes/Core/Database/Database.php @@ -1168,6 +1168,7 @@ class Database { } /** + * * Author: Enis Nuredini * Get table name by form id. * Needed for encryption feature diff --git a/extension/Classes/Core/Helper/EncryptDecrypt.php b/extension/Classes/Core/Helper/EncryptDecrypt.php index a67bf9680431f46c8f0b8356afeb18fc1c5d277e..8e40b58f9e04404c8b929c5b5b02ab681b1e79d9 100644 --- a/extension/Classes/Core/Helper/EncryptDecrypt.php +++ b/extension/Classes/Core/Helper/EncryptDecrypt.php @@ -210,26 +210,26 @@ class EncryptDecrypt { $store = Store::getInstance(); $dbIndexData = $dbIndex; $dbArray[$dbIndexData] = new Database($dbIndexData); + $indexQfq = $store->getVar(SYSTEM_DB_INDEX_QFQ, STORE_SYSTEM, SANITIZE_ALLOW_ALL); $referenceFieldName = $store->getVar(F_NAME, STORE_FORM, SANITIZE_ALLOW_ALL); - // Get form id from needed form -> form in which inside is actual form element $referenceFormId = $store->getVar(FE_FORM_ID, STORE_FORM, SANITIZE_ALLOW_ALL); // Get the right table name with the form id if ($referenceFormId) { - $tableNameArray = $dbArray[$dbIndexData]->getTableNameById($referenceFormId); + if ($indexQfq != $dbIndexData) { + $dbArrayQfq[$indexQfq] = new Database($indexQfq); + $tableNameArray = $dbArrayQfq[$indexQfq]->getTableNameById($referenceFormId); + } else { + $tableNameArray = $dbArray[$dbIndexData]->getTableNameById($referenceFormId); + } $referenceTableName = $tableNameArray[0][F_TABLE_NAME]; $tableDefinition = $dbArray[$dbIndexData]->getTableDefinition($referenceTableName); - // Get dbFieldType from table definition - foreach ($tableDefinition as $column => $argument) { - foreach ($argument as $property => $value) { - if ($property === 'Field') { - if ($value === $referenceFieldName) { - $dbFieldType = $argument['Type']; - break; - } - } + foreach ($tableDefinition as $column) { + if ($column['Field'] === $referenceFieldName) { + $dbFieldType = $column['Type']; + break; } } diff --git a/extension/Classes/Core/QuickFormQuery.php b/extension/Classes/Core/QuickFormQuery.php index 21c9664eedde882129280655775a9ffa757a0ea4..38a267519dc708bc53325e26e67cd28c60f71d4b 100644 --- a/extension/Classes/Core/QuickFormQuery.php +++ b/extension/Classes/Core/QuickFormQuery.php @@ -304,7 +304,7 @@ class QuickFormQuery { // Show system messages if be-user logged in if (T3Info::beUserLoggedIn()) { - foreach (self::$systemMessages AS $message) { + foreach (self::$systemMessages as $message) { $html = '<div class="alert alert-warning">' . $message . '</div>' . $html; } } @@ -1688,7 +1688,10 @@ class QuickFormQuery { } else { $systemInlineReport = false; } - $this->inlineReport = $systemInlineReport; + + if ($this->inlineReport) { + $this->inlineReport = $systemInlineReport; + } if ($beUserLoggedIn && $this->inlineReport) { $html .= $this->buildInlineReport($this->t3data[T3DATA_UID] ?? null, $this->t3data[T3DATA_REPORT_PATH_FILENAME] ?? null, diff --git a/extension/Classes/Core/Report/Report.php b/extension/Classes/Core/Report/Report.php index 3cf8c422bbd687fb16156c8a11e5231bbc1fcbfc..867455285d5ce182700bc8a574cd7939179471e2 100644 --- a/extension/Classes/Core/Report/Report.php +++ b/extension/Classes/Core/Report/Report.php @@ -820,18 +820,12 @@ class Report { // Author: Enis Nuredini // Split and get given encryption method from column name + $encryptionMethod = null; $key = $arr[0]; $keyArray = explode('=', $key, 2); if (isset($keyArray[1]) && $keyArray[1] !== '') { $encryptionMethod = $keyArray[1]; - if (EncryptDecrypt::checkForValidEncryptMethod($encryptionMethod)) { - try { - $this->store::setVar(ENCRYPTION_CIPHER_METHOD_COLUMN_NAME, $encryptionMethod, STORE_SYSTEM); - } catch (\CodeException|\UserFormException $e) { - throw new \CodeException("No access to store.", ERROR_NO_STORE_FOUND); - } - $arr[0] = $keyArray[0]; - } + $arr[0] = $keyArray[0]; } // End author @@ -867,6 +861,9 @@ class Report { if (($newKeys[$ii][C_TITLE][0] ?? '') == TOKEN_COLUMN_CTRL) { $newKeys[$ii][C_TITLE] = substr($newKeys[$ii][C_TITLE], 1); } + if ($encryptionMethod !== null) { + $newKeys[$ii][C_ENCRYPTION_METHOD] = $encryptionMethod; + } $ii++; } @@ -1334,14 +1331,13 @@ class Report { // Author: Enis Nuredini case COLUMN_ENCRYPT: - $encryptionMethodColumn = $this->store->getVar(ENCRYPTION_CIPHER_METHOD_COLUMN_NAME, STORE_SYSTEM, SANITIZE_ALLOW_ALL); - // If method from column not given then use default or check if the given one is valid - if ($encryptionMethodColumn) { - if (!EncryptDecrypt::checkForValidEncryptMethod($encryptionMethodColumn)) { - throw new \UserReportException ("Invalid encryption method used in special column name: $encryptionMethodColumn", ERROR_INVALID_ENCRYPTION_METHOD); - } - } else { - $encryptionMethodColumn = $this->store->getVar(SYSTEM_ENCRYPTION_METHOD, STORE_SYSTEM, SANITIZE_ALLOW_ALL); + $encryptionMethodColumn = $this->store->getVar(SYSTEM_ENCRYPTION_METHOD, STORE_SYSTEM, SANITIZE_ALLOW_ALL); + if (isset($columnCtrl[C_ENCRYPTION_METHOD])) { + $encryptionMethodColumn = $columnCtrl[C_ENCRYPTION_METHOD]; + } + // check if the given one is valid + if (!EncryptDecrypt::checkForValidEncryptMethod($encryptionMethodColumn)) { + throw new \UserReportException ("Invalid encryption method used in special column name: $encryptionMethodColumn", ERROR_INVALID_ENCRYPTION_METHOD); } $content .= EncryptDecrypt::buildDatabaseValue($columnValue, $encryptionKey, $encryptionMethodColumn); diff --git a/extension/Classes/Core/Save.php b/extension/Classes/Core/Save.php index 52f5a8ae8f50d9ac6dbb8063b0b79694d289dae0..8b35b7d1680de5a7b6cb1abc90ccdd3608c0b2f5 100644 --- a/extension/Classes/Core/Save.php +++ b/extension/Classes/Core/Save.php @@ -114,26 +114,23 @@ class Save { if ($formName === 'formElement') { $encryptionState = $this->store->getVar(FE_ENCRYPTION, STORE_FORM, SANITIZE_ALLOW_ALL); - $databaseFieldType = ''; - if ($encryptionState === 'yes' && $encryptionKey == '') { - throw new \UserFormException("Missing encryption key.", ERROR_MISSING_ENCRYPTION_KEY); + $databaseFieldType = 'No real column'; + if ($encryptionState === 'yes') { + if ($encryptionKey == '') { + throw new \UserFormException("Missing encryption key.", ERROR_MISSING_ENCRYPTION_KEY); + } + $indexData = $this->store->getVar(SYSTEM_DB_INDEX_DATA, STORE_SYSTEM, SANITIZE_ALLOW_ALL); + if (!EncryptDecrypt::validDatabaseFieldType($indexData, $databaseFieldType)) { + throw new \UserFormException("Invalid database field type for encryption: " . $databaseFieldType . ". Only varchar or text.", ERROR_INVALID_DATABASE_FIELD_TYPE); + } } - - //TODO: notfallmaessig deaktiviert - #14622 -// if (!EncryptDecrypt::validDatabaseFieldType($this->formSpec[F_DB_INDEX], $databaseFieldType) && $encryptionState === 'yes') { -// throw new \UserFormException("Invalid database field type for encryption: " . $databaseFieldType . ". Only varchar or text.", ERROR_INVALID_DATABASE_FIELD_TYPE); -// } } else { // Get all elements which are to encrypt and their information $elementsToEncrypt = EncryptDecrypt::getElementsToEncrypt($this->feSpecNative); // Database field type and length from each form element is needed - $dbFieldAttributes = array(); -// $formId = $this->formSpec['id']; $dbObject = $this->dbArray[$this->dbIndexData]; -// if ($formId) { $dbFieldAttributes = EncryptDecrypt::getDbFieldAttributes($this->formSpec[F_TABLE_NAME], $dbObject); -// } if (EncryptDecrypt::hasEnoughSpace($elementsToEncrypt, $dbFieldAttributes)) { // Overwrite values in form store with encrypted values diff --git a/javascript/src/Element/NameSpaceFunctions.js b/javascript/src/Element/NameSpaceFunctions.js index 54168318a2c9c6cffb8fe651af354594d5febe7a..e30998c3fee2087c1bc6aa42e96250edbf096d87 100644 --- a/javascript/src/Element/NameSpaceFunctions.js +++ b/javascript/src/Element/NameSpaceFunctions.js @@ -31,7 +31,12 @@ QfqNS.Element = QfqNS.Element || {}; var elementName; var $element = $('[name="' + QfqNS.escapeJqueryIdSelector(name) + '"]:not([type="hidden"])'); if ($element.length === 0) { - throw Error('No element with name "' + name + '" found.'); + // Get right element for tinymce with given name (is hidden input field) + $element = $('[name="' + QfqNS.escapeJqueryIdSelector(name) + '"]'); + $element = getTypeAheadInput($element); + if ($element === undefined) { + throw Error('No element with name "' + name + '" found.'); + } } // Handle <select> and <textarea> @@ -51,9 +56,19 @@ QfqNS.Element = QfqNS.Element || {}; } var type = $element[0].getAttribute('type').toLowerCase(); + + if (type === 'checkbox') { + var $formGroup = $('#' + $element.attr('id') + '-i'); + if (!$formGroup || $formGroup.length === 0) { + type = 'nonFormGroupCheckbox'; + } + } + switch (type) { case 'checkbox': return new n.Checkbox($element); + case 'nonFormGroupCheckbox': + return $element; case 'radio': return new n.Radio($element); case 'text': @@ -67,10 +82,23 @@ QfqNS.Element = QfqNS.Element || {}; case "month": case "time": case "week": + case "search": return new n.Textual($element); default: throw new Error("Don't know how to handle <input> of type '" + type + "'"); } + // Get typeahead input element + function getTypeAheadInput (elem) { + var selector = '.twitter-typeahead'; + var sibling = elem.prev(); + var siblingCount = elem.siblings().length; + // If the sibling matches our selector, use it + // If not, jump to the next sibling and continue the loop + for (var i = 0; i < siblingCount; i++) { + if (sibling.is(selector)) return sibling.children('.tt-input'); + sibling = sibling.prev(); + } + } }; })(QfqNS.Element); \ No newline at end of file diff --git a/javascript/src/QfqForm.js b/javascript/src/QfqForm.js index 798d41a9c8dcebc4a4e7f472feb7961c650375d3..ca0c47c9b1f826d5c4760b3d1f0833129ac4690a 100644 --- a/javascript/src/QfqForm.js +++ b/javascript/src/QfqForm.js @@ -1228,6 +1228,7 @@ var QfqNS = QfqNS || {}; * * @param configuration {array} array of objects. */ + var typeAheadFlag = false; n.QfqForm.prototype.applyFormConfiguration = function (configuration) { var arrayLength = configuration.length; var countElementArray = 0; @@ -1239,32 +1240,25 @@ var QfqNS = QfqNS || {}; continue; } try { - var element = $('[name="' + QfqNS.escapeJqueryIdSelector(formElementName) + '"]:not([type="hidden"])'); - // checkboxes without being in form groups aren't triggered over dynamic update, we need to handle them separately. - // for checkboxes with itemList (multiple) we need the countElementArray to trigger the right box - if($(element).attr('type') !== undefined){ - if($(element).attr('type').toLowerCase() ==='checkbox'){ - if(element.length > 1 && element.length !== countElementArray){ - element = element[countElementArray]; - countElementArray++; - } - if (configurationItem.value !== undefined) { - $(element).prop('checked',configurationItem.value); - } - } - }else { - // For all other form-elements the general script is used. - element = n.Element.getElement(formElementName); - // Cleaner way to set states for tinymce - // This triggers the event on the unaccesable textarea - // The tinymce registers a listener on the textarea - // See helper/tinyMCE.js for details + var element = n.Element.getElement(formElementName); + // Cleaner way to set states for tinymce + // This triggers the event on the unaccesable textarea + // The tinymce registers a listener on the textarea + // See helper/tinyMCE.js for details + if (element.$element !== undefined) { if (element.$element.hasClass('qfq-tinymce')) { element.$element.trigger("blur", [configurationItem]); } if (configurationItem.value !== undefined) { - element.setValue(configurationItem.value); + if (element.$element.hasClass('qfq-typeahead')) { + if (configurationItem.value !== 0) { + element.setValue(configurationItem.value); + } + typeAheadFlag = true; + } else { + element.setValue(configurationItem.value); + } } if (configurationItem.readonly !== undefined) { @@ -1296,7 +1290,28 @@ var QfqNS = QfqNS || {}; } } countElementArray = 0; + } else { + // checkboxes without being in form groups aren't triggered over dynamic update, we need to handle them separately. + // for checkboxes with itemList (multiple) we need the countElementArray to trigger the right box + if ($(element).attr('type').toLowerCase() === 'checkbox') { + var elementLength = element.length; + if (elementLength > 1) { + if (elementLength !== countElementArray) { + element = element[countElementArray]; + countElementArray++; + + if (elementLength === countElementArray) { + countElementArray = 0; + } + } + } + + if (configurationItem.value !== undefined) { + $(element).prop('checked', configurationItem.value); + } + } } + } catch (e) { n.Log.error(e.message); } @@ -1310,6 +1325,11 @@ var QfqNS = QfqNS || {}; } n.ElementUpdate.updateAll(configuration); + + // Trigger typeahead after dynamic update to show prefetch value, except empty values + if (typeAheadFlag) { + $('.tt-input[value!="0"]').blur(); + } }; /**