diff --git a/extension/Documentation/Manual.rst b/extension/Documentation/Manual.rst index 9a02d4291a94a7fa752a5bef9b691f9288b721dd..a2d9ba802073942f55f7077a3a86182fba9a5edd 100644 --- a/extension/Documentation/Manual.rst +++ b/extension/Documentation/Manual.rst @@ -1563,12 +1563,13 @@ Prefetch ^^^^^^^^ After 'form load' with an existing record, the user epects to see the previous saved data. In case there is an *id* to -*value* translation, the *value* does not exist in the database, instead it has to be fetched again dynamically from the -LDAP server. A precise LDAP query has to be defined to force this: +*value* translation, the *value* does not exist in the database, instead it has to be fetched again dynamically. +A precise LDAP or SQL query has to be defined to force this: * *Form.parameter* or *FormElement.parameter*: * *typeAheadLdapSearchPrefetch* = `(mail=?)` + * *typeAheadSqlPrefetch* = `SELECT firstName, ' ', lastName FROM person WHERE id = ?` This situation also applies in *pedantic* mode to verify the user input after each change. @@ -2488,6 +2489,7 @@ See also at specific *FormElement* definitions. | typeAheadLimit | string | See `input-typeahead`_ | | typeAheadMinLength | string | | | typeAheadSql | string | | +| typeAheadSqlPrefetch | string | | +------------------------+--------+----------------------------------------------------------------------------------------------------------+ | editor-plugins | string | See `input-editor`_ | | editor-toolbar | string | | @@ -2856,6 +2858,11 @@ SQL * The value, typed by the user, will be replaced on all places where a `?` appears. * All `?` will be automatically surrounded by '%'. Therefore wildcard search is implemented: `... LIKE '%%' ...` + * *typeAheadSqlPrefetch* = `SELECT firstName, ' ', lastName FROM person WHERE id = ?` + + * If the query returns several results, only the first one is returned and displayed. + * If the query selects multiple columns, the columns are concatenated. + LDAP ;;;; diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php index abe3ee8ff179fdaf5e5e5a68647c67f236ea53f9..4b43864f34361a70548726c8a33c507e6e484e6e 100644 --- a/extension/qfq/qfq/AbstractBuildForm.php +++ b/extension/qfq/qfq/AbstractBuildForm.php @@ -685,7 +685,6 @@ abstract class AbstractBuildForm { * @throws UserFormException */ private function prepareFillStoreFireLdap(array $formElement) { - $config = array(); if (isset($formElement[FE_FILL_STORE_LDAP]) || isset($formElement[FE_TYPEAHEAD_LDAP])) { $keyNames = [F_LDAP_SERVER, F_LDAP_BASE_DN, F_LDAP_ATTRIBUTES, @@ -1192,14 +1191,19 @@ abstract class AbstractBuildForm { */ private function typeAheadBuildParam(array &$formElement) { - $urlParam = ''; + $arr = []; $formElement[FE_TYPEAHEAD_LIMIT] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LIMIT, TYPEAHEAD_DEFAULT_LIMIT); $formElement[FE_TYPEAHEAD_MINLENGTH] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_MINLENGTH, 2); if (isset($formElement[FE_TYPEAHEAD_SQL])) { $sql = $this->checkSqlAppendLimit($formElement[FE_TYPEAHEAD_SQL], $formElement[FE_TYPEAHEAD_LIMIT]); - $urlParam = FE_TYPEAHEAD_SQL . '=' . $sql; + $formElement[FE_TYPEAHEAD_SQL_PREFETCH] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_SQL_PREFETCH); + + $arr = [ + FE_TYPEAHEAD_SQL => $sql, + FE_TYPEAHEAD_SQL_PREFETCH => $formElement[FE_TYPEAHEAD_SQL_PREFETCH] + ]; } elseif (isset($formElement[FE_TYPEAHEAD_LDAP])) { $formElement[FE_LDAP_SERVER] = Support::setIfNotSet($formElement, FE_LDAP_SERVER); $formElement[FE_LDAP_BASE_DN] = Support::setIfNotSet($formElement, FE_LDAP_BASE_DN); @@ -1238,11 +1242,9 @@ abstract class AbstractBuildForm { $arr[SYSTEM_LDAP_1_PASSWORD] = $this->store->getVar(SYSTEM_LDAP_1_PASSWORD, STORE_SYSTEM); } - $urlParam = OnArray::toString($arr); - } - return $urlParam; + return OnArray::toString($arr); } /** diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php index 51b4023f94e09306c266e2f6e62f79562dade6c0..d8b6f8b1b016a7a710d4d26459b75e7b60d57457 100644 --- a/extension/qfq/qfq/Constants.php +++ b/extension/qfq/qfq/Constants.php @@ -233,11 +233,12 @@ const ERROR_UPLOAD_GET_MIME_TYPE = 1503; const ERROR_UPLOAD_UNKNOWN_ACTION = 1504; const ERROR_NO_TARGET_PATH_FILE_NAME = 1505; -// LDAP +// LDAP / typeahead const ERROR_LDAP_CONNECT = 1600; const ERROR_MISSING_TYPE_AHEAD_LDAP_SEARCH = 1601; const ERROR_MISSING_TYPE_AHEAD_LDAP_SEARCH_PREFETCH = 1602; const ERROR_LDAP_BIND = 1603; +const ERROR_MISSING_TYPE_AHEAD_SQL_PREFETCH = 1604; // Download const ERROR_DOWNLOAD_CREATE_NEW_FILE = 1700; @@ -951,6 +952,7 @@ const FE_TYPEAHEAD_LIMIT = F_TYPEAHEAD_LIMIT; const FE_TYPEAHEAD_MINLENGTH = F_TYPEAHEAD_MINLENGTH; const FE_TYPEAHEAD_PEDANTIC = F_TYPEAHEAD_PEDANTIC; const FE_TYPEAHEAD_SQL = 'typeAheadSql'; +const FE_TYPEAHEAD_SQL_PREFETCH = 'typeAheadSqlPrefetch'; const FE_TYPEAHEAD_LDAP_VALUE_PRINTF = F_TYPEAHEAD_LDAP_VALUE_PRINTF; const FE_TYPEAHEAD_LDAP_ID_PRINTF = F_TYPEAHEAD_LDAP_ID_PRINTF; const FE_TYPEAHEAD_LDAP = 'typeAheadLdap'; diff --git a/extension/qfq/qfq/form/TypeAhead.php b/extension/qfq/qfq/form/TypeAhead.php index 601fcaa1c0d4bc069561c42f59331d82ce89bff5..39fd8c2494e05f20158bba03807d2c47ecab6294 100644 --- a/extension/qfq/qfq/form/TypeAhead.php +++ b/extension/qfq/qfq/form/TypeAhead.php @@ -61,14 +61,17 @@ class TypeAhead { public function process() { $arr = array(); - $values = array(); $sipClass = new Sip(); $sipVars = $sipClass->getVarsFromSip($this->vars[TYPEAHEAD_API_SIP]); if (isset($sipVars[FE_TYPEAHEAD_SQL])) { - $arr = $this->typeAheadSql($sipVars, $this->vars[TYPEAHEAD_API_QUERY]); + if($this->vars[TYPEAHEAD_API_PREFETCH] == '') { + $arr = $this->typeAheadSql($sipVars, $this->vars[TYPEAHEAD_API_QUERY]); + } else { + $arr = $this->typeAheadSqlPrefetch($sipVars, $this->vars[TYPEAHEAD_API_PREFETCH]); + } } elseif (isset($sipVars[FE_LDAP_SERVER])) { $ldap = new Ldap(); @@ -87,7 +90,7 @@ class TypeAhead { } /** - * Do a wildcard serach on the prepared statement $config[FE_TYPEAHEAD_SQL]. + * Do a wildcard search on the prepared statement $config[FE_TYPEAHEAD_SQL]. * All '?' will be replaced by '%$value%'. * If there is no 'LIMIT x' defined, append it. * Returns an dict array [ API_TYPEAHEAD_KEY => key, API_TYPEAHEAD_VALUE => value ] @@ -126,6 +129,44 @@ class TypeAhead { return $this->db->makeArrayDict($arr, TYPEAHEAD_SQL_KEY_NAME, API_TYPEAHEAD_VALUE, API_TYPEAHEAD_KEY, API_TYPEAHEAD_VALUE); } + /** + * Returns a dict array [ API_TYPEAHEAD_KEY => key, API_TYPEAHEAD_VALUE => value ] with the prefetch result + * + * @param array $config + * @param string $key + * + * @return array + * @throws UserFormException + */ + + private function typeAheadSqlPrefetch(array $config, $key) { + $keys = array(); + + $sql = $config[FE_TYPEAHEAD_SQL_PREFETCH]; + if ($config[FE_TYPEAHEAD_SQL_PREFETCH] == '') { + throw new UserFormException("Missing definition for `" . FE_TYPEAHEAD_SQL_PREFETCH . "`", ERROR_MISSING_TYPE_AHEAD_SQL_PREFETCH); + } + $cnt = substr_count($sql, '?'); + if ($cnt == 0) { + throw new UserFormException("Missing at least one '?' in " . FE_TYPEAHEAD_SQL_PREFETCH); + } + + for ($ii = 0; $ii < $cnt; $ii++) { + $keys[] = $key; + } + + $arr = $this->db->sql($sql, ROW_REGULAR, $keys); + if ($arr == false || count($arr) == 0) { + return array(); + } + + // return first result as key-value pair (concatenate columns) + $value = ''; + foreach($arr[0] AS $name => $column) { + $value .= $column; + } + return [ [ API_TYPEAHEAD_KEY => $key, API_TYPEAHEAD_VALUE => $value ] ]; + } } \ No newline at end of file diff --git a/extension/qfq/qfq/helper/OnArray.php b/extension/qfq/qfq/helper/OnArray.php index f7792bf1f95988389b713785f2d724c8ac7170c2..e58cf337308ebc7b75eead2c454e8ba95533211e 100644 --- a/extension/qfq/qfq/helper/OnArray.php +++ b/extension/qfq/qfq/helper/OnArray.php @@ -34,6 +34,10 @@ class OnArray { * @return string */ public static function toString(array $dataArray, $keyValueGlue = '=', $rowGlue = '&', $encloseValue = '') { + if (count($dataArray) === 0) { + return ''; + } + $dataString = ''; foreach ($dataArray as $key => $value) {